blob: ea7d200b51bd0b95f4842438dd01ac109e65a88a [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcida04f4a2015-05-21 12:54:09 +020013 */
14
Radek Krejci812b10a2015-05-28 16:48:25 +020015#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020016#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020017#include <errno.h>
18#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020019#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020020#include <stdlib.h>
21#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020022#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020023#include <sys/types.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020024
Radek Krejci998a0b82015-08-17 13:14:36 +020025#include "libyang.h"
26#include "common.h"
27#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020028#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020029#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020030#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020031#include "resolve.h"
32#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020033#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020034
Radek Krejciadb57612016-02-16 13:34:34 +010035#define GETVAL(value, node, arg) \
36 value = lyxml_get_attr(node, arg, NULL); \
37 if (!value) { \
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(LYE_MISSARG, LY_VLOG_NONE, NULL, arg, node->name); \
Radek Krejciadb57612016-02-16 13:34:34 +010039 goto error; \
Michal Vasko2d710f32016-02-05 12:29:21 +010040 }
Radek Krejcice7fb782015-05-29 16:52:34 +020041
Radek Krejcic6556022016-01-27 15:16:45 +010042/* parser.c */
43int dup_prefix_check(const char *prefix, struct lys_module *module);
44
Radek Krejcib388c152015-06-04 17:03:03 +020045#define OPT_IDENT 0x01
46#define OPT_CONFIG 0x02
47#define OPT_MODULE 0x04
48#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020049#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020050static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020051
Radek Krejcib8048692015-08-05 13:36:34 +020052static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020053 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020054static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020055 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020056static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020057 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020058static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020059 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020060static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020061 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020063 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020064static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020065 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020066static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Radek Krejci3440cc52016-06-23 17:03:59 +020067 struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020068static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020069 int resolve, struct unres_schema *unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +020070static struct lys_node *read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
71 int resolve, struct unres_schema *unres);
Michal Vaskof02e3742015-08-05 16:27:02 +020072static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020073
Michal Vasko0d343d12015-08-24 14:57:36 +020074/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020075static const char *
76read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020077{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020078 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020080 /* there should be <text> child */
81 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
Radek Krejci218436d2016-02-10 12:54:06 +010082 LOGERR(LY_EVALID, "Expected \"%s\" element in \"%s\" element.", name, node->name);
Radek Krejci48464ed2016-03-17 15:44:09 +010083 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, node->name);
Radek Krejci218436d2016-02-10 12:54:06 +010084 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020085 } else if (node->child->content) {
86 len = strlen(node->child->content);
87 return lydict_insert(ctx, node->child->content, len);
Radek Krejci218436d2016-02-10 12:54:06 +010088 } else {
89 return lydict_insert(ctx, "", 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090 }
Radek Krejcida04f4a2015-05-21 12:54:09 +020091}
92
Michal Vasko0d343d12015-08-24 14:57:36 +020093/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094static int
Radek Krejci9ff0a922016-07-14 13:08:05 +020095fill_yin_iffeature(struct lys_node *parent, struct lyxml_elem *yin, struct lys_iffeature *iffeat, struct unres_schema *unres)
Michal Vasko1d337e12016-02-15 12:32:04 +010096{
97 int r;
98 const char *value;
99
100 GETVAL(value, yin, "name");
Michal Vasko97b32be2016-07-25 10:59:53 +0200101
102 if ((lys_node_module(parent)->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
103 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
Radek Krejci9ff0a922016-07-14 13:08:05 +0200104error:
Michal Vasko1d337e12016-02-15 12:32:04 +0100105 return EXIT_FAILURE;
106 }
107
Michal Vasko97b32be2016-07-25 10:59:53 +0200108 if (!(value = transform_schema2json(parent->module, value))) {
109 return EXIT_FAILURE;
110 }
111
Radek Krejci9ff0a922016-07-14 13:08:05 +0200112 r = resolve_iffeature_compile(iffeat, value, parent, unres);
113 lydict_remove(parent->module->ctx, value);
114 if (r) {
115 return EXIT_FAILURE;
Michal Vasko1d337e12016-02-15 12:32:04 +0100116 }
117
Radek Krejci9ff0a922016-07-14 13:08:05 +0200118 return EXIT_SUCCESS;
Michal Vasko1d337e12016-02-15 12:32:04 +0100119}
120
121/* logs directly */
122static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200123fill_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 +0200124{
Radek Krejci73adb602015-07-02 18:07:40 +0200125 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200126 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100127 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200128
Michal Vasko4cfcd252015-08-03 14:31:10 +0200129 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100130 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200131
Radek Krejci76512572015-08-04 09:47:08 +0200132 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200133 return EXIT_FAILURE;
134 }
Radek Krejci04581c62015-05-22 21:24:00 +0200135
Pavol Vicand6cda452016-07-13 15:08:29 +0200136 if (dup_identities_check(ident->name, module)) {
137 return EXIT_FAILURE;
138 }
139
Radek Krejci73adb602015-07-02 18:07:40 +0200140 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200141 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
142 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200143 continue;
144 }
145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200146 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100147 if (base_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100148 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200149 return EXIT_FAILURE;
150 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100151 base_flag = 1;
152
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200153 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100154 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100155 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200156 return EXIT_FAILURE;
157 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100158
Radek Krejci48464ed2016-03-17 15:44:09 +0100159 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100160 lydict_remove(module->ctx, value);
161 return EXIT_FAILURE;
162 }
163 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200164 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100165 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200166 return EXIT_FAILURE;
167 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200168 }
Radek Krejci04581c62015-05-22 21:24:00 +0200169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200170 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200171
172error:
173 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200174}
175
Michal Vasko0d343d12015-08-24 14:57:36 +0200176/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200177static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200178read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200179{
Radek Krejci73adb602015-07-02 18:07:40 +0200180 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200181 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200182
Radek Krejci73adb602015-07-02 18:07:40 +0200183 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200184 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
185 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200186 continue;
187 }
188
Radek Krejci41726f92015-06-19 13:11:05 +0200189 if (!strcmp(child->name, "description")) {
190 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100191 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200192 return EXIT_FAILURE;
193 }
194 restr->dsc = read_yin_subnode(ctx, child, "text");
195 if (!restr->dsc) {
196 return EXIT_FAILURE;
197 }
198 } else if (!strcmp(child->name, "reference")) {
199 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100200 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200201 return EXIT_FAILURE;
202 }
203 restr->ref = read_yin_subnode(ctx, child, "text");
204 if (!restr->ref) {
205 return EXIT_FAILURE;
206 }
207 } else if (!strcmp(child->name, "error-app-tag")) {
208 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100209 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200210 return EXIT_FAILURE;
211 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200212 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200213 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200214 } else if (!strcmp(child->name, "error-message")) {
215 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100216 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200217 return EXIT_FAILURE;
218 }
219 restr->emsg = read_yin_subnode(ctx, child, "value");
220 if (!restr->emsg) {
221 return EXIT_FAILURE;
222 }
223 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100224 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200225 return EXIT_FAILURE;
226 }
Radek Krejci41726f92015-06-19 13:11:05 +0200227 }
228
229 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200230
231error:
232 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200233}
234
Michal Vasko88c29542015-11-27 14:57:53 +0100235/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
236int
Radek Krejcib8048692015-08-05 13:36:34 +0200237fill_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 +0200238 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200239{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200240 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200241 struct lys_node *siter;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200242 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200243 struct lys_restr **restr;
Radek Krejcie663e012016-08-01 17:12:34 +0200244 struct lys_type_bit bit, *bits_sc;
245 struct lys_type_enum *enms_sc; /* shortcut */
246 struct lys_type *dertype;
Radek Krejcifc8d8322016-06-24 11:23:23 +0200247 int i, j, rc, val_set;
Radek Krejcidc008d72016-02-17 13:12:14 +0100248 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200249 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200250 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200251
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200252 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100253 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200254 if (!value) {
255 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200256 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200257
258 i = parse_identifier(value);
259 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100260 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100261 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200262 goto error;
263 }
264 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100265 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200266 if (value[i]) {
267 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100268 name += i;
269 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100270 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100271 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200272 goto error;
273 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200274 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100275 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200276 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200277
Radek Krejci225376f2016-02-16 17:36:22 +0100278 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200279 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100280 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200281 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200282 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100283
284 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200285 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200286 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200287 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100288 ret = EXIT_FAILURE;
289 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200290 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200291 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200293
Radek Krejcicf509982015-12-15 09:22:44 +0100294 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100295 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100296 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100297 return -1;
298 }
299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200300 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200301 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200302 /* RFC 6020 9.7.4 - bit */
303
304 /* get bit specifications, at least one must be present */
305 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200306 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
307 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100308 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200309 continue;
310 }
311
Radek Krejci994b6f62015-06-18 16:47:27 +0200312 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200313 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200314 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100315 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200316 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200317 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200318 }
319 }
Radek Krejcie663e012016-08-01 17:12:34 +0200320 dertype = &type->der->type;
321 if (!dertype->der) {
322 if (!type->info.bits.count) {
323 /* type is derived directly from buit-in bits type and bit statement is required */
324 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
325 goto error;
326 }
327 } else {
328 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
329 if (module->version < 2 && type->info.bits.count) {
330 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
331 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
332 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200333 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200334 goto error;
335 }
Radek Krejciac781922015-07-09 15:35:14 +0200336 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200337
338 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100339 if (!type->info.bits.bit) {
340 LOGMEM;
341 goto error;
342 }
Radek Krejci73adb602015-07-02 18:07:40 +0200343 p = 0;
344 i = -1;
345 LY_TREE_FOR(yin->child, next) {
346 i++;
347
348 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100349 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100350 goto error;
351 }
352
Radek Krejci994b6f62015-06-18 16:47:27 +0200353 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200354 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200355 type->info.bits.count = i + 1;
356 goto error;
357 }
358
Radek Krejcie663e012016-08-01 17:12:34 +0200359 if (!dertype->der) { /* directly derived type from bits built-in type */
360 /* check the name uniqueness */
361 for (j = 0; j < i; j++) {
362 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
363 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
364 type->info.bits.count = i + 1;
365 goto error;
366 }
367 }
368 } else {
369 /* restricted bits type - the name MUST be used in the base type */
370 bits_sc = dertype->info.bits.bit;
371 for (j = 0; j < dertype->info.bits.count; j++) {
372 if (ly_strequal(bits_sc[j].name, value, 1)) {
373 break;
374 }
375 }
376 if (j == dertype->info.bits.count) {
377 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200378 type->info.bits.count = i + 1;
379 goto error;
380 }
381 }
382
Radek Krejcie663e012016-08-01 17:12:34 +0200383
Radek Krejci0d70c372015-07-02 16:23:10 +0200384 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200385 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200386 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
387 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200388 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200389 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200390
Radek Krejci0d70c372015-07-02 16:23:10 +0200391 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200392 if (p_ != -1) {
393 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
394 type->info.bits.count = i + 1;
395 goto error;
396 }
397
Radek Krejci0d70c372015-07-02 16:23:10 +0200398 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200399 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200400
401 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200402 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100403 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200404 type->info.bits.count = i + 1;
405 goto error;
406 }
407 type->info.bits.bit[i].pos = (uint32_t)p_;
408
Radek Krejcie663e012016-08-01 17:12:34 +0200409 if (!dertype->der) { /* directly derived type from bits built-in type */
410 /* keep the highest enum value for automatic increment */
411 if (type->info.bits.bit[i].pos >= p) {
412 p = type->info.bits.bit[i].pos;
413 p++;
414 } else {
415 /* check that the value is unique */
416 for (j = 0; j < i; j++) {
417 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
418 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
419 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
420 type->info.bits.bit[j].name);
421 type->info.bits.count = i + 1;
422 goto error;
423 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200424 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200425 }
426 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200427 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100428 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200429 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200430 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200431 }
Radek Krejcie663e012016-08-01 17:12:34 +0200432
433 if (!dertype->der) { /* directly derived type from bits built-in type */
434 if (p_ == -1) {
435 /* assign value automatically */
436 if (p > UINT32_MAX) {
437 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
438 type->info.bits.count = i + 1;
439 goto error;
440 }
441 type->info.bits.bit[i].pos = (uint32_t)p;
442 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
443 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200444 }
Radek Krejcie663e012016-08-01 17:12:34 +0200445 } else { /* restricted bits type */
446 if (p_ == -1) {
447 /* automatically assign position from base type */
448 type->info.bits.bit[i].pos = bits_sc[j].pos;
449 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
450 } else {
451 /* check that the assigned position corresponds to the original
452 * position of the bit in the base type */
453 if (p_ != bits_sc[j].pos) {
454 /* p_ - assigned position in restricted bits
455 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
456 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200457 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200458 type->info.bits.count = i + 1;
459 goto error;
460 }
461 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200462 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200463
464 /* keep them ordered by position */
465 j = i;
466 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
467 /* switch them */
468 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
469 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
470 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
471 j--;
472 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200473 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200474 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200476 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200477 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200478 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200479 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
480 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200481 continue;
482 }
483
Radek Krejcif9401c32015-06-26 16:47:36 +0200484 if (!strcmp(node->name, "range")) {
485 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100486 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200487 goto error;
488 }
489
490 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200491 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100492 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200493 goto error;
494 }
495 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100496 if (!type->info.dec64.range) {
497 LOGMEM;
498 goto error;
499 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200500 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
501
502 /* get possible substatements */
503 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
504 goto error;
505 }
506 } else if (!strcmp(node->name, "fraction-digits")) {
507 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100508 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200509 goto error;
510 }
511 GETVAL(value, node, "value");
512 v = strtol(value, NULL, 10);
513
514 /* range check */
515 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100516 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200517 goto error;
518 }
519 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200520 type->info.dec64.div = 10;
521 for (i = 1; i < v; i++) {
522 type->info.dec64.div *= 10;
523 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200524 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100525 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200526 goto error;
527 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200528 }
529
530 /* mandatory sub-statement(s) check */
531 if (!type->info.dec64.dig && !type->der->type.der) {
532 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100533 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200534 goto error;
535 }
Radek Krejci7511f402015-07-10 09:56:30 +0200536 if (type->info.dec64.dig && type->der->type.der) {
537 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100538 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200539 goto error;
540 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200541 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200543 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200544 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200545
Radek Krejci994b6f62015-06-18 16:47:27 +0200546 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200548 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
549 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100550 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200551 continue;
552 }
553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200554 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200556 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100557 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200558 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200559 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200560 }
561 }
Radek Krejcie663e012016-08-01 17:12:34 +0200562 dertype = &type->der->type;
563 if (!dertype->der) {
564 if (!type->info.enums.count) {
565 /* type is derived directly from buit-in enumeartion type and enum statement is required */
566 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
567 goto error;
568 }
569 } else {
570 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
571 if (module->version < 2 && type->info.enums.count) {
572 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
573 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
574 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200575 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200576 goto error;
577 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200578 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200579
Radek Krejci1574a8d2015-08-03 14:16:52 +0200580 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100581 if (!type->info.enums.enm) {
582 LOGMEM;
583 goto error;
584 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200585
Radek Krejcie663e012016-08-01 17:12:34 +0200586 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200587 i = -1;
588 LY_TREE_FOR(yin->child, next) {
589 i++;
590
591 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100592 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100593 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
594 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100595 goto error;
596 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200597 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200598 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200599 type->info.enums.count = i + 1;
600 goto error;
601 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200603 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200604 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100606 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200607 type->info.enums.count = i + 1;
608 goto error;
609 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200610
Radek Krejcie663e012016-08-01 17:12:34 +0200611 if (!dertype->der) { /* directly derived type from enumeration built-in type */
612 /* check the name uniqueness */
613 for (j = 0; j < i; j++) {
614 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
615 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
616 type->info.enums.count = i + 1;
617 goto error;
618 }
619 }
620 } else {
621 /* restricted enumeration type - the name MUST be used in the base type */
622 enms_sc = dertype->info.enums.enm;
623 for (j = 0; j < dertype->info.enums.count; j++) {
624 if (ly_strequal(enms_sc[j].name, value, 1)) {
625 break;
626 }
627 }
628 if (j == dertype->info.enums.count) {
629 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200630 type->info.enums.count = i + 1;
631 goto error;
632 }
633 }
Radek Krejci04581c62015-05-22 21:24:00 +0200634
Radek Krejcie663e012016-08-01 17:12:34 +0200635 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200636 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200637 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
638 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200639 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641
Radek Krejci0d70c372015-07-02 16:23:10 +0200642 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200643 if (val_set) {
644 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
645 type->info.enums.count = i + 1;
646 goto error;
647 }
648
Radek Krejci0d70c372015-07-02 16:23:10 +0200649 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200650 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200651
652 /* range check */
653 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100654 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200655 type->info.enums.count = i + 1;
656 goto error;
657 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200658 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200659
Radek Krejcie663e012016-08-01 17:12:34 +0200660 if (!dertype->der) { /* directly derived type from enumeration built-in type */
661 /* keep the highest enum value for automatic increment */
662 if (type->info.enums.enm[i].value > v) {
663 v = type->info.enums.enm[i].value;
664 v++;
665 } else {
666 /* check that the value is unique */
667 for (j = 0; j < i; j++) {
668 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
669 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
670 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
671 type->info.enums.enm[j].name);
672 type->info.enums.count = i + 1;
673 goto error;
674 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200675 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 }
677 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200678 val_set = 1;
Radek Krejci0d70c372015-07-02 16:23:10 +0200679 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100680 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200681 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200683 }
Radek Krejcie663e012016-08-01 17:12:34 +0200684
685 if (!dertype->der) { /* directly derived type from enumeration */
686 if (!val_set) {
687 /* assign value automatically */
688 if (v > INT32_MAX) {
689 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
690 type->info.enums.count = i + 1;
691 goto error;
692 }
693 type->info.enums.enm[i].value = v;
694 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
695 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696 }
Radek Krejcie663e012016-08-01 17:12:34 +0200697 } else { /* restricted enum type */
698 if (!val_set) {
699 /* automatically assign value from base type */
700 type->info.enums.enm[i].value = enms_sc[j].value;
701 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
702 } else {
703 /* check that the assigned value corresponds to the original
704 * value of the enum in the base type */
705 if (v_ != enms_sc[j].value) {
706 /* v_ - assigned value in restricted enum
707 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
708 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200709 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200710 type->info.enums.count = i + 1;
711 goto error;
712 }
713 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200714 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200715 }
716 break;
717
718 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200719 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200720
721 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200722 LY_TREE_FOR_SAFE(yin->child, next, node) {
723 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
724 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100725 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200726 continue;
727 }
728
Michal Vaskoe29c6622015-11-27 15:02:31 +0100729 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100730 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200731 goto error;
732 }
733 }
734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200735 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200736 if (type->der->type.der) {
737 /* this is just a derived type with no base specified/required */
738 break;
739 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100740 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 goto error;
742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100744 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200745 goto error;
746 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200747 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100748 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100749 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100750 if (!value) {
751 goto error;
752 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100753 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100754 lydict_remove(module->ctx, value);
755
756 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200757 goto error;
758 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200759 break;
760
761 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200762 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200763 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200764 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
765 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200766 continue;
767 }
768
Radek Krejciaf351422015-06-19 14:49:38 +0200769 if (!strcmp(node->name, "require-instance")) {
770 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100771 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200772 goto error;
773 }
774 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200775 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200776 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200777 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200778 type->info.inst.req = -1;
779 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100780 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200781 goto error;
782 }
783 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100784 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200785 goto error;
786 }
Radek Krejciaf351422015-06-19 14:49:38 +0200787 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 break;
790
Radek Krejcif2860132015-06-20 12:37:20 +0200791 case LY_TYPE_BINARY:
792 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200793 case LY_TYPE_INT8:
794 case LY_TYPE_INT16:
795 case LY_TYPE_INT32:
796 case LY_TYPE_INT64:
797 case LY_TYPE_UINT8:
798 case LY_TYPE_UINT16:
799 case LY_TYPE_UINT32:
800 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200801 /* RFC 6020 9.2.4 - range */
802
803 /* length and range are actually the same restriction, so process
804 * them by this common code, we just need to differ the name and
805 * structure where the information will be stored
806 */
807 if (type->base == LY_TYPE_BINARY) {
808 restr = &type->info.binary.length;
809 name = "length";
810 } else {
811 restr = &type->info.num.range;
812 name = "range";
813 }
814
Radek Krejci73adb602015-07-02 18:07:40 +0200815 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200816 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
817 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200818 continue;
819 }
820
Radek Krejcif2860132015-06-20 12:37:20 +0200821 if (!strcmp(node->name, name)) {
822 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100823 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200824 goto error;
825 }
826
827 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200828 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100829 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200830 goto error;
831 }
832 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100833 if (!(*restr)) {
834 LOGMEM;
835 goto error;
836 }
Radek Krejcif2860132015-06-20 12:37:20 +0200837 (*restr)->expr = lydict_insert(module->ctx, value, 0);
838
839 /* get possible substatements */
840 if (read_restr_substmt(module->ctx, *restr, node)) {
841 goto error;
842 }
843 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100844 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200845 goto error;
846 }
Radek Krejcif2860132015-06-20 12:37:20 +0200847 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200848 break;
849
850 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200851 /* flag resolving for later use */
852 if (!tpdftype) {
853 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
854 if (siter) {
855 /* just a flag - do not resolve */
856 tpdftype = 1;
857 }
858 }
859
Radek Krejcidc4c1412015-06-19 15:39:54 +0200860 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200861 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200862 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
863 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200864 continue;
865 }
866
Michal Vasko88c29542015-11-27 14:57:53 +0100867 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200868 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100869 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200870 goto error;
871 }
872
873 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200874 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100875 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200876 if (!type->info.lref.path) {
877 goto error;
878 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200879
880 /* try to resolve leafref path only when this is instantiated
881 * leaf, so it is not:
882 * - typedef's type,
883 * - in grouping definition,
884 * - just instantiated in a grouping definition,
885 * because in those cases the nodes referenced in path might not be present
886 * and it is not a bug. */
887 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200888 goto error;
889 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200890
Radek Krejcidc4c1412015-06-19 15:39:54 +0200891 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100892 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200893 goto error;
894 }
Radek Krejci73adb602015-07-02 18:07:40 +0200895 }
896
Radek Krejci742be352016-07-17 12:18:54 +0200897 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200898 if (!type->der->type.der) {
899 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +0200900 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200901 } else {
902 /* copy leafref definition into the derived type */
903 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
904 /* and resolve the path at the place we are (if not in grouping/typedef) */
905 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
906 goto error;
907 }
908
909 /* add pointer to leafref target, only on leaves (not in typedefs) */
910 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
911 goto error;
912 }
Michal Vasko01c6fd22016-05-20 11:43:05 +0200913 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200914 }
Radek Krejci742be352016-07-17 12:18:54 +0200915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916 break;
917
918 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200919 /* RFC 6020 9.4.4 - length */
920 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200921 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200922 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200923 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
924 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100925 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200926 continue;
927 }
928
Radek Krejci3733a802015-06-19 13:43:21 +0200929 if (!strcmp(node->name, "length")) {
930 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100931 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200932 goto error;
933 }
934
935 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200936 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100937 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200938 goto error;
939 }
940 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100941 if (!type->info.str.length) {
942 LOGMEM;
943 goto error;
944 }
Radek Krejci3733a802015-06-19 13:43:21 +0200945 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
946
Radek Krejci5fbc9162015-06-19 14:11:11 +0200947 /* get possible sub-statements */
948 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200949 goto error;
950 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100951 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200952 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200953 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200954 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100955 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200956 goto error;
957 }
958 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200959 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200960 if (i) {
961 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100962 if (!type->info.str.patterns) {
963 LOGMEM;
964 goto error;
965 }
Radek Krejci73adb602015-07-02 18:07:40 +0200966 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100967 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200968
Michal Vasko0aee5c12016-06-17 14:27:26 +0200969 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +0200970 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +0200971 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +0200972 goto error;
973 }
Michal Vasko69068852015-07-13 14:34:31 +0200974
Radek Krejci73adb602015-07-02 18:07:40 +0200975 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200976
977 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100978 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200979 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200980 goto error;
981 }
Radek Krejci73adb602015-07-02 18:07:40 +0200982 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200983 }
984 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 break;
986
987 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200988 /* RFC 6020 7.4 - type */
989 /* count number of types in union */
990 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 LY_TREE_FOR_SAFE(yin->child, next, node) {
992 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
993 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100994 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200995 continue;
996 }
997
Radek Krejcie4c366b2015-07-02 10:11:31 +0200998 if (!strcmp(node->name, "type")) {
999 i++;
1000 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001001 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001002 goto error;
1003 }
1004 }
1005
1006 if (!i) {
1007 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +01001008 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +02001009 break;
1010 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001011 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001012 goto error;
1013 }
1014
1015 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001016 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001017 if (!type->info.uni.types) {
1018 LOGMEM;
1019 goto error;
1020 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001021 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001022 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001023 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001024 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001025 if (!rc) {
1026 type->info.uni.count++;
1027
1028 /* union's type cannot be empty or leafref */
1029 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001030 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +01001031 rc = -1;
1032 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001033 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +01001034 rc = -1;
1035 }
1036 }
1037 if (rc) {
1038 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1039 for (i = 0; i < type->info.uni.count; ++i) {
1040 lys_type_free(module->ctx, &type->info.uni.types[i]);
1041 }
1042 free(type->info.uni.types);
1043 type->info.uni.types = NULL;
1044 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001045 type->der = NULL;
1046 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001047
1048 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001049 ret = EXIT_FAILURE;
1050 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +01001051 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001052 goto error;
1053 }
Michal Vasko88c29542015-11-27 14:57:53 +01001054 }
1055 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001056
Michal Vasko88c29542015-11-27 14:57:53 +01001057 case LY_TYPE_BOOL:
1058 case LY_TYPE_EMPTY:
1059 /* no sub-statement allowed */
1060 LY_TREE_FOR(yin->child, node) {
1061 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001062 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001063 goto error;
1064 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001065 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001066 break;
1067
1068 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001069 LOGINT;
1070 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 }
1072
1073 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001074
1075error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001076 if (type->module_name) {
1077 lydict_remove(module->ctx, type->module_name);
1078 type->module_name = NULL;
1079 }
1080 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001081}
1082
Michal Vasko0d343d12015-08-24 14:57:36 +02001083/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001085fill_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 +02001086{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001087 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001088 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001089 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001091 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001092 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001093 goto error;
1094 }
1095 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001097 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001098 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001099 goto error;
1100 }
Radek Krejcieac35532015-05-31 19:09:15 +02001101
Michal Vasko88c29542015-11-27 14:57:53 +01001102 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001103 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1104 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001105 continue;
1106 }
1107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001108 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001109 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001110 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001111 goto error;
1112 }
Michal Vasko88c29542015-11-27 14:57:53 +01001113 /* HACK for unres */
1114 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001115 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001116 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001117 goto error;
1118 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001119 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 } else if (!strcmp(node->name, "default")) {
1121 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001123 goto error;
1124 }
1125 GETVAL(value, node, "value");
1126 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1127 } else if (!strcmp(node->name, "units")) {
1128 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001129 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001130 goto error;
1131 }
1132 GETVAL(value, node, "name");
1133 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1134 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001135 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 goto error;
1137 }
1138 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001141 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001142 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001143 goto error;
1144 }
Radek Krejcieac35532015-05-31 19:09:15 +02001145
Michal Vasko478c4652016-07-21 12:55:01 +02001146 /* check default value (if not defined, there still could be some restrictions
1147 * that need to be checked against a default value from a derived type) */
1148 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1149 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001152 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001153
1154error:
1155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001156 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001157}
1158
Michal Vasko0d343d12015-08-24 14:57:36 +02001159/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001160static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001161fill_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 +02001162{
1163 const char *value;
1164 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001165 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001166
Radek Krejcib05774c2015-06-18 13:52:59 +02001167 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001168 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001169 goto error;
1170 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001171 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001172 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001173
Radek Krejci76512572015-08-04 09:47:08 +02001174 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001175 goto error;
1176 }
1177
1178 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001179 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1180 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001181 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001182 continue;
1183 }
1184
Radek Krejci3cf9e222015-06-18 11:37:50 +02001185 if (!strcmp(child->name, "if-feature")) {
1186 c++;
1187 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001188 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001189 goto error;
1190 }
1191 }
1192
1193 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001194 f->iffeature = calloc(c, sizeof *f->iffeature);
1195 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001196 LOGMEM;
1197 goto error;
1198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001199 }
Radek Krejci73adb602015-07-02 18:07:40 +02001200 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001201 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1202 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001203 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001204 goto error;
1205 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001206 }
1207
Radek Krejcic79c6b12016-07-26 15:11:49 +02001208 /* check for circular dependencies */
1209 if (f->iffeature_size) {
1210 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1211 goto error;
1212 }
1213 }
1214
Radek Krejci3cf9e222015-06-18 11:37:50 +02001215 return EXIT_SUCCESS;
1216
1217error:
1218
1219 return EXIT_FAILURE;
1220}
1221
Michal Vasko0d343d12015-08-24 14:57:36 +02001222/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001223static int
Radek Krejcib8048692015-08-05 13:36:34 +02001224fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001225{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001226 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001228 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001229 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001230 if (!must->expr) {
1231 goto error;
1232 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001233 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001234 goto error;
1235 }
Radek Krejci800af702015-06-02 13:46:01 +02001236
Radek Krejci41726f92015-06-19 13:11:05 +02001237 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001238
Michal Vasko77dc5652016-02-15 12:32:42 +01001239error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001240 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001241}
1242
Radek Krejci581ce772015-11-10 17:22:40 +01001243static int
Michal Vasko88c29542015-11-27 14:57:53 +01001244fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1245 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001246{
1247 int i, j;
1248 const char *value, *vaux;
1249
1250 /* get unique value (list of leafs supposed to be unique */
1251 GETVAL(value, yin, "tag");
1252
1253 /* count the number of unique leafs in the value */
1254 vaux = value;
1255 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001256 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001257 while (isspace(*vaux)) {
1258 vaux++;
1259 }
1260 }
1261 unique->expr_size++;
1262 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001263 if (!unique->expr) {
1264 LOGMEM;
1265 goto error;
1266 }
Radek Krejci581ce772015-11-10 17:22:40 +01001267
1268 for (i = 0; i < unique->expr_size; i++) {
1269 vaux = strpbrk(value, " \t\n");
1270 if (!vaux) {
1271 /* the last token, lydict_insert() will count its size on its own */
1272 vaux = value;
1273 }
1274
1275 /* store token into unique structure */
1276 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1277
1278 /* check that the expression does not repeat */
1279 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001280 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001281 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1282 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001283 goto error;
1284 }
1285 }
1286
1287 /* try to resolve leaf */
1288 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001289 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1290 goto error;
1291 }
Radek Krejci581ce772015-11-10 17:22:40 +01001292 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001293 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001294 goto error;
1295 }
1296 }
1297
1298 /* move to next token */
1299 value = vaux;
1300 while(isspace(*value)) {
1301 value++;
1302 }
1303 }
1304
1305 return EXIT_SUCCESS;
1306
1307error:
1308 return EXIT_FAILURE;
1309}
1310
Michal Vasko0d343d12015-08-24 14:57:36 +02001311/* logs directly
1312 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001313 * type: 0 - min, 1 - max
1314 */
1315static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001316deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001317{
1318 const char *value;
1319 char *endptr;
1320 unsigned long val;
1321 uint32_t *ui32val;
1322
Michal Vaskof7e57d52016-03-07 11:31:09 +01001323 /* del min/max is forbidden */
1324 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001325 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001326 goto error;
1327 }
1328
Radek Krejcieb00f512015-07-01 16:44:58 +02001329 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001330 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001331 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001332 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001333 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001334 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001335 }
Radek Krejci76512572015-08-04 09:47:08 +02001336 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001337 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001338 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001340 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001341 }
1342 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001343 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1344 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001345 goto error;
1346 }
1347
1348 GETVAL(value, node, "value");
1349 while (isspace(value[0])) {
1350 value++;
1351 }
1352
Radek Krejci0d7b2472016-02-12 11:11:03 +01001353 if (type && !strcmp(value, "unbounded")) {
1354 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001355 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001356 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001357 /* convert it to uint32_t */
1358 errno = 0;
1359 endptr = NULL;
1360 val = strtoul(value, &endptr, 10);
1361 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001362 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001363 goto error;
1364 }
1365 if (type) {
1366 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001367 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001368 } else {
1369 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001370 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001371 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001372 }
1373
1374 if (d->mod == LY_DEVIATE_ADD) {
1375 /* check that there is no current value */
1376 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001377 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1378 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001379 goto error;
1380 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001381 } else if (d->mod == LY_DEVIATE_RPL) {
1382 /* unfortunately, there is no way to check reliably that there
1383 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001384 }
1385
Michal Vaskof7e57d52016-03-07 11:31:09 +01001386 /* add (already checked) and replace */
1387 /* set new value specified in deviation */
1388 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001389
1390 return EXIT_SUCCESS;
1391
1392error:
1393
1394 return EXIT_FAILURE;
1395}
1396
Michal Vasko0d343d12015-08-24 14:57:36 +02001397/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001398static int
Michal Vasko88c29542015-11-27 14:57:53 +01001399fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1400 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001401{
1402 const char *value, **stritem;
1403 struct lyxml_elem *next, *child, *develem;
1404 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001405 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001406 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001407 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001408 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001409 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001410 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001411 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001412 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001413 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001414 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001415 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001416 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001417
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001418 ctx = module->ctx;
1419
Radek Krejcieb00f512015-07-01 16:44:58 +02001420 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001421 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001422 if (!dev->target_name) {
1423 goto error;
1424 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001425
1426 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001427 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1428 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001429 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001430 goto error;
1431 }
Radek Krejcic4283442016-04-22 09:19:27 +02001432 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001433 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1434 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 goto error;
1436 }
Michal Vasko89563fc2016-07-28 16:19:35 +02001437 lys_node_module(dev_target)->deviated = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001438
1439 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001440 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1441 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001442 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001443 continue;
1444 }
1445
Radek Krejcieb00f512015-07-01 16:44:58 +02001446 if (!strcmp(child->name, "description")) {
1447 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001448 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001449 goto error;
1450 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001451 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001452 if (!dev->dsc) {
1453 goto error;
1454 }
1455 } else if (!strcmp(child->name, "reference")) {
1456 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001457 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001458 goto error;
1459 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001460 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001461 if (!dev->ref) {
1462 goto error;
1463 }
1464 } else if (!strcmp(child->name, "deviate")) {
1465 c_dev++;
1466
Michal Vasko345da0a2015-12-02 10:35:55 +01001467 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001468 * further processed later
1469 */
1470 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001471
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001473 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001474 goto error;
1475 }
1476
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001477 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 }
1479
1480 if (c_dev) {
1481 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001482 if (!dev->deviate) {
1483 LOGMEM;
1484 goto error;
1485 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 }
1487
1488 LY_TREE_FOR(yin->child, develem) {
1489 /* init */
1490 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001491 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001492 c_must = 0;
1493 c_uniq = 0;
1494
1495 /* get deviation type */
1496 GETVAL(value, develem, "value");
1497 if (!strcmp(value, "not-supported")) {
1498 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1499 /* no property expected in this case */
1500 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001501 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
1504
Radek Krejci5b917642015-07-02 09:03:13 +02001505 /* and neither any other deviate statement is expected,
1506 * not-supported deviation must be the only deviation of the target
1507 */
1508 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001509 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1510 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001511 goto error;
1512 }
1513
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001514 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001515 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1516 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1517 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001518 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1519 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001520 goto error;
1521 }
1522 }
1523 }
Radek Krejci5b917642015-07-02 09:03:13 +02001524
Michal Vaskoff006c12016-02-17 11:15:19 +01001525 /* unlink and store the original node */
1526 lys_node_unlink(dev_target);
1527 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001528
Radek Krejci5b917642015-07-02 09:03:13 +02001529 dev->deviate_size = 1;
1530 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001531 } else if (!strcmp(value, "add")) {
1532 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1533 } else if (!strcmp(value, "replace")) {
1534 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1535 } else if (!strcmp(value, "delete")) {
1536 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1537 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001538 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001539 goto error;
1540 }
1541 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001542 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001543
Michal Vaskoff006c12016-02-17 11:15:19 +01001544 /* store a shallow copy of the original node */
1545 if (!dev->orig_node) {
1546 memset(&tmp_unres, 0, sizeof tmp_unres);
1547 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1548 /* just to be safe */
1549 if (tmp_unres.count) {
1550 LOGINT;
1551 goto error;
1552 }
1553 }
1554
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 /* process deviation properties */
1556 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001557 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1558 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001559 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001560 continue;
1561 }
1562
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001564 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 goto error;
1567 }
1568
1569 /* for we deviate from RFC 6020 and allow config property even it is/is not
1570 * specified in the target explicitly since config property inherits. So we expect
1571 * that config is specified in every node. But for delete, we check that the value
1572 * is the same as here in deviation
1573 */
1574 GETVAL(value, child, "value");
1575 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001576 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001577 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001578 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001579 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001580 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001581 goto error;
1582 }
1583
1584 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001585 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001586 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001587 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001588 } else { /* add and replace are the same in this case */
1589 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001590 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001591
1592 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001593 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001594 }
1595 } else if (!strcmp(child->name, "default")) {
1596 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001597 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001598 goto error;
1599 }
1600 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001601 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001602
Michal Vasko60f4b452016-02-12 11:02:55 +01001603 if (dev_target->nodetype == LYS_CHOICE) {
1604 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001605
1606 if (d->mod == LY_DEVIATE_ADD) {
1607 /* check that there is no current value */
1608 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001609 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1610 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 goto error;
1612 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001613 /* check collision with mandatory */
1614 if (choice->flags & LYS_MAND_TRUE) {
1615 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1616 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1617 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1618 goto error;
1619 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001620 } else if (d->mod == LY_DEVIATE_RPL) {
1621 /* check that there was a value before */
1622 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001623 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1624 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001625 goto error;
1626 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001627 }
1628
Michal Vasko3edeaf72016-02-11 13:17:43 +01001629 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001630 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001631 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001632 goto error;
1633 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001634 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001635 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001636 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1637 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 goto error;
1639 }
1640 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001641 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 if (!choice->dflt) {
1643 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001644 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 }
1647 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001648 } else if (dev_target->nodetype == LYS_LEAF) {
1649 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650
1651 if (d->mod == LY_DEVIATE_ADD) {
1652 /* check that there is no current value */
1653 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1655 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001656 goto error;
1657 }
Radek Krejci841ec082016-04-05 13:05:17 +02001658 /* check collision with mandatory */
1659 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001660 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001661 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001662 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001663 goto error;
1664 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 }
1666
1667 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001668 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001669 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1670 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 goto error;
1672 }
1673 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001674 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001675 leaf->dflt = NULL;
1676 } else { /* add (already checked) and replace */
1677 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001678 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001679
1680 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001681 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001682
1683 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1684 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1685 if (!leaf_dflt_check) {
1686 LOGMEM;
1687 goto error;
1688 }
1689 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001690 }
1691 } else {
1692 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001693 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1694 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001695 goto error;
1696 }
1697 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001698 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001699 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 goto error;
1701 }
1702
1703 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001704 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001705 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1706 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001707 goto error;
1708 }
1709
1710 GETVAL(value, child, "value");
1711 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001712 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001714 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001715 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001716 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001717 goto error;
1718 }
1719
1720 if (d->mod == LY_DEVIATE_ADD) {
1721 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001722 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001723 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1724 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 goto error;
1726 }
Radek Krejci841ec082016-04-05 13:05:17 +02001727 /* check collision with default-stmt */
1728 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001729 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001730 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001731 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001732 goto error;
1733 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001734
Michal Vasko21be1b32016-03-07 12:31:34 +01001735 dev_target->flags |= d->flags & LYS_MAND_MASK;
1736 } else if (d->mod == LY_DEVIATE_RPL) {
1737 /* check that there was a value before */
1738 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001739 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1740 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 goto error;
1742 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001743
Michal Vasko21be1b32016-03-07 12:31:34 +01001744 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001745 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001746 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001747 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001748 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001749 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001750 }
1751 } else if (!strcmp(child->name, "min-elements")) {
1752 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001753 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001754 goto error;
1755 }
1756 f_min = 1;
1757
Michal Vasko60f4b452016-02-12 11:02:55 +01001758 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001759 goto error;
1760 }
1761 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001762 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001763 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001764 goto error;
1765 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001766 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001767
Michal Vasko60f4b452016-02-12 11:02:55 +01001768 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001769 goto error;
1770 }
1771 } else if (!strcmp(child->name, "must")) {
1772 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001773 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001774 continue;
1775 } else if (!strcmp(child->name, "type")) {
1776 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001777 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001778 goto error;
1779 }
1780
Michal Vaskof7e57d52016-03-07 11:31:09 +01001781 /* add, del type is forbidden */
1782 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001783 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001784 goto error;
1785 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001786 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001787 goto error;
1788 }
1789
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001791 if (dev_target->nodetype == LYS_LEAF) {
1792 t = &((struct lys_node_leaf *)dev_target)->type;
1793 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1794 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001796 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1797 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 goto error;
1799 }
1800
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001802 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001803 /* HACK for unres */
1804 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001805 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001806 goto error;
1807 }
1808 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001809
1810 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1811 if (dev_target->nodetype == LYS_LEAF) {
1812 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1813 if (!leaf_dflt_check) {
1814 LOGMEM;
1815 goto error;
1816 }
1817 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1818 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 } else if (!strcmp(child->name, "unique")) {
1820 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001821 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 continue;
1823 } else if (!strcmp(child->name, "units")) {
1824 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001825 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 goto error;
1827 }
1828
1829 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001830 if (dev_target->nodetype == LYS_LEAFLIST) {
1831 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1832 } else if (dev_target->nodetype == LYS_LEAF) {
1833 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001834 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001835 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1836 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001837 goto error;
1838 }
1839
1840 /* get units value */
1841 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001842 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001843
1844 /* apply to target */
1845 if (d->mod == LY_DEVIATE_ADD) {
1846 /* check that there is no current value */
1847 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001848 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1849 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001850 goto error;
1851 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001852
Michal Vasko21be1b32016-03-07 12:31:34 +01001853 *stritem = lydict_insert(ctx, value, 0);
1854 } else if (d->mod == LY_DEVIATE_RPL) {
1855 /* check that there was a value before */
1856 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001857 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1858 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001859 goto error;
1860 }
1861
1862 lydict_remove(ctx, *stritem);
1863 *stritem = lydict_insert(ctx, value, 0);
1864 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001865 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001866 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001867 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1868 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001869 goto error;
1870 }
1871 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001872 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001873 }
1874 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001875 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001876 goto error;
1877 }
1878
Michal Vasko88c29542015-11-27 14:57:53 +01001879 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001880 }
1881
1882 if (c_must) {
1883 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001884 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001885 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001886 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1887 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 break;
Radek Krejci76512572015-08-04 09:47:08 +02001889 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001890 trg_must = &((struct lys_node_container *)dev_target)->must;
1891 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001892 break;
Radek Krejci76512572015-08-04 09:47:08 +02001893 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001894 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1895 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001896 break;
Radek Krejci76512572015-08-04 09:47:08 +02001897 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001898 trg_must = &((struct lys_node_list *)dev_target)->must;
1899 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001900 break;
Radek Krejci76512572015-08-04 09:47:08 +02001901 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001902 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1903 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001904 break;
1905 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001906 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1907 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001908 goto error;
1909 }
1910
1911 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001912 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001913 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001914 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001915 } else if (d->mod == LY_DEVIATE_ADD) {
1916 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001917 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001918 if (!d->must) {
1919 LOGMEM;
1920 goto error;
1921 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001923 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001924 d->must_size = c_must;
1925 } else { /* LY_DEVIATE_DEL */
1926 d->must = calloc(c_must, sizeof *d->must);
1927 }
Michal Vasko253035f2015-12-17 16:58:13 +01001928 if (!d->must) {
1929 LOGMEM;
1930 goto error;
1931 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001932 }
1933 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001934 /* replace unique is forbidden */
1935 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001936 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001937 goto error;
1938 }
1939
Radek Krejcieb00f512015-07-01 16:44:58 +02001940 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001941 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001942 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1943 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001944 goto error;
1945 }
1946
Michal Vasko60f4b452016-02-12 11:02:55 +01001947 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001948 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001949 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001950 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001951 list->unique = d->unique;
1952 d->unique = &list->unique[list->unique_size];
1953 d->unique_size = c_uniq;
1954 } else { /* LY_DEVIATE_DEL */
1955 d->unique = calloc(c_uniq, sizeof *d->unique);
1956 }
Michal Vasko253035f2015-12-17 16:58:13 +01001957 if (!d->unique) {
1958 LOGMEM;
1959 goto error;
1960 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001961 }
1962
1963 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001964 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001965 if (!strcmp(child->name, "must")) {
1966 if (d->mod == LY_DEVIATE_DEL) {
1967 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1968 goto error;
1969 }
1970
1971 /* find must to delete, we are ok with just matching conditions */
1972 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001973 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001974 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001975 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001976 /* ... and maintain the array */
1977 (*trg_must_size)--;
1978 if (i != *trg_must_size) {
1979 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1980 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1981 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1982 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1983 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1984 }
1985 if (!(*trg_must_size)) {
1986 free(*trg_must);
1987 *trg_must = NULL;
1988 } else {
1989 (*trg_must)[*trg_must_size].expr = NULL;
1990 (*trg_must)[*trg_must_size].dsc = NULL;
1991 (*trg_must)[*trg_must_size].ref = NULL;
1992 (*trg_must)[*trg_must_size].eapptag = NULL;
1993 (*trg_must)[*trg_must_size].emsg = NULL;
1994 }
1995
1996 i = -1; /* set match flag */
1997 break;
1998 }
1999 }
2000 d->must_size++;
2001 if (i != -1) {
2002 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002003 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002004 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002005 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002006 goto error;
2007 }
2008 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002009 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2010 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002011 goto error;
2012 }
2013 (*trg_must_size)++;
2014 }
2015 } else if (!strcmp(child->name, "unique")) {
2016 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002017 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002018 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002019 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002020 goto error;
2021 }
2022
2023 /* find unique structures to delete */
2024 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002025 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002026 continue;
2027 }
2028
Radek Krejci581ce772015-11-10 17:22:40 +01002029 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002030 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002031 break;
2032 }
2033 }
2034
Radek Krejci581ce772015-11-10 17:22:40 +01002035 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002036 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002037 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002038 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002039 }
2040 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002041 /* ... and maintain the array */
2042 list->unique_size--;
2043 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002044 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2045 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002046 }
2047
2048 if (!list->unique_size) {
2049 free(list->unique);
2050 list->unique = NULL;
2051 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002052 list->unique[list->unique_size].expr_size = 0;
2053 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002054 }
2055
2056 i = -1; /* set match flag */
2057 break;
2058 }
2059 }
2060
2061 d->unique_size++;
2062 if (i != -1) {
2063 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002064 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2065 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002066 goto error;
2067 }
2068 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002069 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002070 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002071 list->unique_size++;
2072 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002073 goto error;
2074 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002075 }
2076 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002077 }
2078 }
2079
Michal Vasko43a1feb2016-03-07 12:03:02 +01002080 /* now check whether default value, if any, matches the type */
2081 for (i = 0; i < leaf_dflt_check_count; ++i) {
2082 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002083 rc = unres_schema_add_str(module, unres, &leaf_dflt_check[i]->type, UNRES_TYPE_DFLT, leaf_dflt_check[i]->dflt);
Michal Vasko43a1feb2016-03-07 12:03:02 +01002084 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002085 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
2086 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->target_name);
Michal Vasko43a1feb2016-03-07 12:03:02 +01002087 goto error;
2088 }
2089 }
2090 }
2091 free(leaf_dflt_check);
2092
Radek Krejcieb00f512015-07-01 16:44:58 +02002093 return EXIT_SUCCESS;
2094
2095error:
Michal Vasko34867132016-03-11 10:26:38 +01002096 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002097 return EXIT_FAILURE;
2098}
2099
Michal Vasko0d343d12015-08-24 14:57:36 +02002100/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002101static int
Radek Krejcib8048692015-08-05 13:36:34 +02002102fill_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 +02002103 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002104{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002106 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002107 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002108 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002109
Michal Vasko591e0b22015-08-13 13:53:43 +02002110 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002112 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002113 if (!aug->target_name) {
2114 goto error;
2115 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002117
Michal Vasko1d87a922015-08-21 12:57:16 +02002118 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002119 goto error;
2120 }
2121
2122 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002123 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2124 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002125 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002126 continue;
2127 }
2128
Radek Krejci3cf9e222015-06-18 11:37:50 +02002129 if (!strcmp(child->name, "if-feature")) {
2130 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002131 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002132 } else if (!strcmp(child->name, "when")) {
2133 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002134 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002135 goto error;
2136 }
2137
2138 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002139 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002140 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002141 goto error;
2142 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002143 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002144 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002145
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002146 /* check allowed data sub-statements */
2147 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002148 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002149 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002150 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002151 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002152 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002153 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002154 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002155 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002156 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002157 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002158 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002159 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002160 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002161 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002162 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002163 } else if (!strcmp(child->name, "action")) {
2164 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002165 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002166 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002167 goto error;
2168 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002169
Radek Krejci1d82ef62015-08-07 14:44:40 +02002170 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002171 goto error;
2172 }
2173
Radek Krejci1d82ef62015-08-07 14:44:40 +02002174 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002175 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002176 }
2177
2178 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002179 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2180 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002181 LOGMEM;
2182 goto error;
2183 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002184 }
2185
2186 LY_TREE_FOR_SAFE(yin->child, next, child) {
2187 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002188 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2189 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002190 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002191 goto error;
2192 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002193 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002194 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002195 }
2196
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002197 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002198 * connected to the tree and adjusted (if possible right now).
2199 * However, if this is augment in a uses, it gets resolved
2200 * when the uses does and cannot be resolved now for sure
2201 * (the grouping was not yet copied into uses).
2202 */
2203 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002204 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002205 goto error;
2206 }
Michal Vasko49291b32015-08-06 09:49:41 +02002207 }
Radek Krejci106efc02015-06-10 14:36:27 +02002208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002210
2211error:
2212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002214}
2215
Michal Vasko0d343d12015-08-24 14:57:36 +02002216/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002218fill_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 +02002219{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002220 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 struct lyxml_elem *sub, *next;
2222 const char *value;
2223 char *endptr;
2224 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002225 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 int r;
2227 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002228
Radek Krejci363bd4a2016-07-29 14:30:20 +02002229 assert(uses);
2230 module = uses->module; /* shorthand */
2231
Radek Krejci76512572015-08-04 09:47:08 +02002232 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 goto error;
2234 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002235
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002236 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002237 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002238 if (!rfn->target_name) {
2239 goto error;
2240 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002243 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2244 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002245 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002246 continue;
2247 }
2248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 /* limited applicability */
2250 if (!strcmp(sub->name, "default")) {
2251 /* leaf or choice */
2252 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002253 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 goto error;
2255 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 /* check possibility of statements combination */
2258 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002259 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002261 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2262 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 goto error;
2264 }
2265 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002266 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002267 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 GETVAL(value, sub, "value");
2270 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2271 } else if (!strcmp(sub->name, "mandatory")) {
2272 /* leaf, choice or anyxml */
2273 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002274 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 goto error;
2276 }
2277 /* just checking the flags in leaf is not sufficient, we would allow
2278 * multiple mandatory statements with the "false" value
2279 */
2280 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 /* check possibility of statements combination */
2283 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002284 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002286 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2287 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 goto error;
2289 }
2290 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002291 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 GETVAL(value, sub, "value");
2295 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002296 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002298 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002300 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 goto error;
2302 }
2303 } else if (!strcmp(sub->name, "min-elements")) {
2304 /* list or leaf-list */
2305 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002306 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 goto error;
2308 }
2309 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 /* check possibility of statements combination */
2312 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002313 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002315 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2316 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 goto error;
2318 }
2319 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002320 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 GETVAL(value, sub, "value");
2324 while (isspace(value[0])) {
2325 value++;
2326 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 /* convert it to uint32_t */
2329 errno = 0;
2330 endptr = NULL;
2331 val = strtoul(value, &endptr, 10);
2332 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002333 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 goto error;
2335 }
2336 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002337 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 } else if (!strcmp(sub->name, "max-elements")) {
2339 /* list or leaf-list */
2340 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002341 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 goto error;
2343 }
2344 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346 /* check possibility of statements combination */
2347 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002348 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002350 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2351 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352 goto error;
2353 }
2354 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002355 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 GETVAL(value, sub, "value");
2359 while (isspace(value[0])) {
2360 value++;
2361 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002362
Radek Krejci0d7b2472016-02-12 11:11:03 +01002363 if (!strcmp(value, "unbounded")) {
2364 rfn->mod.list.max = 0;
2365 } else {
2366 /* convert it to uint32_t */
2367 errno = 0;
2368 endptr = NULL;
2369 val = strtoul(value, &endptr, 10);
2370 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002371 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002372 goto error;
2373 }
2374 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002376 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 } else if (!strcmp(sub->name, "presence")) {
2378 /* container */
2379 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002380 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 goto error;
2382 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 /* check possibility of statements combination */
2385 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002386 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002388 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2389 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002390 goto error;
2391 }
2392 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002393 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 GETVAL(value, sub, "value");
2397 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2398 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002399 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 /* check possibility of statements combination */
2401 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002402 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002403 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002404 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2405 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 goto error;
2407 }
2408 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002409 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002413 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002414
Radek Krejci363bd4a2016-07-29 14:30:20 +02002415 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2416 /* leaf, leaf-list, list, container or anyxml */
2417 /* check possibility of statements combination */
2418 if (rfn->target_type) {
2419 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
2420 if (!rfn->target_type) {
2421 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2422 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2423 goto error;
2424 }
2425 } else {
2426 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
2427 }
2428
2429 c_ftrs++;
2430 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002432 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 goto error;
2434 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002435
Michal Vasko345da0a2015-12-02 10:35:55 +01002436 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 /* process nodes with cardinality of 0..n */
2440 if (c_must) {
2441 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002442 if (!rfn->must) {
2443 LOGMEM;
2444 goto error;
2445 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002447 if (c_ftrs) {
2448 rfn->iffeature = calloc(c_must, sizeof *rfn->iffeature);
2449 if (!rfn->iffeature) {
2450 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002451 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002454
Radek Krejci363bd4a2016-07-29 14:30:20 +02002455 LY_TREE_FOR(yin->child, sub) {
2456 if (!strcmp(sub->name, "if-feature")) {
2457 r = fill_yin_iffeature(uses, sub, &rfn->iffeature[rfn->iffeature_size], unres);
2458 rfn->iffeature_size++;
2459 if (r) {
2460 goto error;
2461 }
2462 } else {
2463 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2464 rfn->must_size++;
2465 if (r) {
2466 goto error;
2467 }
2468 }
2469 }
2470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002472
2473error:
2474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002476}
2477
Michal Vasko0d343d12015-08-24 14:57:36 +02002478/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479static int
Radek Krejcib8048692015-08-05 13:36:34 +02002480fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002481{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 struct lyxml_elem *child;
2483 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002484
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002486 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2487 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002488 continue;
2489 }
2490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 if (!strcmp(child->name, "prefix")) {
2492 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002493 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 goto error;
2495 }
2496 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2497 } else if (!strcmp(child->name, "revision-date")) {
2498 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002499 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2500 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 }
2502 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002503 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 goto error;
2505 }
2506 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002507 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002508 if (imp->dsc) {
2509 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2510 goto error;
2511 }
2512 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2513 if (!imp->dsc) {
2514 goto error;
2515 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002516 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002517 if (imp->ref) {
2518 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2519 goto error;
2520 }
2521 imp->ref = read_yin_subnode(module->ctx, child, "text");
2522 if (!imp->ref) {
2523 goto error;
2524 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002526 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 goto error;
2528 }
2529 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 /* check mandatory information */
2532 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002533 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 goto error;
2535 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002538
Pavol Vicane994fda2016-03-22 10:47:58 +01002539 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002540
2541error:
2542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002544}
2545
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002546/* logs directly
2547 * returns:
2548 * 0 - inc successfully filled
2549 * -1 - error, inc is cleaned
2550 * 1 - duplication, ignore the inc structure, inc is cleaned
2551 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002553fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2554 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002555{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 struct lyxml_elem *child;
2557 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002559 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002560 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2561 /* garbage */
2562 continue;
2563 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 if (!strcmp(child->name, "revision-date")) {
2565 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002566 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 goto error;
2568 }
2569 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002570 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 goto error;
2572 }
2573 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002574 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002575 if (inc->dsc) {
2576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2577 goto error;
2578 }
2579 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2580 if (!inc->dsc) {
2581 goto error;
2582 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002583 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002584 if (inc->ref) {
2585 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2586 goto error;
2587 }
2588 inc->ref = read_yin_subnode(module->ctx, child, "text");
2589 if (!inc->ref) {
2590 goto error;
2591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002592 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002593 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 goto error;
2595 }
2596 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002599
Pavol Vican0adf01d2016-03-22 12:29:33 +01002600 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002601
2602error:
2603
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002604 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002605}
2606
Michal Vasko0d343d12015-08-24 14:57:36 +02002607/* logs directly
2608 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002609 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002610 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002611 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002612 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002613static int
Radek Krejcib8048692015-08-05 13:36:34 +02002614read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002615 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002616{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 const char *value;
2618 struct lyxml_elem *sub, *next;
2619 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002622 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002623 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 if (opt & OPT_IDENT) {
2626 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002627 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 goto error;
2629 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002630 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002632
Radek Krejci6764bb32015-07-03 15:16:04 +02002633 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002634 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002635 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002636 }
2637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 /* process local parameters */
2639 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002640 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002641 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002642 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002643 continue;
2644 }
2645 if (strcmp(sub->ns->value, LY_NSYIN)) {
2646 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002647 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002648 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002649 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002650 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002651 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002652 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002653 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002654 goto error;
2655 }
2656 }
2657
2658 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002659 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002660 continue;
2661 }
2662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002664 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002665 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002666 goto error;
2667 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002668 node->dsc = read_yin_subnode(ctx, sub, "text");
2669 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002670 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002671 }
2672 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002673 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002674 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002675 goto error;
2676 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002677 node->ref = read_yin_subnode(ctx, sub, "text");
2678 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002679 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 }
2681 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002682 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002683 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 goto error;
2685 }
2686 GETVAL(value, sub, "value");
2687 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002688 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002689 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002690 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002692 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002694 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002695 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 }
2697 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002698 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002699 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 goto error;
2701 }
2702 GETVAL(value, sub, "value");
2703 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002704 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002705 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002706 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002708 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002709 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002711 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002713 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 continue;
2715 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002716 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002718
Radek Krejci1d82ef62015-08-07 14:44:40 +02002719 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002721 if (parent && (parent->flags & LYS_CONFIG_R)) {
2722 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 } else {
2724 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002725 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002726 }
2727 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002729 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002730
2731error:
2732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002734}
2735
Michal Vasko0d343d12015-08-24 14:57:36 +02002736/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002737static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002738read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002739{
Radek Krejci76512572015-08-04 09:47:08 +02002740 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002741 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002742 const char *value;
2743
2744 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002745 if (!retval) {
2746 LOGMEM;
2747 return NULL;
2748 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002749
2750 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002751 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002752 if (!retval->cond) {
2753 goto error;
2754 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002755 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002756 goto error;
2757 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002758
Radek Krejci73adb602015-07-02 18:07:40 +02002759 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002760 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2761 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002762 continue;
2763 }
2764
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002765 if (!strcmp(child->name, "description")) {
2766 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002767 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002768 goto error;
2769 }
2770 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2771 if (!retval->dsc) {
2772 goto error;
2773 }
2774 } else if (!strcmp(child->name, "reference")) {
2775 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002776 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002777 goto error;
2778 }
2779 retval->ref = read_yin_subnode(module->ctx, child, "text");
2780 if (!retval->ref) {
2781 goto error;
2782 }
2783 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002784 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002785 goto error;
2786 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002787 }
2788
2789 return retval;
2790
2791error:
2792
Michal Vasko0308dd62015-10-07 09:14:40 +02002793 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002794 return NULL;
2795}
2796
Michal Vasko0d343d12015-08-24 14:57:36 +02002797/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002798static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002799read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2800 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002801{
Michal Vasko29fc0182015-08-24 15:02:39 +02002802 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002803 struct lys_node_case *cs;
2804 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002805 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002806
Radek Krejcie867c852015-08-27 09:52:34 +02002807 /* init */
2808 memset(&root, 0, sizeof root);
2809
Radek Krejci1d82ef62015-08-07 14:44:40 +02002810 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002811 if (!cs) {
2812 LOGMEM;
2813 return NULL;
2814 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002815 cs->nodetype = LYS_CASE;
2816 cs->prev = (struct lys_node *)cs;
2817 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002818
Radek Krejci6a113852015-07-03 16:04:20 +02002819 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820 goto error;
2821 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002822
Radek Krejcia9544502015-08-14 08:24:29 +02002823 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2824
Michal Vasko3a0043f2015-08-12 12:11:30 +02002825 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002826 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002827 goto error;
2828 }
2829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 /* process choice's specific children */
2831 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002832 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2833 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002834 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002835 continue;
2836 }
2837
Michal Vasko29fc0182015-08-24 15:02:39 +02002838 if (!strcmp(sub->name, "container") ||
2839 !strcmp(sub->name, "leaf-list") ||
2840 !strcmp(sub->name, "leaf") ||
2841 !strcmp(sub->name, "list") ||
2842 !strcmp(sub->name, "uses") ||
2843 !strcmp(sub->name, "choice") ||
2844 !strcmp(sub->name, "anyxml")) {
2845
Michal Vaskof3930de2015-10-22 12:03:59 +02002846 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002847 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002848 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002849 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002850 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002851 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002852 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002853 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002854 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002855 goto error;
2856 }
2857
Radek Krejci1d82ef62015-08-07 14:44:40 +02002858 cs->when = read_yin_when(module, sub);
2859 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002860 goto error;
2861 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002862
Michal Vasko345da0a2015-12-02 10:35:55 +01002863 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002864 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002865 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002868 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002869
Radek Krejci3cf9e222015-06-18 11:37:50 +02002870 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002871 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
2872 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002873 LOGMEM;
2874 goto error;
2875 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002876 }
Radek Krejci73adb602015-07-02 18:07:40 +02002877 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002878 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
2879 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002880 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002881 goto error;
2882 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 }
Radek Krejcib388c152015-06-04 17:03:03 +02002884
Michal Vasko29fc0182015-08-24 15:02:39 +02002885 /* last part - process data nodes */
2886 LY_TREE_FOR_SAFE(root.child, next, sub) {
2887 if (!strcmp(sub->name, "container")) {
2888 node = read_yin_container(module, retval, sub, resolve, unres);
2889 } else if (!strcmp(sub->name, "leaf-list")) {
2890 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2891 } else if (!strcmp(sub->name, "leaf")) {
2892 node = read_yin_leaf(module, retval, sub, resolve, unres);
2893 } else if (!strcmp(sub->name, "list")) {
2894 node = read_yin_list(module, retval, sub, resolve, unres);
2895 } else if (!strcmp(sub->name, "choice")) {
2896 node = read_yin_choice(module, retval, sub, resolve, unres);
2897 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002898 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02002899 } else if (!strcmp(sub->name, "anyxml")) {
2900 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2901 }
2902 if (!node) {
2903 goto error;
2904 }
2905
Michal Vasko345da0a2015-12-02 10:35:55 +01002906 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002907 }
2908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002909 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002910
2911error:
2912
Michal Vasko29fc0182015-08-24 15:02:39 +02002913 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002914 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002915 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002916 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002919}
2920
Michal Vasko0d343d12015-08-24 14:57:36 +02002921/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002922static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002923read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002924{
Radek Krejci629cdef2016-06-06 15:06:36 +02002925 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002927 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002928 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002929 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002930 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002932 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002933 if (!choice) {
2934 LOGMEM;
2935 return NULL;
2936 }
Radek Krejci76512572015-08-04 09:47:08 +02002937 choice->nodetype = LYS_CHOICE;
2938 choice->prev = (struct lys_node *)choice;
2939 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002940
Michal Vaskoe0c59842015-09-24 13:52:20 +02002941 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2942 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 goto error;
2944 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002945
Radek Krejcia9544502015-08-14 08:24:29 +02002946 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2947
Michal Vasko3a0043f2015-08-12 12:11:30 +02002948 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002949 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002950 goto error;
2951 }
2952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 /* process choice's specific children */
2954 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002955 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2956 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002957 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002958 continue;
2959 }
2960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002962 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 goto error;
2964 }
2965 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002966 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002967 goto error;
2968 }
2969 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002970 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 goto error;
2972 }
2973 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002974 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 goto error;
2976 }
2977 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002978 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 goto error;
2980 }
2981 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002982 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002983 goto error;
2984 }
2985 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002986 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002987 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 goto error;
2989 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002990 dflt = sub;
2991 lyxml_unlink_elem(ctx, dflt, 0);
2992
Radek Krejcif9a312c2016-06-06 15:14:30 +02002993 continue;
2994 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 } else if (!strcmp(sub->name, "mandatory")) {
2997 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002998 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 goto error;
3000 }
3001 /* just checking the flags in leaf is not sufficient, we would allow
3002 * multiple mandatory statements with the "false" value
3003 */
3004 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003005
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 GETVAL(value, sub, "value");
3007 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003008 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003009 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003010 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003011 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003012 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 goto error;
3014 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003015 } else if (!strcmp(sub->name, "when")) {
3016 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003017 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003018 goto error;
3019 }
3020
3021 choice->when = read_yin_when(module, sub);
3022 if (!choice->when) {
3023 goto error;
3024 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003025 } else if (!strcmp(sub->name, "if-feature")) {
3026 c_ftrs++;
3027
Michal Vasko345da0a2015-12-02 10:35:55 +01003028 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003029 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003031 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003033 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003034
Radek Krejci1d82ef62015-08-07 14:44:40 +02003035 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003036 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003038
Radek Krejci3cf9e222015-06-18 11:37:50 +02003039 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003040 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3041 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003042 LOGMEM;
3043 goto error;
3044 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003045 }
3046
Radek Krejci73adb602015-07-02 18:07:40 +02003047 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003048 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
3049 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003050 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003051 goto error;
3052 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003053 }
3054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003056 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003057 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3058 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 goto error;
3060 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003063 if (dflt) {
3064 GETVAL(value, dflt, "value");
3065 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003066 goto error;
3067 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003068 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072
3073error:
3074
Radek Krejci629cdef2016-06-06 15:06:36 +02003075 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003076 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003079}
3080
Michal Vasko0d343d12015-08-24 14:57:36 +02003081/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003082static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003083read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003084 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003085{
Radek Krejci76512572015-08-04 09:47:08 +02003086 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003087 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 struct lyxml_elem *sub, *next;
3089 const char *value;
3090 int r;
3091 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003092 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003095 if (!anyxml) {
3096 LOGMEM;
3097 return NULL;
3098 }
Radek Krejci76512572015-08-04 09:47:08 +02003099 anyxml->nodetype = LYS_ANYXML;
3100 anyxml->prev = (struct lys_node *)anyxml;
3101 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003102
Michal Vaskoe0c59842015-09-24 13:52:20 +02003103 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3104 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003105 goto error;
3106 }
Radek Krejci863c2852015-06-03 15:47:11 +02003107
Radek Krejcia9544502015-08-14 08:24:29 +02003108 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003109
Radek Krejciadb30652016-07-11 15:27:07 +02003110 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003111 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003112 goto error;
3113 }
3114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003116 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3117 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003118 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003119 continue;
3120 }
3121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003122 if (!strcmp(sub->name, "mandatory")) {
3123 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003124 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
3127 /* just checking the flags in leaf is not sufficient, we would allow
3128 * multiple mandatory statements with the "false" value
3129 */
3130 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 GETVAL(value, sub, "value");
3133 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003134 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003135 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003136 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003137 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003138 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 goto error;
3140 }
3141 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003142 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003143 } else if (!strcmp(sub->name, "when")) {
3144 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003145 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003146 goto error;
3147 }
3148
3149 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003150 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003151 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003152 goto error;
3153 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003154 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 } else if (!strcmp(sub->name, "must")) {
3156 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003157 } else if (!strcmp(sub->name, "if-feature")) {
3158 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003161 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163 }
3164 }
Radek Krejci863c2852015-06-03 15:47:11 +02003165
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003166 /* middle part - process nodes with cardinality of 0..n */
3167 if (c_must) {
3168 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003169 if (!anyxml->must) {
3170 LOGMEM;
3171 goto error;
3172 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003174 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003175 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3176 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003177 LOGMEM;
3178 goto error;
3179 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003180 }
Radek Krejci863c2852015-06-03 15:47:11 +02003181
Radek Krejci73adb602015-07-02 18:07:40 +02003182 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003184 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3185 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 if (r) {
3187 goto error;
3188 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003189 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003190 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3191 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003192 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003193 goto error;
3194 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 }
Radek Krejci863c2852015-06-03 15:47:11 +02003197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003199
3200error:
3201
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003202 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003205}
3206
Michal Vasko0d343d12015-08-24 14:57:36 +02003207/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003208static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003209read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003210 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003211{
Radek Krejci76512572015-08-04 09:47:08 +02003212 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003213 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003214 struct lyxml_elem *sub, *next;
3215 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003216 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003217 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003220 if (!leaf) {
3221 LOGMEM;
3222 return NULL;
3223 }
Radek Krejci76512572015-08-04 09:47:08 +02003224 leaf->nodetype = LYS_LEAF;
3225 leaf->prev = (struct lys_node *)leaf;
3226 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003227
Michal Vaskoe0c59842015-09-24 13:52:20 +02003228 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3229 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 goto error;
3231 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003232
Radek Krejcia9544502015-08-14 08:24:29 +02003233 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003234
Radek Krejciadb30652016-07-11 15:27:07 +02003235 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003236 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003237 goto error;
3238 }
3239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003241 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3242 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003243 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003244 continue;
3245 }
3246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003248 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003249 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 goto error;
3251 }
Michal Vasko88c29542015-11-27 14:57:53 +01003252 /* HACK for unres */
3253 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003254 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003255 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003256 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 goto error;
3258 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003259 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 } else if (!strcmp(sub->name, "default")) {
3261 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003262 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 goto error;
3264 }
3265 GETVAL(value, sub, "value");
3266 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3267 } else if (!strcmp(sub->name, "units")) {
3268 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003269 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 goto error;
3271 }
3272 GETVAL(value, sub, "name");
3273 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3274 } else if (!strcmp(sub->name, "mandatory")) {
3275 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003276 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 goto error;
3278 }
3279 /* just checking the flags in leaf is not sufficient, we would allow
3280 * multiple mandatory statements with the "false" value
3281 */
3282 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 GETVAL(value, sub, "value");
3285 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003286 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003287 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003288 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003289 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003290 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 goto error;
3292 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003293 } else if (!strcmp(sub->name, "when")) {
3294 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003295 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003296 goto error;
3297 }
3298
3299 leaf->when = read_yin_when(module, sub);
3300 if (!leaf->when) {
3301 goto error;
3302 }
3303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003305 c_must++;
3306 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003307 } else if (!strcmp(sub->name, "if-feature")) {
3308 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003311 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003312 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003314 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003315
Michal Vasko88c29542015-11-27 14:57:53 +01003316 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003320 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003321 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003322 goto error;
3323 }
Michal Vasko478c4652016-07-21 12:55:01 +02003324 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3325 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3326 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3327 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3328 goto error;
3329 }
3330
3331 /* check default value (if not defined, there still could be some restrictions
3332 * that need to be checked against a default value from a derived type) */
3333 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3334 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 /* middle part - process nodes with cardinality of 0..n */
3338 if (c_must) {
3339 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003340 if (!leaf->must) {
3341 LOGMEM;
3342 goto error;
3343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003345 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003346 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3347 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003348 LOGMEM;
3349 goto error;
3350 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003351 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003352
Radek Krejci73adb602015-07-02 18:07:40 +02003353 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003354 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003355 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3356 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 if (r) {
3358 goto error;
3359 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003360 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003361 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3362 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003363 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003364 goto error;
3365 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003370
3371error:
3372
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003373 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003376}
3377
Michal Vasko0d343d12015-08-24 14:57:36 +02003378/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003379static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003380read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003381 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003382{
Radek Krejci76512572015-08-04 09:47:08 +02003383 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003384 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 struct lyxml_elem *sub, *next;
3386 const char *value;
3387 char *endptr;
3388 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003389 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003390 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003394 if (!llist) {
3395 LOGMEM;
3396 return NULL;
3397 }
Radek Krejci76512572015-08-04 09:47:08 +02003398 llist->nodetype = LYS_LEAFLIST;
3399 llist->prev = (struct lys_node *)llist;
3400 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003401
Michal Vaskoe0c59842015-09-24 13:52:20 +02003402 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3403 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 goto error;
3405 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003406
Radek Krejcia9544502015-08-14 08:24:29 +02003407 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003408
Radek Krejciadb30652016-07-11 15:27:07 +02003409 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003410 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003411 goto error;
3412 }
3413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003415 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3416 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003417 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003418 continue;
3419 }
3420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003422 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003423 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 goto error;
3425 }
Michal Vasko88c29542015-11-27 14:57:53 +01003426 /* HACK for unres */
3427 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003428 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003429 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003430 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 goto error;
3432 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003433 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 } else if (!strcmp(sub->name, "units")) {
3435 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003436 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 goto error;
3438 }
3439 GETVAL(value, sub, "name");
3440 llist->units = lydict_insert(module->ctx, value, strlen(value));
3441 } else if (!strcmp(sub->name, "ordered-by")) {
3442 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003443 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 goto error;
3445 }
3446 /* just checking the flags in llist is not sufficient, we would
3447 * allow multiple ordered-by statements with the "system" value
3448 */
3449 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003450
Radek Krejci1574a8d2015-08-03 14:16:52 +02003451 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3453 * state data
3454 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003455 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 continue;
3457 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 GETVAL(value, sub, "value");
3460 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003461 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003463 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003465 } /* else system is the default value, so we can ignore it */
3466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 } else if (!strcmp(sub->name, "must")) {
3468 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003469 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003470 } else if (!strcmp(sub->name, "if-feature")) {
3471 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 } else if (!strcmp(sub->name, "min-elements")) {
3475 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003476 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003477 goto error;
3478 }
3479 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 GETVAL(value, sub, "value");
3482 while (isspace(value[0])) {
3483 value++;
3484 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 /* convert it to uint32_t */
3487 errno = 0;
3488 endptr = NULL;
3489 val = strtoul(value, &endptr, 10);
3490 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003491 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 goto error;
3493 }
3494 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003495 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003496 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3497 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003498 goto error;
3499 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 } else if (!strcmp(sub->name, "max-elements")) {
3501 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003502 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003503 goto error;
3504 }
3505 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 GETVAL(value, sub, "value");
3508 while (isspace(value[0])) {
3509 value++;
3510 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003511
Radek Krejci0d7b2472016-02-12 11:11:03 +01003512 if (!strcmp(value, "unbounded")) {
3513 llist->max = 0;
3514 } else {
3515 /* convert it to uint32_t */
3516 errno = 0;
3517 endptr = NULL;
3518 val = strtoul(value, &endptr, 10);
3519 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003520 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003521 goto error;
3522 }
3523 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003524 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003525 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3526 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003527 goto error;
3528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003530 } else if (!strcmp(sub->name, "when")) {
3531 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003532 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003533 goto error;
3534 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003535
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003536 llist->when = read_yin_when(module, sub);
3537 if (!llist->when) {
3538 goto error;
3539 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003541 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003544
Michal Vasko88c29542015-11-27 14:57:53 +01003545 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003549 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003550 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 goto error;
3552 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 /* middle part - process nodes with cardinality of 0..n */
3555 if (c_must) {
3556 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003557 if (!llist->must) {
3558 LOGMEM;
3559 goto error;
3560 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003562 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003563 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3564 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003565 LOGMEM;
3566 goto error;
3567 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003568 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003569
Radek Krejci73adb602015-07-02 18:07:40 +02003570 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003572 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3573 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 if (r) {
3575 goto error;
3576 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003577 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003578 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3579 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003580 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003581 goto error;
3582 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003583 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003587
3588error:
3589
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003590 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003593}
3594
Michal Vasko0d343d12015-08-24 14:57:36 +02003595/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003596static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003597read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3598 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003599{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003600 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003601 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003603 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003604 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003606 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 char *auxs;
3608 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 /* init */
3611 memset(&root, 0, sizeof root);
3612 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003614 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003615 if (!list) {
3616 LOGMEM;
3617 return NULL;
3618 }
Radek Krejci76512572015-08-04 09:47:08 +02003619 list->nodetype = LYS_LIST;
3620 list->prev = (struct lys_node *)list;
3621 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003622
Michal Vaskoe0c59842015-09-24 13:52:20 +02003623 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3624 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 goto error;
3626 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003627
Radek Krejcia9544502015-08-14 08:24:29 +02003628 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3629
Radek Krejciadb30652016-07-11 15:27:07 +02003630 /* insert the node into the schema tree */
3631 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3632 goto error;
3633 }
3634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 /* process list's specific children */
3636 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003637 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3638 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003639 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003640 continue;
3641 }
3642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 /* data statements */
3644 if (!strcmp(sub->name, "container") ||
3645 !strcmp(sub->name, "leaf-list") ||
3646 !strcmp(sub->name, "leaf") ||
3647 !strcmp(sub->name, "list") ||
3648 !strcmp(sub->name, "choice") ||
3649 !strcmp(sub->name, "uses") ||
3650 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003651 !strcmp(sub->name, "anyxml") ||
3652 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003653 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003654 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 /* array counters */
3657 } else if (!strcmp(sub->name, "key")) {
3658 /* check cardinality 0..1 */
3659 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003660 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 goto error;
3662 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 /* count the number of keys */
3665 GETVAL(value, sub, "value");
3666 key_str = value;
3667 while ((value = strpbrk(value, " \t\n"))) {
3668 list->keys_size++;
3669 while (isspace(*value)) {
3670 value++;
3671 }
3672 }
3673 list->keys_size++;
3674 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003675 if (!list->keys) {
3676 LOGMEM;
3677 goto error;
3678 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 } else if (!strcmp(sub->name, "unique")) {
3680 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003681 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003682 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 } else if (!strcmp(sub->name, "typedef")) {
3684 c_tpdf++;
3685 } else if (!strcmp(sub->name, "must")) {
3686 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003687 } else if (!strcmp(sub->name, "if-feature")) {
3688 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 /* optional stetments */
3691 } else if (!strcmp(sub->name, "ordered-by")) {
3692 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003693 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 goto error;
3695 }
3696 /* just checking the flags in llist is not sufficient, we would
3697 * allow multiple ordered-by statements with the "system" value
3698 */
3699 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003700
Radek Krejci1574a8d2015-08-03 14:16:52 +02003701 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3703 * state data
3704 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003705 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 continue;
3707 }
Radek Krejci345ad742015-06-03 11:04:18 +02003708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 GETVAL(value, sub, "value");
3710 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003711 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003713 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 goto error;
3715 }
3716 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003717 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 } else if (!strcmp(sub->name, "min-elements")) {
3719 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003720 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 goto error;
3722 }
3723 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 GETVAL(value, sub, "value");
3726 while (isspace(value[0])) {
3727 value++;
3728 }
Radek Krejci345ad742015-06-03 11:04:18 +02003729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 /* convert it to uint32_t */
3731 errno = 0;
3732 auxs = NULL;
3733 val = strtoul(value, &auxs, 10);
3734 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003735 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 goto error;
3737 }
3738 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003739 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003740 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3741 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003742 lyxml_free(module->ctx, sub);
3743 goto error;
3744 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003745 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 } else if (!strcmp(sub->name, "max-elements")) {
3747 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003748 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 goto error;
3750 }
3751 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 GETVAL(value, sub, "value");
3754 while (isspace(value[0])) {
3755 value++;
3756 }
Radek Krejci345ad742015-06-03 11:04:18 +02003757
Radek Krejci0d7b2472016-02-12 11:11:03 +01003758 if (!strcmp(value, "unbounded")) {
3759 list->max = 0;;
3760 } else {
3761 /* convert it to uint32_t */
3762 errno = 0;
3763 auxs = NULL;
3764 val = strtoul(value, &auxs, 10);
3765 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003766 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003767 goto error;
3768 }
3769 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003770 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003771 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3772 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003773 goto error;
3774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003776 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003777 } else if (!strcmp(sub->name, "when")) {
3778 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003779 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003780 goto error;
3781 }
3782
3783 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003784 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003785 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003786 goto error;
3787 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003788 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003789 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003790 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003791 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 }
3793 }
Radek Krejci345ad742015-06-03 11:04:18 +02003794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003796 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003797 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 goto error;
3799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3802 if (c_tpdf) {
3803 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003804 if (!list->tpdf) {
3805 LOGMEM;
3806 goto error;
3807 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003809 if (c_must) {
3810 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003811 if (!list->must) {
3812 LOGMEM;
3813 goto error;
3814 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003815 }
3816 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003817 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
3818 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003819 LOGMEM;
3820 goto error;
3821 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003822 }
Radek Krejci73adb602015-07-02 18:07:40 +02003823 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003825 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3826 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 if (r) {
3828 goto error;
3829 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003830 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003831 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
3832 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003833 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003834 goto error;
3835 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003836 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003837 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3838 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003839 if (r) {
3840 goto error;
3841 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 }
3843 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 /* last part - process data nodes */
3846 LY_TREE_FOR_SAFE(root.child, next, sub) {
3847 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003848 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003850 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003852 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003856 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003858 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003860 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003862 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003863 } else if (!strcmp(sub->name, "action")) {
3864 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003865 } else {
3866 LOGINT;
3867 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003868 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003869 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 goto error;
3871 }
Radek Krejci73adb602015-07-02 18:07:40 +02003872
Michal Vasko345da0a2015-12-02 10:35:55 +01003873 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003875
Radek Krejci461efb92016-02-12 15:52:18 +01003876 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003877 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003878 goto error;
3879 }
3880 } /* 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 +02003881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 /* process unique statements */
3883 if (c_uniq) {
3884 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003885 if (!list->unique) {
3886 LOGMEM;
3887 goto error;
3888 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003889
Radek Krejci461efb92016-02-12 15:52:18 +01003890 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3891 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3892 list->unique_size++;
3893 if (r) {
3894 goto error;
3895 }
3896
3897 lyxml_free(module->ctx, sub);
3898 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003901 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003902
3903error:
3904
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003905 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003906 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003907 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 }
3909 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003910 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003914}
3915
Michal Vasko0d343d12015-08-24 14:57:36 +02003916/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003917static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003918read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3919 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003920{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003922 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003923 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003924 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 const char *value;
3926 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003927 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 /* init */
3930 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003933 if (!cont) {
3934 LOGMEM;
3935 return NULL;
3936 }
Radek Krejci76512572015-08-04 09:47:08 +02003937 cont->nodetype = LYS_CONTAINER;
3938 cont->prev = (struct lys_node *)cont;
3939 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003940
Michal Vaskoe0c59842015-09-24 13:52:20 +02003941 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3942 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 goto error;
3944 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003945
Radek Krejcia9544502015-08-14 08:24:29 +02003946 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3947
Radek Krejciadb30652016-07-11 15:27:07 +02003948 /* insert the node into the schema tree */
3949 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3950 goto error;
3951 }
3952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 /* process container's specific children */
3954 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003955 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003956 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003957 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003958 continue;
3959 }
3960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 if (!strcmp(sub->name, "presence")) {
3962 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003963 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003964 goto error;
3965 }
3966 GETVAL(value, sub, "value");
3967 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003968
Michal Vasko345da0a2015-12-02 10:35:55 +01003969 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003970 } else if (!strcmp(sub->name, "when")) {
3971 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003972 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003973 goto error;
3974 }
3975
3976 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003977 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003978 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003979 goto error;
3980 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003981 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983 /* data statements */
3984 } else if (!strcmp(sub->name, "container") ||
3985 !strcmp(sub->name, "leaf-list") ||
3986 !strcmp(sub->name, "leaf") ||
3987 !strcmp(sub->name, "list") ||
3988 !strcmp(sub->name, "choice") ||
3989 !strcmp(sub->name, "uses") ||
3990 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003991 !strcmp(sub->name, "anyxml") ||
3992 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003993 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003994 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 /* array counters */
3997 } else if (!strcmp(sub->name, "typedef")) {
3998 c_tpdf++;
3999 } else if (!strcmp(sub->name, "must")) {
4000 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004001 } else if (!strcmp(sub->name, "if-feature")) {
4002 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004003 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004004 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004006 }
4007 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004009 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4010 if (c_tpdf) {
4011 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004012 if (!cont->tpdf) {
4013 LOGMEM;
4014 goto error;
4015 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004016 }
4017 if (c_must) {
4018 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004019 if (!cont->must) {
4020 LOGMEM;
4021 goto error;
4022 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004024 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004025 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4026 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004027 LOGMEM;
4028 goto error;
4029 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004030 }
Radek Krejci800af702015-06-02 13:46:01 +02004031
Radek Krejci73adb602015-07-02 18:07:40 +02004032 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004034 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4035 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004036 if (r) {
4037 goto error;
4038 }
4039 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004040 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4041 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 if (r) {
4043 goto error;
4044 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004045 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004046 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
4047 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004048 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004049 goto error;
4050 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 /* last part - process data nodes */
4055 LY_TREE_FOR_SAFE(root.child, next, sub) {
4056 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004059 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004061 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004063 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004065 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004066 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004067 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004069 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004071 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004072 } else if (!strcmp(sub->name, "action")) {
4073 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004075 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004076 goto error;
4077 }
Radek Krejci73adb602015-07-02 18:07:40 +02004078
Michal Vasko345da0a2015-12-02 10:35:55 +01004079 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004080 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004081
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004082 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004083
4084error:
4085
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004086 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004087 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004088 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004089 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004091 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004092}
4093
Michal Vasko0d343d12015-08-24 14:57:36 +02004094/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004095static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02004096read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004097 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004098{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004100 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004101 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004102 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103 int r;
4104 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 /* init */
4107 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004109 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004110 if (!grp) {
4111 LOGMEM;
4112 return NULL;
4113 }
Radek Krejci76512572015-08-04 09:47:08 +02004114 grp->nodetype = LYS_GROUPING;
4115 grp->prev = (struct lys_node *)grp;
4116 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004117
Michal Vasko71e1aa82015-08-12 12:17:51 +02004118 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 goto error;
4120 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004121
Radek Krejcia9544502015-08-14 08:24:29 +02004122 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4123
Radek Krejciadb30652016-07-11 15:27:07 +02004124 /* insert the node into the schema tree */
4125 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4126 goto error;
4127 }
4128
Radek Krejci1d82ef62015-08-07 14:44:40 +02004129 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004130 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4131 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004132 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004133 continue;
4134 }
4135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004136 /* data statements */
4137 if (!strcmp(sub->name, "container") ||
4138 !strcmp(sub->name, "leaf-list") ||
4139 !strcmp(sub->name, "leaf") ||
4140 !strcmp(sub->name, "list") ||
4141 !strcmp(sub->name, "choice") ||
4142 !strcmp(sub->name, "uses") ||
4143 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004144 !strcmp(sub->name, "anyxml") ||
4145 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004146 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004147 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 /* array counters */
4150 } else if (!strcmp(sub->name, "typedef")) {
4151 c_tpdf++;
4152 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004153 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 goto error;
4155 }
4156 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004158 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4159 if (c_tpdf) {
4160 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004161 if (!grp->tpdf) {
4162 LOGMEM;
4163 goto error;
4164 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004165 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004166 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004167 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4168 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004169 if (r) {
4170 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004171 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004174 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004175 if (!root.child) {
4176 LOGWRN("Grouping \"%s\" without children.", retval->name);
4177 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004178 LY_TREE_FOR_SAFE(root.child, next, sub) {
4179 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004180 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004182 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004184 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004186 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004187 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004188 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004189 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004190 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004191 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004192 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004193 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004194 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004195 } else if (!strcmp(sub->name, "action")) {
4196 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004197 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004198 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 goto error;
4200 }
Radek Krejci73adb602015-07-02 18:07:40 +02004201
Michal Vasko345da0a2015-12-02 10:35:55 +01004202 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004203 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004205 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004206
4207error:
4208
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004209 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004210 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004211 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004212 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004214 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004215}
4216
Michal Vasko0d343d12015-08-24 14:57:36 +02004217/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004218static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004219read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4220 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004221{
Radek Krejcie0674f82015-06-15 13:58:51 +02004222 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004223 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004224 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004225 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004226 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004227 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004228
Radek Krejcie0674f82015-06-15 13:58:51 +02004229 /* init */
4230 memset(&root, 0, sizeof root);
4231
Michal Vasko38d01f72015-06-15 09:41:06 +02004232 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004233 if (!inout) {
4234 LOGMEM;
4235 return NULL;
4236 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004237 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004238
4239 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004240 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004241 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004242 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004243 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004244 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004245 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004246 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004247 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004248 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004249 }
4250
Radek Krejci76512572015-08-04 09:47:08 +02004251 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004252
Radek Krejci6a113852015-07-03 16:04:20 +02004253 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004254 goto error;
4255 }
4256
Radek Krejcia9544502015-08-14 08:24:29 +02004257 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4258
Radek Krejciadb30652016-07-11 15:27:07 +02004259 /* insert the node into the schema tree */
4260 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4261 goto error;
4262 }
4263
Michal Vasko38d01f72015-06-15 09:41:06 +02004264 /* data statements */
4265 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004266 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4267 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004268 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004269 continue;
4270 }
4271
Michal Vasko38d01f72015-06-15 09:41:06 +02004272 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004273 !strcmp(sub->name, "leaf-list") ||
4274 !strcmp(sub->name, "leaf") ||
4275 !strcmp(sub->name, "list") ||
4276 !strcmp(sub->name, "choice") ||
4277 !strcmp(sub->name, "uses") ||
4278 !strcmp(sub->name, "grouping") ||
4279 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004280 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004281 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004284 } else if (!strcmp(sub->name, "typedef")) {
4285 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004286
Radek Krejci1a31efe2016-07-29 11:04:16 +02004287 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004288 c_must++;
4289
Michal Vasko38d01f72015-06-15 09:41:06 +02004290 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004291 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004292 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004293 }
4294 }
4295
4296 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4297 if (c_tpdf) {
4298 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004299 if (!inout->tpdf) {
4300 LOGMEM;
4301 goto error;
4302 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004303 }
Radek Krejci19332802016-07-29 10:39:46 +02004304 if (c_must) {
4305 inout->must = calloc(c_must, sizeof *inout->must);
4306 if (!inout->must) {
4307 LOGMEM;
4308 goto error;
4309 }
4310 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004311
Radek Krejci73adb602015-07-02 18:07:40 +02004312 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004313 if (!strcmp(sub->name, "must")) {
4314 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4315 inout->must_size++;
4316 if (r) {
4317 goto error;
4318 }
4319 } else { /* typedef */
4320 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4321 inout->tpdf_size++;
4322 if (r) {
4323 goto error;
4324 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004325 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004326 }
4327
4328 /* last part - process data nodes */
4329 LY_TREE_FOR_SAFE(root.child, next, sub) {
4330 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004331 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004332 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004333 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004334 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004335 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004336 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004337 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004338 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004339 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004340 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004341 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004342 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004343 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004344 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004346 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004348 goto error;
4349 }
Radek Krejci73adb602015-07-02 18:07:40 +02004350
Michal Vasko345da0a2015-12-02 10:35:55 +01004351 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004352 }
4353
Michal Vasko38d01f72015-06-15 09:41:06 +02004354 return retval;
4355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004357
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004358 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004359 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004360 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004361 }
4362
4363 return NULL;
4364}
4365
Michal Vasko0d343d12015-08-24 14:57:36 +02004366/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004367static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004368read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4369 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004370{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004371 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004373 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004374 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004375 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004376 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004377
Michal Vaskoc6551b32015-06-16 10:51:43 +02004378 memset(&root, 0, sizeof root);
4379
Michal Vasko0ea41032015-06-16 08:53:55 +02004380 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004381 if (!notif) {
4382 LOGMEM;
4383 return NULL;
4384 }
Radek Krejci76512572015-08-04 09:47:08 +02004385 notif->nodetype = LYS_NOTIF;
4386 notif->prev = (struct lys_node *)notif;
4387 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004388
Radek Krejci6a113852015-07-03 16:04:20 +02004389 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004390 goto error;
4391 }
4392
Radek Krejcia9544502015-08-14 08:24:29 +02004393 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4394
Radek Krejciadb30652016-07-11 15:27:07 +02004395 /* insert the node into the schema tree */
4396 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4397 goto error;
4398 }
4399
Michal Vasko0ea41032015-06-16 08:53:55 +02004400 /* process rpc's specific children */
4401 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004402 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4403 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004404 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004405 continue;
4406 }
4407
Michal Vasko0ea41032015-06-16 08:53:55 +02004408 /* data statements */
4409 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 !strcmp(sub->name, "leaf-list") ||
4411 !strcmp(sub->name, "leaf") ||
4412 !strcmp(sub->name, "list") ||
4413 !strcmp(sub->name, "choice") ||
4414 !strcmp(sub->name, "uses") ||
4415 !strcmp(sub->name, "grouping") ||
4416 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004417 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004418 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004421 } else if (!strcmp(sub->name, "typedef")) {
4422 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004423 } else if (!strcmp(sub->name, "if-feature")) {
4424 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004425 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004426 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004427 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004428 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004429 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004430 }
4431 }
4432
4433 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4434 if (c_tpdf) {
4435 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004436 if (!notif->tpdf) {
4437 LOGMEM;
4438 goto error;
4439 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004440 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004441 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004442 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4443 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004444 LOGMEM;
4445 goto error;
4446 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004447 }
Radek Krejci19332802016-07-29 10:39:46 +02004448 if (c_must) {
4449 notif->must = calloc(c_must, sizeof *notif->must);
4450 if (!notif->must) {
4451 LOGMEM;
4452 goto error;
4453 }
4454 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004455
Radek Krejci73adb602015-07-02 18:07:40 +02004456 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004457 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004458 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4459 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004460 if (r) {
4461 goto error;
4462 }
Radek Krejci96299152016-06-22 10:17:50 +02004463 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004464 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4465 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004466 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004467 goto error;
4468 }
Radek Krejci19332802016-07-29 10:39:46 +02004469 } else if (!strcmp(sub->name, "must")) {
4470 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4471 notif->must_size++;
4472 if (r) {
4473 goto error;
4474 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004475 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004476 }
4477
4478 /* last part - process data nodes */
4479 LY_TREE_FOR_SAFE(root.child, next, sub) {
4480 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004481 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004482 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004484 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004485 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004486 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004487 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004488 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004489 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004490 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004491 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004492 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004493 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004494 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004495 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004496 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004497 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004498 goto error;
4499 }
Radek Krejci73adb602015-07-02 18:07:40 +02004500
Michal Vasko345da0a2015-12-02 10:35:55 +01004501 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004502 }
4503
Michal Vasko0ea41032015-06-16 08:53:55 +02004504 return retval;
4505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004507
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004508 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004509 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004510 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004511 }
4512
4513 return NULL;
4514}
4515
Michal Vasko0d343d12015-08-24 14:57:36 +02004516/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004517static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004518read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4519 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004520{
Radek Krejcie0674f82015-06-15 13:58:51 +02004521 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004522 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004523 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004524 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004525 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004526 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004527
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004528 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02004529 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02004530 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
4531 return NULL;
4532 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004533 for (node = parent; node; node = lys_parent(node)) {
4534 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
4535 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
4536 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
4537 return NULL;
4538 }
4539 }
4540 }
4541
Radek Krejcie0674f82015-06-15 13:58:51 +02004542 /* init */
4543 memset(&root, 0, sizeof root);
4544
Michal Vasko38d01f72015-06-15 09:41:06 +02004545 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004546 if (!rpc) {
4547 LOGMEM;
4548 return NULL;
4549 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004550 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02004551 rpc->prev = (struct lys_node *)rpc;
4552 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004553
Radek Krejci6a113852015-07-03 16:04:20 +02004554 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004555 goto error;
4556 }
4557
Radek Krejcia9544502015-08-14 08:24:29 +02004558 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4559
Radek Krejciadb30652016-07-11 15:27:07 +02004560 /* insert the node into the schema tree */
4561 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4562 goto error;
4563 }
4564
Michal Vasko38d01f72015-06-15 09:41:06 +02004565 /* process rpc's specific children */
4566 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004567 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4568 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004569 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004570 continue;
4571 }
4572
Michal Vasko38d01f72015-06-15 09:41:06 +02004573 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004575 && (rpc->child->nodetype == LYS_INPUT
4576 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004577 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004578 goto error;
4579 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004580 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004581 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004582 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004583 if (rpc->child
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004584 && (rpc->child->nodetype == LYS_OUTPUT
4585 || (rpc->child->next && rpc->child->next->nodetype == LYS_OUTPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004586 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004587 goto error;
4588 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004589 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004590 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004593 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004594 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004595 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004598 } else if (!strcmp(sub->name, "typedef")) {
4599 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004600 } else if (!strcmp(sub->name, "if-feature")) {
4601 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004602 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004603 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004604 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004605 }
4606 }
4607
4608 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4609 if (c_tpdf) {
4610 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004611 if (!rpc->tpdf) {
4612 LOGMEM;
4613 goto error;
4614 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004615 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004616 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004617 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
4618 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004619 LOGMEM;
4620 goto error;
4621 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004622 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004623
Radek Krejci73adb602015-07-02 18:07:40 +02004624 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004625 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004626 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4627 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004628 if (r) {
4629 goto error;
4630 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004631 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004632 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
4633 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004634 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004635 goto error;
4636 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004637 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004638 }
4639
4640 /* last part - process data nodes */
4641 LY_TREE_FOR_SAFE(root.child, next, sub) {
4642 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004644 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004645 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004646 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004647 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004648 goto error;
4649 }
Radek Krejci73adb602015-07-02 18:07:40 +02004650
Michal Vasko345da0a2015-12-02 10:35:55 +01004651 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004652 }
4653
Michal Vasko38d01f72015-06-15 09:41:06 +02004654 return retval;
4655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004657
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004658 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004659 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004660 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004661 }
4662
4663 return NULL;
4664}
4665
Michal Vasko0d343d12015-08-24 14:57:36 +02004666/* logs directly
4667 *
Radek Krejci74705112015-06-05 10:25:44 +02004668 * resolve - referenced grouping should be bounded to the namespace (resolved)
4669 * only when uses does not appear in grouping. In a case of grouping's uses,
4670 * we just get information but we do not apply augment or refine to it.
4671 */
Radek Krejci76512572015-08-04 09:47:08 +02004672static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004673read_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 +02004674{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004675 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004676 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004677 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004679 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004680 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004683 if (!uses) {
4684 LOGMEM;
4685 return NULL;
4686 }
Radek Krejci76512572015-08-04 09:47:08 +02004687 uses->nodetype = LYS_USES;
4688 uses->prev = (struct lys_node *)uses;
4689 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004690
Radek Krejcia9544502015-08-14 08:24:29 +02004691 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004693
Michal Vaskoe0c59842015-09-24 13:52:20 +02004694 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004695 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 goto error;
4697 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004698
Radek Krejcia9544502015-08-14 08:24:29 +02004699 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4700
Radek Krejciadb30652016-07-11 15:27:07 +02004701 /* insert the node into the schema tree */
4702 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4703 goto error;
4704 }
4705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004707 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004708 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4709 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004710 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004711 continue;
4712 }
4713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 if (!strcmp(sub->name, "refine")) {
4715 c_ref++;
4716 } else if (!strcmp(sub->name, "augment")) {
4717 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004718 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004719 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004720 } else if (!strcmp(sub->name, "when")) {
4721 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004722 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004723 goto error;
4724 }
4725
4726 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004727 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004728 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004729 goto error;
4730 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004731 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004733 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 }
4736 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 /* process properties with cardinality 0..n */
4739 if (c_ref) {
4740 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004741 if (!uses->refine) {
4742 LOGMEM;
4743 goto error;
4744 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 }
4746 if (c_aug) {
4747 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004748 if (!uses->augment) {
4749 LOGMEM;
4750 goto error;
4751 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004753 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004754 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
4755 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004756 LOGMEM;
4757 goto error;
4758 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004759 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004760
Radek Krejcia9544502015-08-14 08:24:29 +02004761 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004762 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02004763 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004764 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004765 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004766 goto error;
4767 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004768 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004769 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4770 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004771 if (r) {
4772 goto error;
4773 }
4774 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004775 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
4776 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004777 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004778 goto error;
4779 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 }
4781 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004782
Radek Krejci48464ed2016-03-17 15:44:09 +01004783 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004784 goto error;
4785 }
Radek Krejci74705112015-06-05 10:25:44 +02004786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004788
4789error:
4790
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004791 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004793 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004794}
4795
Michal Vasko0d343d12015-08-24 14:57:36 +02004796/* logs directly
4797 *
4798 * common code for yin_read_module() and yin_read_submodule()
4799 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800static int
Radek Krejcic071c542016-01-27 14:57:51 +01004801read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4802 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004803{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004805 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004806 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004807 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004808 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004810 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004811 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004812 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004813 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004814 int c_imp = 0, c_rev = 0, c_tpdf = 0, c_ident = 0, c_inc = 0, c_aug = 0, c_ftrs = 0, c_dev = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004815
Radek Krejcic071c542016-01-27 14:57:51 +01004816 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004817 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004819 /* init */
4820 memset(&root, 0, sizeof root);
4821 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004822 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 /*
4825 * in the first run, we process elements with cardinality of 1 or 0..1 and
4826 * count elements with cardinality 0..n. Data elements (choices, containers,
4827 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4828 * need have all top-level and groupings already prepared at that time. In
4829 * the middle loop, we process other elements with carinality of 0..n since
4830 * we need to allocate arrays to store them.
4831 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004832 LY_TREE_FOR_SAFE(yin->child, next, child) {
4833 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004834 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004835 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 continue;
4837 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004838
Radek Krejcic071c542016-01-27 14:57:51 +01004839 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004841 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 goto error;
4843 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004844 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004846 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004847 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004848 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004849 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004850 goto error;
4851 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004852 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004853 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 goto error;
4855 }
4856 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004857 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004858 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4859 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004860 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 goto error;
4862 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004863 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004864 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004865 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 goto error;
4867 }
Radek Krejcif3886932015-06-04 17:36:06 +02004868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004870 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004871 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004873 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004874 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004876 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004877 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004878 goto error;
4879 }
4880 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004881 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 /* check here differs from a generic prefix check, since this prefix
4883 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004884 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004885 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 goto error;
4887 }
Radek Krejcic071c542016-01-27 14:57:51 +01004888 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004891 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004892
4893 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004894 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004895 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004896 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004898 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004900 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004902 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004904 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004905 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004906 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004907 lyxml_unlink_elem(ctx, child, 2);
4908 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004909
Radek Krejci1d82ef62015-08-07 14:44:40 +02004910 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004911 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004912 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004913 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004916 } else if (!strcmp(child->name, "container") ||
4917 !strcmp(child->name, "leaf-list") ||
4918 !strcmp(child->name, "leaf") ||
4919 !strcmp(child->name, "list") ||
4920 !strcmp(child->name, "choice") ||
4921 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004922 !strcmp(child->name, "anyxml") ||
4923 !strcmp(child->name, "rpc") ||
4924 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004925 lyxml_unlink_elem(ctx, child, 2);
4926 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004927
Radek Krejci1d82ef62015-08-07 14:44:40 +02004928 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004929 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004930 lyxml_unlink_elem(ctx, child, 2);
4931 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004934 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004935 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004936 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 goto error;
4938 }
Radek Krejcic071c542016-01-27 14:57:51 +01004939 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004940 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004941 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 goto error;
4943 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004944 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004945 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004946 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 goto error;
4948 }
Radek Krejcic071c542016-01-27 14:57:51 +01004949 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004950 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004951 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 goto error;
4953 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004954 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004955 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004956 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 goto error;
4958 }
Radek Krejcic071c542016-01-27 14:57:51 +01004959 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004960 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004961 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004962 goto error;
4963 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004964 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004965 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004966 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004967 goto error;
4968 }
Radek Krejcic071c542016-01-27 14:57:51 +01004969 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004970 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004971 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004972 goto error;
4973 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004974 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004975 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004976 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004977 goto error;
4978 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004979 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02004980 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004981 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 goto error;
4983 }
Radek Krejcic071c542016-01-27 14:57:51 +01004984 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02004985 if (!strcmp(value, "1")) {
4986 if (submodule) {
4987 if (module->version > 1) {
4988 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4989 goto error;
4990 }
4991 } else {
4992 module->version = 1;
4993 }
4994 } else {
4995 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02004996 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02004997 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4998 goto error;
4999 }
5000 } else {
5001 module->version = 2;
5002 }
5003 }
5004
Michal Vasko345da0a2015-12-02 10:35:55 +01005005 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005006
Radek Krejci1d82ef62015-08-07 14:44:40 +02005007 } else if (!strcmp(child->name, "extension")) {
5008 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005009
Radek Krejci3d468122015-10-02 13:36:12 +02005010 /* we have the following supported (hardcoded) extensions: */
5011 /* ietf-netconf's get-filter-element-attributes */
5012 if (!strcmp(module->ns, LY_NSNC) &&
5013 !strcmp(value, "get-filter-element-attributes")) {
5014 LOGDBG("NETCONF filter extension found");
5015 /* NACM's default-deny-write and default-deny-all */
5016 } else if (!strcmp(module->ns, LY_NSNACM) &&
5017 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5018 LOGDBG("NACM extension found");
5019 /* other extensions are not supported, so inform about such an extension */
5020 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005021 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005022 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005023 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005024 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005025 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005026 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 }
5028 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005029
Radek Krejcic071c542016-01-27 14:57:51 +01005030 /* check for mandatory statements */
5031 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005032 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005033 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005034 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005036 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 goto error;
5038 }
5039 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005040 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005041 goto error;
5042 }
5043 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 /* allocate arrays for elements with cardinality of 0..n */
5046 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005047 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5048 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005049 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005050 LOGMEM;
5051 goto error;
5052 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005053 /* set stop block for possible realloc */
5054 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005055 }
5056 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005057 trg->rev = calloc(c_rev, sizeof *trg->rev);
5058 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005059 LOGMEM;
5060 goto error;
5061 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005062 }
5063 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005064 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5065 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005066 LOGMEM;
5067 goto error;
5068 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005069 }
5070 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005071 trg->ident = calloc(c_ident, sizeof *trg->ident);
5072 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005073 LOGMEM;
5074 goto error;
5075 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005076 }
5077 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005078 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5079 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005080 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005081 LOGMEM;
5082 goto error;
5083 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005084 /* set stop block for possible realloc */
5085 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005086 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005087 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005088 trg->augment = calloc(c_aug, sizeof *trg->augment);
5089 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005090 LOGMEM;
5091 goto error;
5092 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005093 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005094 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005095 trg->features = calloc(c_ftrs, sizeof *trg->features);
5096 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005097 LOGMEM;
5098 goto error;
5099 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005100 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005101 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005102 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5103 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005104 LOGMEM;
5105 goto error;
5106 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005107 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005108
Michal Vasko2f7925f2015-10-21 15:06:56 +02005109 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5110 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005111 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005112 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5113 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 if (r) {
5115 goto error;
5116 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005117
Radek Krejci1d82ef62015-08-07 14:44:40 +02005118 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005119 memset(&inc, 0, sizeof inc);
5120 /* 1) pass module, not trg, since we want to pass the main module
5121 * 2) we cannot pass directly the structure in the array since
5122 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005123 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005124 if (!r) {
5125 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005126 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5127 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005128 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005129 goto error;
5130 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005131
Radek Krejci1d82ef62015-08-07 14:44:40 +02005132 } else if (!strcmp(child->name, "revision")) {
5133 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005134 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005135 goto error;
5136 }
Radek Krejcic071c542016-01-27 14:57:51 +01005137 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005138 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005139 for (i = 0; i < trg->rev_size; i++) {
5140 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005141 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5142 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005143 }
5144 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005145
Radek Krejci1d82ef62015-08-07 14:44:40 +02005146 LY_TREE_FOR(child->child, child2) {
5147 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005148 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005149 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005150 goto error;
5151 }
Radek Krejcic071c542016-01-27 14:57:51 +01005152 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5153 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 goto error;
5155 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005156 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005157 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005158 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005159 goto error;
5160 }
Radek Krejcic071c542016-01-27 14:57:51 +01005161 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5162 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005163 goto error;
5164 }
5165 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005166 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 goto error;
5168 }
5169 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005172 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005174 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005175 if (!value) {
5176 LOGMEM;
5177 goto error;
5178 }
Radek Krejcic071c542016-01-27 14:57:51 +01005179 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5180 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005182
Radek Krejci749190d2016-02-18 16:26:25 +01005183 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005184 value = trg->rev[0].dsc;
5185 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5186 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005187 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005188
Radek Krejci749190d2016-02-18 16:26:25 +01005189 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005190 value = trg->rev[0].ref;
5191 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5192 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005193 }
5194 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005195
Radek Krejcic071c542016-01-27 14:57:51 +01005196 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005197
Radek Krejci1d82ef62015-08-07 14:44:40 +02005198 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005199 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5200 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005201 if (r) {
5202 goto error;
5203 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005204
Radek Krejci1d82ef62015-08-07 14:44:40 +02005205 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005206 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5207 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005208 if (r) {
5209 goto error;
5210 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005211
Radek Krejci1d82ef62015-08-07 14:44:40 +02005212 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005213 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5214 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005215 if (r) {
5216 goto error;
5217 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005218
Radek Krejci1d82ef62015-08-07 14:44:40 +02005219 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005220 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5221 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005222 if (r) {
5223 goto error;
5224 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005225 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5226 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005229 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005230
Radek Krejcib8f98c12016-06-24 10:30:46 +02005231 if (!submodule) {
5232 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005233 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005234 if (module->inc_size) {
5235 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5236 if (!module->inc) {
5237 LOGMEM;
5238 goto error;
5239 }
5240 }
5241 if (module->imp_size) {
5242 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5243 if (!module->imp) {
5244 LOGMEM;
5245 goto error;
5246 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005247 }
5248 }
Radek Krejcic071c542016-01-27 14:57:51 +01005249
Radek Krejcif5be10f2015-06-16 13:29:36 +02005250 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005251 * refer to them. Submodule's data nodes are stored in the
5252 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005253 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005254 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005255 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005256 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 goto error;
5258 }
Radek Krejci74705112015-06-05 10:25:44 +02005259
Michal Vasko345da0a2015-12-02 10:35:55 +01005260 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005261 }
Radek Krejci74705112015-06-05 10:25:44 +02005262
Radek Krejcif5be10f2015-06-16 13:29:36 +02005263 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005264 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005265
Radek Krejci1d82ef62015-08-07 14:44:40 +02005266 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005267 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005268 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005269 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005270 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005271 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005272 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005273 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005274 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005275 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005276 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005277 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005278 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005279 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005280 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005281 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005282 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005283 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005284 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005285 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005286 goto error;
5287 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005288
Michal Vasko345da0a2015-12-02 10:35:55 +01005289 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005290 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005291
Michal Vasko2f7925f2015-10-21 15:06:56 +02005292 /* ... and finally augments (last, so we can augment our data, for instance) */
5293 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005294 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5295 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005296
Michal Vasko2f7925f2015-10-21 15:06:56 +02005297 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005298 goto error;
5299 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005300 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005301 }
5302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005303 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005304
5305error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005306 /* cleanup */
5307 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005308 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 }
5310 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005311 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005313 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005314 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005315 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005317 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005318}
5319
Michal Vasko0d343d12015-08-24 14:57:36 +02005320/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005321struct lys_submodule *
5322yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005323{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005325 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005326 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005327
Michal Vasko5a721fd2016-02-16 12:16:48 +01005328 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005329
Radek Krejci722b0072016-02-01 17:09:45 +01005330 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005331 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005332 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005335 /* check root element */
5336 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005337 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 goto error;
5339 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005341 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005342 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 goto error;
5344 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005345
Michal Vasko5a721fd2016-02-16 12:16:48 +01005346 submodule = calloc(1, sizeof *submodule);
5347 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 LOGMEM;
5349 goto error;
5350 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005351
Michal Vasko5a721fd2016-02-16 12:16:48 +01005352 submodule->ctx = module->ctx;
5353 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5354 submodule->type = 1;
5355 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005356
Michal Vasko5a721fd2016-02-16 12:16:48 +01005357 LOGVRB("Reading submodule \"%s\".", submodule->name);
5358 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005359 goto error;
5360 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005361
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005362 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005363 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005364
Michal Vasko5a721fd2016-02-16 12:16:48 +01005365 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005366 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005367
5368error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005369 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005370 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005371 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005372
Michal Vasko5a721fd2016-02-16 12:16:48 +01005373 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005374 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005375 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005376 }
5377
Michal Vasko5a721fd2016-02-16 12:16:48 +01005378 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005379
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005380 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5381 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005382 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005383 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005384}
5385
Michal Vasko0d343d12015-08-24 14:57:36 +02005386/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005387struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005388yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005389{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005391 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005392 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005393 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005394 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005395
Radek Krejcic071c542016-01-27 14:57:51 +01005396 unres = calloc(1, sizeof *unres);
5397 if (!unres) {
5398 LOGMEM;
5399 return NULL;
5400 }
5401
Radek Krejci722b0072016-02-01 17:09:45 +01005402 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005403 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005404 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005407 /* check root element */
5408 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005409 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005410 goto error;
5411 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005413 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005414 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 goto error;
5416 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005418 module = calloc(1, sizeof *module);
5419 if (!module) {
5420 LOGMEM;
5421 goto error;
5422 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005424 module->ctx = ctx;
5425 module->name = lydict_insert(ctx, value, strlen(value));
5426 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005427 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005428
Michal Vasko9f258e42016-02-11 11:36:27 +01005429 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005430 if (read_sub_module(module, NULL, yin, unres)) {
5431 goto error;
5432 }
5433
5434 /* resolve rest of unres items */
5435 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005436 goto error;
5437 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005438
Radek Krejciff4874d2016-03-07 12:30:50 +01005439 if (revision) {
5440 /* check revision of the parsed model */
5441 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005442 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5443 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005444 goto error;
5445 }
5446 }
5447
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005448 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005449 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005450 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005451
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005452 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005453 if (!module->implemented) {
5454 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5455 }
Michal Vasko26055752016-05-03 11:36:31 +02005456 if (lys_module_set_implement(module)) {
5457 goto error;
5458 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005459
Michal Vasko26055752016-05-03 11:36:31 +02005460 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5461 goto error;
5462 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005463 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005464 if (!module->inc[i].submodule) {
5465 continue;
5466 }
Michal Vasko26055752016-05-03 11:36:31 +02005467 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5468 goto error;
5469 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005470 }
5471 }
5472
Michal Vasko345da0a2015-12-02 10:35:55 +01005473 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005474 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005475 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005476 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005477
5478error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005479 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005480 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005481 unres_schema_free(module, &unres);
5482
5483 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005484 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005485 return NULL;
5486 }
5487
5488 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005489
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005490 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005491 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005492 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005493}