blob: 9e7e01f9be985792d06c3e2e7b7df6349a28605b [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;
244 struct lys_type_bit bit;
Radek Krejcifc8d8322016-06-24 11:23:23 +0200245 int i, j, rc, val_set;
Radek Krejcidc008d72016-02-17 13:12:14 +0100246 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200247 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200248 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200249
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200250 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100251 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200252 if (!value) {
253 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200254 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200255
256 i = parse_identifier(value);
257 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100258 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100259 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200260 goto error;
261 }
262 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100263 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200264 if (value[i]) {
265 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100266 name += i;
267 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100268 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100269 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200270 goto error;
271 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200272 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100273 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200274 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200275
Radek Krejci225376f2016-02-16 17:36:22 +0100276 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200277 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100278 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200279 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200280 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100281
282 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200283 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200284 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200285 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100286 ret = EXIT_FAILURE;
287 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200288 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200289 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200290 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200291
Radek Krejcicf509982015-12-15 09:22:44 +0100292 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100293 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100294 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100295 return -1;
296 }
297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200298 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200299 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200300 /* RFC 6020 9.7.4 - bit */
301
302 /* get bit specifications, at least one must be present */
303 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200304 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
305 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100306 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200307 continue;
308 }
309
Radek Krejci994b6f62015-06-18 16:47:27 +0200310 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200311 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200312 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100313 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200314 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200315 }
316 }
Radek Krejciac781922015-07-09 15:35:14 +0200317 if (!type->der->type.der && !type->info.bits.count) {
318 /* type is derived directly from buit-in bits type and bit statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100319 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200320 goto error;
321 }
Radek Krejciac781922015-07-09 15:35:14 +0200322 if (type->der->type.der && type->info.bits.count) {
323 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100324 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200325 goto error;
326 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200327
328 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100329 if (!type->info.bits.bit) {
330 LOGMEM;
331 goto error;
332 }
Radek Krejci73adb602015-07-02 18:07:40 +0200333 p = 0;
334 i = -1;
335 LY_TREE_FOR(yin->child, next) {
336 i++;
337
338 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100339 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100340 goto error;
341 }
342
Radek Krejci994b6f62015-06-18 16:47:27 +0200343 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200344 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200345 type->info.bits.count = i + 1;
346 goto error;
347 }
348
349 /* check the name uniqueness */
350 for (j = 0; j < i; j++) {
351 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100352 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200353 type->info.bits.count = i + 1;
354 goto error;
355 }
356 }
357
Radek Krejci0d70c372015-07-02 16:23:10 +0200358 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200359 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200360 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
361 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200362 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200363 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200364
Radek Krejci0d70c372015-07-02 16:23:10 +0200365 if (!strcmp(node->name, "position")) {
366 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200367 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200368
369 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200370 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100371 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200372 type->info.bits.count = i + 1;
373 goto error;
374 }
375 type->info.bits.bit[i].pos = (uint32_t)p_;
376
377 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200378 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200379 p = type->info.bits.bit[i].pos;
380 p++;
381 } else {
382 /* check that the value is unique */
383 for (j = 0; j < i; j++) {
384 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100385 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100386 type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200387 type->info.bits.count = i + 1;
388 goto error;
389 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200390 }
391 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200392 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100393 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200394 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200395 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200396 }
397 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200398 /* assign value automatically */
399 if (p > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100400 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200401 type->info.bits.count = i + 1;
402 goto error;
403 }
404 type->info.bits.bit[i].pos = (uint32_t)p;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100405 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci994b6f62015-06-18 16:47:27 +0200406 p++;
407 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200408
409 /* keep them ordered by position */
410 j = i;
411 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
412 /* switch them */
413 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
414 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
415 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
416 j--;
417 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200418 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200419 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200421 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200422 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200423 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200424 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
425 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200426 continue;
427 }
428
Radek Krejcif9401c32015-06-26 16:47:36 +0200429 if (!strcmp(node->name, "range")) {
430 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100431 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200432 goto error;
433 }
434
435 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200436 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100437 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200438 goto error;
439 }
440 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100441 if (!type->info.dec64.range) {
442 LOGMEM;
443 goto error;
444 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200445 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
446
447 /* get possible substatements */
448 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
449 goto error;
450 }
451 } else if (!strcmp(node->name, "fraction-digits")) {
452 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100453 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200454 goto error;
455 }
456 GETVAL(value, node, "value");
457 v = strtol(value, NULL, 10);
458
459 /* range check */
460 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100461 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200462 goto error;
463 }
464 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200465 type->info.dec64.div = 10;
466 for (i = 1; i < v; i++) {
467 type->info.dec64.div *= 10;
468 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200469 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100470 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200471 goto error;
472 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200473 }
474
475 /* mandatory sub-statement(s) check */
476 if (!type->info.dec64.dig && !type->der->type.der) {
477 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100478 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200479 goto error;
480 }
Radek Krejci7511f402015-07-10 09:56:30 +0200481 if (type->info.dec64.dig && type->der->type.der) {
482 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100483 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200484 goto error;
485 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200486 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200488 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200489 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200490
Radek Krejci994b6f62015-06-18 16:47:27 +0200491 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200492 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200493 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
494 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100495 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200496 continue;
497 }
498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200500 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200501 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100502 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200503 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200504 }
505 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200506 if (!type->der->type.der && !type->info.enums.count) {
507 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Radek Krejci48464ed2016-03-17 15:44:09 +0100508 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200509 goto error;
510 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200511 if (type->der->type.der && type->info.enums.count) {
512 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100513 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200514 goto error;
515 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200516
Radek Krejci1574a8d2015-08-03 14:16:52 +0200517 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100518 if (!type->info.enums.enm) {
519 LOGMEM;
520 goto error;
521 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200522
523 val_set = v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200524 i = -1;
525 LY_TREE_FOR(yin->child, next) {
526 i++;
527
528 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100529 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100530 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
531 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100532 goto error;
533 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200534 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200535 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200536 type->info.enums.count = i + 1;
537 goto error;
538 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200540 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200541 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200542 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100543 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200544 type->info.enums.count = i + 1;
545 goto error;
546 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200547
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200548 /* check the name uniqueness */
549 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200550 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100551 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552 type->info.enums.count = i + 1;
553 goto error;
554 }
555 }
Radek Krejci04581c62015-05-22 21:24:00 +0200556
Radek Krejci73adb602015-07-02 18:07:40 +0200557 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200558 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
559 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200561 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200562
Radek Krejci0d70c372015-07-02 16:23:10 +0200563 if (!strcmp(node->name, "value")) {
564 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200565 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200566
567 /* range check */
568 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100569 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200570 type->info.enums.count = i + 1;
571 goto error;
572 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200573 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200574
575 /* keep the highest enum value for automatic increment */
Radek Krejcifc8d8322016-06-24 11:23:23 +0200576 if (!val_set || type->info.enums.enm[i].value > v) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200577 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 v++;
579 } else {
580 /* check that the value is unique */
581 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200582 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100583 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +0100584 type->info.enums.enm[i].value, type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200585 type->info.enums.count = i + 1;
586 goto error;
587 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200588 }
589 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200590 val_set = 1;
Radek Krejci0d70c372015-07-02 16:23:10 +0200591 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100592 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200593 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200595 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200596 if (!val_set) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200597 /* assign value automatically */
598 if (v > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100599 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200600 type->info.enums.count = i + 1;
601 goto error;
602 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200603 type->info.enums.enm[i].value = v;
Michal Vasko3f053ef2016-02-12 14:27:13 +0100604 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 v++;
606 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200607 }
608 break;
609
610 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200611 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200612
613 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200614 LY_TREE_FOR_SAFE(yin->child, next, node) {
615 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
616 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100617 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200618 continue;
619 }
620
Michal Vaskoe29c6622015-11-27 15:02:31 +0100621 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100622 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200623 goto error;
624 }
625 }
626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200628 if (type->der->type.der) {
629 /* this is just a derived type with no base specified/required */
630 break;
631 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100632 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200633 goto error;
634 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100636 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200637 goto error;
638 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200639 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100640 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100641 value = transform_schema2json(module, value);
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100642 if (!value) {
643 goto error;
644 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100645 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Radek Krejcic5989d42016-02-17 11:16:38 +0100646 lydict_remove(module->ctx, value);
647
648 if (rc == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200649 goto error;
650 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200651 break;
652
653 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200654 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200655 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200656 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
657 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200658 continue;
659 }
660
Radek Krejciaf351422015-06-19 14:49:38 +0200661 if (!strcmp(node->name, "require-instance")) {
662 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100663 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200664 goto error;
665 }
666 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200667 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200668 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200669 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200670 type->info.inst.req = -1;
671 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100672 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200673 goto error;
674 }
675 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100676 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200677 goto error;
678 }
Radek Krejciaf351422015-06-19 14:49:38 +0200679 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200681 break;
682
Radek Krejcif2860132015-06-20 12:37:20 +0200683 case LY_TYPE_BINARY:
684 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 case LY_TYPE_INT8:
686 case LY_TYPE_INT16:
687 case LY_TYPE_INT32:
688 case LY_TYPE_INT64:
689 case LY_TYPE_UINT8:
690 case LY_TYPE_UINT16:
691 case LY_TYPE_UINT32:
692 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200693 /* RFC 6020 9.2.4 - range */
694
695 /* length and range are actually the same restriction, so process
696 * them by this common code, we just need to differ the name and
697 * structure where the information will be stored
698 */
699 if (type->base == LY_TYPE_BINARY) {
700 restr = &type->info.binary.length;
701 name = "length";
702 } else {
703 restr = &type->info.num.range;
704 name = "range";
705 }
706
Radek Krejci73adb602015-07-02 18:07:40 +0200707 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200708 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
709 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200710 continue;
711 }
712
Radek Krejcif2860132015-06-20 12:37:20 +0200713 if (!strcmp(node->name, name)) {
714 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100715 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200716 goto error;
717 }
718
719 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200720 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100721 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200722 goto error;
723 }
724 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100725 if (!(*restr)) {
726 LOGMEM;
727 goto error;
728 }
Radek Krejcif2860132015-06-20 12:37:20 +0200729 (*restr)->expr = lydict_insert(module->ctx, value, 0);
730
731 /* get possible substatements */
732 if (read_restr_substmt(module->ctx, *restr, node)) {
733 goto error;
734 }
735 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100736 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200737 goto error;
738 }
Radek Krejcif2860132015-06-20 12:37:20 +0200739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200740 break;
741
742 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200743 /* flag resolving for later use */
744 if (!tpdftype) {
745 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
746 if (siter) {
747 /* just a flag - do not resolve */
748 tpdftype = 1;
749 }
750 }
751
Radek Krejcidc4c1412015-06-19 15:39:54 +0200752 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200753 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200754 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
755 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200756 continue;
757 }
758
Michal Vasko88c29542015-11-27 14:57:53 +0100759 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200760 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100761 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200762 goto error;
763 }
764
765 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200766 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +0100767 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200768 if (!type->info.lref.path) {
769 goto error;
770 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200771
772 /* try to resolve leafref path only when this is instantiated
773 * leaf, so it is not:
774 * - typedef's type,
775 * - in grouping definition,
776 * - just instantiated in a grouping definition,
777 * because in those cases the nodes referenced in path might not be present
778 * and it is not a bug. */
779 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200780 goto error;
781 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200782
Radek Krejcidc4c1412015-06-19 15:39:54 +0200783 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100784 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200785 goto error;
786 }
Radek Krejci73adb602015-07-02 18:07:40 +0200787 }
788
Radek Krejci742be352016-07-17 12:18:54 +0200789 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200790 if (!type->der->type.der) {
791 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +0200792 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200793 } else {
794 /* copy leafref definition into the derived type */
795 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
796 /* and resolve the path at the place we are (if not in grouping/typedef) */
797 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
798 goto error;
799 }
800
801 /* add pointer to leafref target, only on leaves (not in typedefs) */
802 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
803 goto error;
804 }
Michal Vasko01c6fd22016-05-20 11:43:05 +0200805 }
Radek Krejcidc4c1412015-06-19 15:39:54 +0200806 }
Radek Krejci742be352016-07-17 12:18:54 +0200807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200808 break;
809
810 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200811 /* RFC 6020 9.4.4 - length */
812 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200813 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200814 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200815 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
816 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100817 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200818 continue;
819 }
820
Radek Krejci3733a802015-06-19 13:43:21 +0200821 if (!strcmp(node->name, "length")) {
822 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100823 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +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, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200830 goto error;
831 }
832 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100833 if (!type->info.str.length) {
834 LOGMEM;
835 goto error;
836 }
Radek Krejci3733a802015-06-19 13:43:21 +0200837 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
838
Radek Krejci5fbc9162015-06-19 14:11:11 +0200839 /* get possible sub-statements */
840 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200841 goto error;
842 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100843 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200844 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200845 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200846 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100847 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200848 goto error;
849 }
850 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200851 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200852 if (i) {
853 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100854 if (!type->info.str.patterns) {
855 LOGMEM;
856 goto error;
857 }
Radek Krejci73adb602015-07-02 18:07:40 +0200858 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100859 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200860
Michal Vasko0aee5c12016-06-17 14:27:26 +0200861 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +0200862 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +0200863 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +0200864 goto error;
865 }
Michal Vasko69068852015-07-13 14:34:31 +0200866
Radek Krejci73adb602015-07-02 18:07:40 +0200867 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200868
869 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100870 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200871 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200872 goto error;
873 }
Radek Krejci73adb602015-07-02 18:07:40 +0200874 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200875 }
876 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200877 break;
878
879 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200880 /* RFC 6020 7.4 - type */
881 /* count number of types in union */
882 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200883 LY_TREE_FOR_SAFE(yin->child, next, node) {
884 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
885 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100886 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200887 continue;
888 }
889
Radek Krejcie4c366b2015-07-02 10:11:31 +0200890 if (!strcmp(node->name, "type")) {
891 i++;
892 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100893 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200894 goto error;
895 }
896 }
897
898 if (!i) {
899 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100900 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200901 break;
902 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100903 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200904 goto error;
905 }
906
907 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200908 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100909 if (!type->info.uni.types) {
910 LOGMEM;
911 goto error;
912 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200913 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200914 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100915 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200916 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +0100917 if (!rc) {
918 type->info.uni.count++;
919
920 /* union's type cannot be empty or leafref */
921 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100922 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100923 rc = -1;
924 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100925 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
Michal Vasko88c29542015-11-27 14:57:53 +0100926 rc = -1;
927 }
928 }
929 if (rc) {
930 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
931 for (i = 0; i < type->info.uni.count; ++i) {
932 lys_type_free(module->ctx, &type->info.uni.types[i]);
933 }
934 free(type->info.uni.types);
935 type->info.uni.types = NULL;
936 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +0200937 type->der = NULL;
938 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +0100939
940 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +0100941 ret = EXIT_FAILURE;
942 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100943 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200944 goto error;
945 }
Michal Vasko88c29542015-11-27 14:57:53 +0100946 }
947 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200948
Michal Vasko88c29542015-11-27 14:57:53 +0100949 case LY_TYPE_BOOL:
950 case LY_TYPE_EMPTY:
951 /* no sub-statement allowed */
952 LY_TREE_FOR(yin->child, node) {
953 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100954 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200955 goto error;
956 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200957 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200958 break;
959
960 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100961 LOGINT;
962 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200963 }
964
965 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200966
967error:
Radek Krejcidc008d72016-02-17 13:12:14 +0100968 if (type->module_name) {
969 lydict_remove(module->ctx, type->module_name);
970 type->module_name = NULL;
971 }
972 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200973}
974
Michal Vasko0d343d12015-08-24 14:57:36 +0200975/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200976static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200977fill_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 +0200978{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100980 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +0100981 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200983 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100984 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200985 goto error;
986 }
987 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200989 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +0100990 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200991 goto error;
992 }
Radek Krejcieac35532015-05-31 19:09:15 +0200993
Michal Vasko88c29542015-11-27 14:57:53 +0100994 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200995 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
996 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200997 continue;
998 }
999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001000 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001001 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001002 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 goto error;
1004 }
Michal Vasko88c29542015-11-27 14:57:53 +01001005 /* HACK for unres */
1006 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001007 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001008 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001009 goto error;
1010 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001011 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 } else if (!strcmp(node->name, "default")) {
1013 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001014 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001015 goto error;
1016 }
1017 GETVAL(value, node, "value");
1018 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1019 } else if (!strcmp(node->name, "units")) {
1020 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001021 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001022 goto error;
1023 }
1024 GETVAL(value, node, "name");
1025 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1026 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001027 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001028 goto error;
1029 }
1030 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001032 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001033 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001034 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001035 goto error;
1036 }
Radek Krejcieac35532015-05-31 19:09:15 +02001037
Michal Vasko478c4652016-07-21 12:55:01 +02001038 /* check default value (if not defined, there still could be some restrictions
1039 * that need to be checked against a default value from a derived type) */
1040 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1041 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001042 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001045
1046error:
1047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001048 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001049}
1050
Michal Vasko0d343d12015-08-24 14:57:36 +02001051/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001052static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001053fill_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 +02001054{
1055 const char *value;
1056 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001057 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001058
Radek Krejcib05774c2015-06-18 13:52:59 +02001059 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001060 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001061 goto error;
1062 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001063 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001064 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001065
Radek Krejci76512572015-08-04 09:47:08 +02001066 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001067 goto error;
1068 }
1069
1070 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001071 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1072 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001073 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001074 continue;
1075 }
1076
Radek Krejci3cf9e222015-06-18 11:37:50 +02001077 if (!strcmp(child->name, "if-feature")) {
1078 c++;
1079 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001080 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001081 goto error;
1082 }
1083 }
1084
1085 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001086 f->iffeature = calloc(c, sizeof *f->iffeature);
1087 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001088 LOGMEM;
1089 goto error;
1090 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001091 }
Radek Krejci73adb602015-07-02 18:07:40 +02001092 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001093 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1094 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001095 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001096 goto error;
1097 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001098 }
1099
Radek Krejcic79c6b12016-07-26 15:11:49 +02001100 /* check for circular dependencies */
1101 if (f->iffeature_size) {
1102 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1103 goto error;
1104 }
1105 }
1106
Radek Krejci3cf9e222015-06-18 11:37:50 +02001107 return EXIT_SUCCESS;
1108
1109error:
1110
1111 return EXIT_FAILURE;
1112}
1113
Michal Vasko0d343d12015-08-24 14:57:36 +02001114/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115static int
Radek Krejcib8048692015-08-05 13:36:34 +02001116fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001117{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001121 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001122 if (!must->expr) {
1123 goto error;
1124 }
Radek Krejci48464ed2016-03-17 15:44:09 +01001125 if (lyxp_syntax_check(must->expr)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01001126 goto error;
1127 }
Radek Krejci800af702015-06-02 13:46:01 +02001128
Radek Krejci41726f92015-06-19 13:11:05 +02001129 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001130
Michal Vasko77dc5652016-02-15 12:32:42 +01001131error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001133}
1134
Radek Krejci581ce772015-11-10 17:22:40 +01001135static int
Michal Vasko88c29542015-11-27 14:57:53 +01001136fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1137 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001138{
1139 int i, j;
1140 const char *value, *vaux;
1141
1142 /* get unique value (list of leafs supposed to be unique */
1143 GETVAL(value, yin, "tag");
1144
1145 /* count the number of unique leafs in the value */
1146 vaux = value;
1147 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001148 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001149 while (isspace(*vaux)) {
1150 vaux++;
1151 }
1152 }
1153 unique->expr_size++;
1154 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001155 if (!unique->expr) {
1156 LOGMEM;
1157 goto error;
1158 }
Radek Krejci581ce772015-11-10 17:22:40 +01001159
1160 for (i = 0; i < unique->expr_size; i++) {
1161 vaux = strpbrk(value, " \t\n");
1162 if (!vaux) {
1163 /* the last token, lydict_insert() will count its size on its own */
1164 vaux = value;
1165 }
1166
1167 /* store token into unique structure */
1168 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1169
1170 /* check that the expression does not repeat */
1171 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001172 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001173 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1174 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001175 goto error;
1176 }
1177 }
1178
1179 /* try to resolve leaf */
1180 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +02001181 if (unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i]) == -1){
1182 goto error;
1183 }
Radek Krejci581ce772015-11-10 17:22:40 +01001184 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001185 if (resolve_unique(parent, unique->expr[i])) {
Radek Krejci581ce772015-11-10 17:22:40 +01001186 goto error;
1187 }
1188 }
1189
1190 /* move to next token */
1191 value = vaux;
1192 while(isspace(*value)) {
1193 value++;
1194 }
1195 }
1196
1197 return EXIT_SUCCESS;
1198
1199error:
1200 return EXIT_FAILURE;
1201}
1202
Michal Vasko0d343d12015-08-24 14:57:36 +02001203/* logs directly
1204 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001205 * type: 0 - min, 1 - max
1206 */
1207static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001208deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001209{
1210 const char *value;
1211 char *endptr;
1212 unsigned long val;
1213 uint32_t *ui32val;
1214
Michal Vaskof7e57d52016-03-07 11:31:09 +01001215 /* del min/max is forbidden */
1216 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001217 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001218 goto error;
1219 }
1220
Radek Krejcieb00f512015-07-01 16:44:58 +02001221 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001222 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001223 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001224 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001225 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001226 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001227 }
Radek Krejci76512572015-08-04 09:47:08 +02001228 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001229 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001230 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001231 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001232 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001233 }
1234 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001235 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1236 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001237 goto error;
1238 }
1239
1240 GETVAL(value, node, "value");
1241 while (isspace(value[0])) {
1242 value++;
1243 }
1244
Radek Krejci0d7b2472016-02-12 11:11:03 +01001245 if (type && !strcmp(value, "unbounded")) {
1246 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001247 d->max_set = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001248 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001249 /* convert it to uint32_t */
1250 errno = 0;
1251 endptr = NULL;
1252 val = strtoul(value, &endptr, 10);
1253 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001254 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001255 goto error;
1256 }
1257 if (type) {
1258 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001259 d->max_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001260 } else {
1261 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001262 d->min_set = 1;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001263 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001264 }
1265
1266 if (d->mod == LY_DEVIATE_ADD) {
1267 /* check that there is no current value */
1268 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001269 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1270 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 goto error;
1272 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001273 } else if (d->mod == LY_DEVIATE_RPL) {
1274 /* unfortunately, there is no way to check reliably that there
1275 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001276 }
1277
Michal Vaskof7e57d52016-03-07 11:31:09 +01001278 /* add (already checked) and replace */
1279 /* set new value specified in deviation */
1280 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001281
1282 return EXIT_SUCCESS;
1283
1284error:
1285
1286 return EXIT_FAILURE;
1287}
1288
Michal Vasko0d343d12015-08-24 14:57:36 +02001289/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001290static int
Michal Vasko88c29542015-11-27 14:57:53 +01001291fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1292 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001293{
1294 const char *value, **stritem;
1295 struct lyxml_elem *next, *child, *develem;
1296 int c_dev = 0, c_must, c_uniq;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001297 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001298 int i, j, rc;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001299 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001300 struct lys_deviate *d = NULL;
Michal Vasko60f4b452016-02-12 11:02:55 +01001301 struct lys_node *node = NULL, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001302 struct lys_node_choice *choice = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001303 struct lys_node_leaf *leaf = NULL, **leaf_dflt_check = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001304 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001305 struct lys_type *t = NULL;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001306 uint8_t *trg_must_size = NULL, leaf_dflt_check_count = 0;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001307 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001308 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001309
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001310 ctx = module->ctx;
1311
Radek Krejcieb00f512015-07-01 16:44:58 +02001312 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001313 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001314 if (!dev->target_name) {
1315 goto error;
1316 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001317
1318 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001319 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1320 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001321 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001322 goto error;
1323 }
Radek Krejcic4283442016-04-22 09:19:27 +02001324 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001325 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1326 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001327 goto error;
1328 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001329 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
Radek Krejcieb00f512015-07-01 16:44:58 +02001330
1331 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001332 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1333 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001334 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001335 continue;
1336 }
1337
Radek Krejcieb00f512015-07-01 16:44:58 +02001338 if (!strcmp(child->name, "description")) {
1339 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001340 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001341 goto error;
1342 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001343 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001344 if (!dev->dsc) {
1345 goto error;
1346 }
1347 } else if (!strcmp(child->name, "reference")) {
1348 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001349 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001350 goto error;
1351 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001352 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001353 if (!dev->ref) {
1354 goto error;
1355 }
1356 } else if (!strcmp(child->name, "deviate")) {
1357 c_dev++;
1358
Michal Vasko345da0a2015-12-02 10:35:55 +01001359 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001360 * further processed later
1361 */
1362 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001363
Radek Krejcieb00f512015-07-01 16:44:58 +02001364 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001365 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001366 goto error;
1367 }
1368
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001369 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001370 }
1371
1372 if (c_dev) {
1373 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001374 if (!dev->deviate) {
1375 LOGMEM;
1376 goto error;
1377 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001378 }
1379
1380 LY_TREE_FOR(yin->child, develem) {
1381 /* init */
1382 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001383 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001384 c_must = 0;
1385 c_uniq = 0;
1386
1387 /* get deviation type */
1388 GETVAL(value, develem, "value");
1389 if (!strcmp(value, "not-supported")) {
1390 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1391 /* no property expected in this case */
1392 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001393 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001394 goto error;
1395 }
1396
Radek Krejci5b917642015-07-02 09:03:13 +02001397 /* and neither any other deviate statement is expected,
1398 * not-supported deviation must be the only deviation of the target
1399 */
1400 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001401 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1402 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001403 goto error;
1404 }
1405
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001406 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001407 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1408 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1409 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001410 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1411 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001412 goto error;
1413 }
1414 }
1415 }
Radek Krejci5b917642015-07-02 09:03:13 +02001416
Michal Vaskoff006c12016-02-17 11:15:19 +01001417 /* unlink and store the original node */
1418 lys_node_unlink(dev_target);
1419 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001420
Radek Krejci5b917642015-07-02 09:03:13 +02001421 dev->deviate_size = 1;
1422 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001423 } else if (!strcmp(value, "add")) {
1424 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1425 } else if (!strcmp(value, "replace")) {
1426 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1427 } else if (!strcmp(value, "delete")) {
1428 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1429 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001430 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001431 goto error;
1432 }
1433 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001434 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001435
Michal Vaskoff006c12016-02-17 11:15:19 +01001436 /* store a shallow copy of the original node */
1437 if (!dev->orig_node) {
1438 memset(&tmp_unres, 0, sizeof tmp_unres);
1439 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1440 /* just to be safe */
1441 if (tmp_unres.count) {
1442 LOGINT;
1443 goto error;
1444 }
1445 }
1446
Radek Krejcieb00f512015-07-01 16:44:58 +02001447 /* process deviation properties */
1448 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001449 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1450 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001451 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001452 continue;
1453 }
1454
Radek Krejcieb00f512015-07-01 16:44:58 +02001455 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001456 if (d->flags & LYS_CONFIG_MASK) {
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 }
1460
1461 /* for we deviate from RFC 6020 and allow config property even it is/is not
1462 * specified in the target explicitly since config property inherits. So we expect
1463 * that config is specified in every node. But for delete, we check that the value
1464 * is the same as here in deviation
1465 */
1466 GETVAL(value, child, "value");
1467 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001468 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001469 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001470 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001472 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001473 goto error;
1474 }
1475
1476 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001477 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001478 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001479 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001480 } else { /* add and replace are the same in this case */
1481 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001482 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001483
1484 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001485 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 }
1487 } else if (!strcmp(child->name, "default")) {
1488 if (d->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001489 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001490 goto error;
1491 }
1492 GETVAL(value, child, "value");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001493 d->dflt = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001494
Michal Vasko60f4b452016-02-12 11:02:55 +01001495 if (dev_target->nodetype == LYS_CHOICE) {
1496 choice = (struct lys_node_choice *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001497
1498 if (d->mod == LY_DEVIATE_ADD) {
1499 /* check that there is no current value */
1500 if (choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001501 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1502 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001503 goto error;
1504 }
Radek Krejci9e8c10c2016-04-05 16:36:52 +02001505 /* check collision with mandatory */
1506 if (choice->flags & LYS_MAND_TRUE) {
1507 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1508 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1509 "Adding the \"default\" statement is forbidden on choice with the \"mandatory\" statement.");
1510 goto error;
1511 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001512 } else if (d->mod == LY_DEVIATE_RPL) {
1513 /* check that there was a value before */
1514 if (!choice->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001515 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1516 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001517 goto error;
1518 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 }
1520
Michal Vasko3edeaf72016-02-11 13:17:43 +01001521 rc = resolve_choice_default_schema_nodeid(d->dflt, choice->child, (const struct lys_node **)&node);
Michal Vasko9bb061b2016-02-12 11:00:19 +01001522 if (rc || !node) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001523 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001524 goto error;
1525 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001526 if (d->mod == LY_DEVIATE_DEL) {
Michal Vasko60f4b452016-02-12 11:02:55 +01001527 if (!choice->dflt || (choice->dflt != node)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001528 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1529 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001530 goto error;
1531 }
1532 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001533 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001534 if (!choice->dflt) {
1535 /* default branch not found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001536 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001537 goto error;
1538 }
1539 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001540 } else if (dev_target->nodetype == LYS_LEAF) {
1541 leaf = (struct lys_node_leaf *)dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001542
1543 if (d->mod == LY_DEVIATE_ADD) {
1544 /* check that there is no current value */
1545 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001546 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1547 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001548 goto error;
1549 }
Radek Krejci841ec082016-04-05 13:05:17 +02001550 /* check collision with mandatory */
1551 if (leaf->flags & LYS_MAND_TRUE) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001552 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001553 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001554 "Adding the \"default\" statement is forbidden on leaf with the \"mandatory\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001555 goto error;
1556 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 }
1558
1559 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001560 if (!leaf->dflt || !ly_strequal(leaf->dflt, d->dflt, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001561 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1562 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 goto error;
1564 }
1565 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001566 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 leaf->dflt = NULL;
1568 } else { /* add (already checked) and replace */
1569 /* remove value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001570 lydict_remove(ctx, leaf->dflt);
Radek Krejcieb00f512015-07-01 16:44:58 +02001571
1572 /* set new value */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001573 leaf->dflt = lydict_insert(ctx, d->dflt, 0);
Michal Vasko43a1feb2016-03-07 12:03:02 +01001574
1575 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1576 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1577 if (!leaf_dflt_check) {
1578 LOGMEM;
1579 goto error;
1580 }
1581 leaf_dflt_check[leaf_dflt_check_count - 1] = leaf;
Radek Krejcieb00f512015-07-01 16:44:58 +02001582 }
1583 } else {
1584 /* invalid target for default value */
Radek Krejci48464ed2016-03-17 15:44:09 +01001585 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1586 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
1589 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001590 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001591 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001592 goto error;
1593 }
1594
1595 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001596 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001597 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1598 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001599 goto error;
1600 }
1601
1602 GETVAL(value, child, "value");
1603 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001604 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001605 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001606 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001608 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 goto error;
1610 }
1611
1612 if (d->mod == LY_DEVIATE_ADD) {
1613 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001614 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001615 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1616 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 goto error;
1618 }
Radek Krejci841ec082016-04-05 13:05:17 +02001619 /* check collision with default-stmt */
1620 if ((dev_target->nodetype == LYS_LEAF) && ((struct lys_node_leaf *)(dev_target))->dflt) {
Radek Krejci6052ada2016-04-05 16:37:51 +02001621 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
Radek Krejci841ec082016-04-05 13:05:17 +02001622 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
Radek Krejci6052ada2016-04-05 16:37:51 +02001623 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
Radek Krejci841ec082016-04-05 13:05:17 +02001624 goto error;
1625 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001626
Michal Vasko21be1b32016-03-07 12:31:34 +01001627 dev_target->flags |= d->flags & LYS_MAND_MASK;
1628 } else if (d->mod == LY_DEVIATE_RPL) {
1629 /* check that there was a value before */
1630 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001631 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1632 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001633 goto error;
1634 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001635
Michal Vasko21be1b32016-03-07 12:31:34 +01001636 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001637 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001638 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001639 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001640 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001641 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 }
1643 } else if (!strcmp(child->name, "min-elements")) {
1644 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001645 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 goto error;
1647 }
1648 f_min = 1;
1649
Michal Vasko60f4b452016-02-12 11:02:55 +01001650 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001651 goto error;
1652 }
1653 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001654 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001655 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001656 goto error;
1657 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001658 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001659
Michal Vasko60f4b452016-02-12 11:02:55 +01001660 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001661 goto error;
1662 }
1663 } else if (!strcmp(child->name, "must")) {
1664 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001665 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 continue;
1667 } else if (!strcmp(child->name, "type")) {
1668 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001669 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001670 goto error;
1671 }
1672
Michal Vaskof7e57d52016-03-07 11:31:09 +01001673 /* add, del type is forbidden */
1674 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001675 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001676 goto error;
1677 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001678 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001679 goto error;
1680 }
1681
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001683 if (dev_target->nodetype == LYS_LEAF) {
1684 t = &((struct lys_node_leaf *)dev_target)->type;
1685 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1686 t = &((struct lys_node_leaflist *)dev_target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001687 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001688 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1689 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001690 goto error;
1691 }
1692
Radek Krejcieb00f512015-07-01 16:44:58 +02001693 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001694 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001695 /* HACK for unres */
1696 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001697 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001698 goto error;
1699 }
1700 d->type = t;
Michal Vasko43a1feb2016-03-07 12:03:02 +01001701
1702 /* check leaf default later (type may not fit now, but default can be deviated later too) */
1703 if (dev_target->nodetype == LYS_LEAF) {
1704 leaf_dflt_check = ly_realloc(leaf_dflt_check, ++leaf_dflt_check_count * sizeof *leaf_dflt_check);
1705 if (!leaf_dflt_check) {
1706 LOGMEM;
1707 goto error;
1708 }
1709 leaf_dflt_check[leaf_dflt_check_count - 1] = (struct lys_node_leaf *)dev_target;
1710 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001711 } else if (!strcmp(child->name, "unique")) {
1712 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001713 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001714 continue;
1715 } else if (!strcmp(child->name, "units")) {
1716 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001717 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001718 goto error;
1719 }
1720
1721 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001722 if (dev_target->nodetype == LYS_LEAFLIST) {
1723 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1724 } else if (dev_target->nodetype == LYS_LEAF) {
1725 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001726 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001727 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1728 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 goto error;
1730 }
1731
1732 /* get units value */
1733 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001734 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001735
1736 /* apply to target */
1737 if (d->mod == LY_DEVIATE_ADD) {
1738 /* check that there is no current value */
1739 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001740 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1741 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001742 goto error;
1743 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001744
Michal Vasko21be1b32016-03-07 12:31:34 +01001745 *stritem = lydict_insert(ctx, value, 0);
1746 } else if (d->mod == LY_DEVIATE_RPL) {
1747 /* check that there was a value before */
1748 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001749 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1750 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001751 goto error;
1752 }
1753
1754 lydict_remove(ctx, *stritem);
1755 *stritem = lydict_insert(ctx, value, 0);
1756 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001757 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001758 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001759 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
1760 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 goto error;
1762 }
1763 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001764 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02001765 }
1766 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001767 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001768 goto error;
1769 }
1770
Michal Vasko88c29542015-11-27 14:57:53 +01001771 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001772 }
1773
1774 if (c_must) {
1775 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001776 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001777 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01001778 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1779 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 break;
Radek Krejci76512572015-08-04 09:47:08 +02001781 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01001782 trg_must = &((struct lys_node_container *)dev_target)->must;
1783 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001784 break;
Radek Krejci76512572015-08-04 09:47:08 +02001785 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001786 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1787 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 break;
Radek Krejci76512572015-08-04 09:47:08 +02001789 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01001790 trg_must = &((struct lys_node_list *)dev_target)->must;
1791 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001792 break;
Radek Krejci76512572015-08-04 09:47:08 +02001793 case LYS_ANYXML:
Michal Vasko60f4b452016-02-12 11:02:55 +01001794 trg_must = &((struct lys_node_anyxml *)dev_target)->must;
1795 trg_must_size = &((struct lys_node_anyxml *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001796 break;
1797 default:
Radek Krejci48464ed2016-03-17 15:44:09 +01001798 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1799 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001800 goto error;
1801 }
1802
1803 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001804 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001805 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001806 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 } else if (d->mod == LY_DEVIATE_ADD) {
1808 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001809 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001810 if (!d->must) {
1811 LOGMEM;
1812 goto error;
1813 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001814 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001815 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 d->must_size = c_must;
1817 } else { /* LY_DEVIATE_DEL */
1818 d->must = calloc(c_must, sizeof *d->must);
1819 }
Michal Vasko253035f2015-12-17 16:58:13 +01001820 if (!d->must) {
1821 LOGMEM;
1822 goto error;
1823 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 }
1825 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001826 /* replace unique is forbidden */
1827 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001828 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001829 goto error;
1830 }
1831
Radek Krejcieb00f512015-07-01 16:44:58 +02001832 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001833 if (dev_target->nodetype != LYS_LIST) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001834 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1835 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 goto error;
1837 }
1838
Michal Vasko60f4b452016-02-12 11:02:55 +01001839 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01001840 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001841 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001842 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001843 list->unique = d->unique;
1844 d->unique = &list->unique[list->unique_size];
1845 d->unique_size = c_uniq;
1846 } else { /* LY_DEVIATE_DEL */
1847 d->unique = calloc(c_uniq, sizeof *d->unique);
1848 }
Michal Vasko253035f2015-12-17 16:58:13 +01001849 if (!d->unique) {
1850 LOGMEM;
1851 goto error;
1852 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001853 }
1854
1855 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001856 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 if (!strcmp(child->name, "must")) {
1858 if (d->mod == LY_DEVIATE_DEL) {
1859 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1860 goto error;
1861 }
1862
1863 /* find must to delete, we are ok with just matching conditions */
1864 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001865 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001866 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001867 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001868 /* ... and maintain the array */
1869 (*trg_must_size)--;
1870 if (i != *trg_must_size) {
1871 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1872 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1873 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1874 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1875 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1876 }
1877 if (!(*trg_must_size)) {
1878 free(*trg_must);
1879 *trg_must = NULL;
1880 } else {
1881 (*trg_must)[*trg_must_size].expr = NULL;
1882 (*trg_must)[*trg_must_size].dsc = NULL;
1883 (*trg_must)[*trg_must_size].ref = NULL;
1884 (*trg_must)[*trg_must_size].eapptag = NULL;
1885 (*trg_must)[*trg_must_size].emsg = NULL;
1886 }
1887
1888 i = -1; /* set match flag */
1889 break;
1890 }
1891 }
1892 d->must_size++;
1893 if (i != -1) {
1894 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001895 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01001896 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01001897 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001898 goto error;
1899 }
1900 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01001901 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
1902 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001903 goto error;
1904 }
1905 (*trg_must_size)++;
1906 }
1907 } else if (!strcmp(child->name, "unique")) {
1908 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001909 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001910 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001911 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 goto error;
1913 }
1914
1915 /* find unique structures to delete */
1916 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001917 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001918 continue;
1919 }
1920
Radek Krejci581ce772015-11-10 17:22:40 +01001921 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001922 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 break;
1924 }
1925 }
1926
Radek Krejci581ce772015-11-10 17:22:40 +01001927 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001928 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001929 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001930 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01001931 }
1932 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001933 /* ... and maintain the array */
1934 list->unique_size--;
1935 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001936 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1937 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001938 }
1939
1940 if (!list->unique_size) {
1941 free(list->unique);
1942 list->unique = NULL;
1943 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001944 list->unique[list->unique_size].expr_size = 0;
1945 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001946 }
1947
1948 i = -1; /* set match flag */
1949 break;
1950 }
1951 }
1952
1953 d->unique_size++;
1954 if (i != -1) {
1955 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01001956 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
1957 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001958 goto error;
1959 }
1960 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01001961 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01001962 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001963 list->unique_size++;
1964 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001965 goto error;
1966 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001967 }
1968 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001969 }
1970 }
1971
Michal Vasko43a1feb2016-03-07 12:03:02 +01001972 /* now check whether default value, if any, matches the type */
1973 for (i = 0; i < leaf_dflt_check_count; ++i) {
1974 if (leaf_dflt_check[i]->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001975 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 +01001976 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001977 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
1978 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 +01001979 goto error;
1980 }
1981 }
1982 }
1983 free(leaf_dflt_check);
1984
Radek Krejcieb00f512015-07-01 16:44:58 +02001985 return EXIT_SUCCESS;
1986
1987error:
Michal Vasko34867132016-03-11 10:26:38 +01001988 free(leaf_dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02001989 return EXIT_FAILURE;
1990}
1991
Michal Vasko0d343d12015-08-24 14:57:36 +02001992/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001993static int
Radek Krejcib8048692015-08-05 13:36:34 +02001994fill_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 +02001995 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001996{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001997 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001999 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002000 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002001
Michal Vasko591e0b22015-08-13 13:53:43 +02002002 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002003 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002004 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002005 if (!aug->target_name) {
2006 goto error;
2007 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002009
Michal Vasko1d87a922015-08-21 12:57:16 +02002010 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002011 goto error;
2012 }
2013
2014 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002015 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2016 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002017 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002018 continue;
2019 }
2020
Radek Krejci3cf9e222015-06-18 11:37:50 +02002021 if (!strcmp(child->name, "if-feature")) {
2022 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002024 } else if (!strcmp(child->name, "when")) {
2025 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002026 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002027 goto error;
2028 }
2029
2030 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002031 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002032 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002033 goto error;
2034 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002035 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002036 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002037
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002038 /* check allowed data sub-statements */
2039 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002041 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002043 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002045 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002048 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002049 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002051 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002052 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002053 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002054 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002055 } else if (!strcmp(child->name, "action")) {
2056 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002057 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002058 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002059 goto error;
2060 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002061
Radek Krejci1d82ef62015-08-07 14:44:40 +02002062 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002063 goto error;
2064 }
2065
Radek Krejci1d82ef62015-08-07 14:44:40 +02002066 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002067 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002068 }
2069
2070 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002071 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2072 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002073 LOGMEM;
2074 goto error;
2075 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002076 }
2077
2078 LY_TREE_FOR_SAFE(yin->child, next, child) {
2079 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002080 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2081 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002082 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002083 goto error;
2084 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002085 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002086 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002087 }
2088
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002089 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002090 * connected to the tree and adjusted (if possible right now).
2091 * However, if this is augment in a uses, it gets resolved
2092 * when the uses does and cannot be resolved now for sure
2093 * (the grouping was not yet copied into uses).
2094 */
2095 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002096 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002097 goto error;
2098 }
Michal Vasko49291b32015-08-06 09:49:41 +02002099 }
Radek Krejci106efc02015-06-10 14:36:27 +02002100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002102
2103error:
2104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002106}
2107
Michal Vasko0d343d12015-08-24 14:57:36 +02002108/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109static int
Michal Vasko0d204592015-10-07 09:50:04 +02002110fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002111{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 struct lyxml_elem *sub, *next;
2113 const char *value;
2114 char *endptr;
2115 int f_mand = 0, f_min = 0, f_max = 0;
2116 int c_must = 0;
2117 int r;
2118 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002119
Radek Krejci76512572015-08-04 09:47:08 +02002120 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 goto error;
2122 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002123
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002124 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002125 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002126 if (!rfn->target_name) {
2127 goto error;
2128 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002131 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2132 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002133 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002134 continue;
2135 }
2136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 /* limited applicability */
2138 if (!strcmp(sub->name, "default")) {
2139 /* leaf or choice */
2140 if (rfn->mod.dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002141 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 goto error;
2143 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002145 /* check possibility of statements combination */
2146 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002147 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002149 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2150 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 goto error;
2152 }
2153 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002154 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002155 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002156
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 GETVAL(value, sub, "value");
2158 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2159 } else if (!strcmp(sub->name, "mandatory")) {
2160 /* leaf, choice or anyxml */
2161 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002162 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 goto error;
2164 }
2165 /* just checking the flags in leaf is not sufficient, we would allow
2166 * multiple mandatory statements with the "false" value
2167 */
2168 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 /* check possibility of statements combination */
2171 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002172 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002174 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2175 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 goto error;
2177 }
2178 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002179 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 GETVAL(value, sub, "value");
2183 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002184 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002186 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002188 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 goto error;
2190 }
2191 } else if (!strcmp(sub->name, "min-elements")) {
2192 /* list or leaf-list */
2193 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002194 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 goto error;
2196 }
2197 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 /* check possibility of statements combination */
2200 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002201 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002203 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2204 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 goto error;
2206 }
2207 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002208 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 GETVAL(value, sub, "value");
2212 while (isspace(value[0])) {
2213 value++;
2214 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 /* convert it to uint32_t */
2217 errno = 0;
2218 endptr = NULL;
2219 val = strtoul(value, &endptr, 10);
2220 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002221 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 goto error;
2223 }
2224 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002225 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 } else if (!strcmp(sub->name, "max-elements")) {
2227 /* list or leaf-list */
2228 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002229 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 goto error;
2231 }
2232 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 /* check possibility of statements combination */
2235 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002236 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002238 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2239 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 goto error;
2241 }
2242 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002243 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 GETVAL(value, sub, "value");
2247 while (isspace(value[0])) {
2248 value++;
2249 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002250
Radek Krejci0d7b2472016-02-12 11:11:03 +01002251 if (!strcmp(value, "unbounded")) {
2252 rfn->mod.list.max = 0;
2253 } else {
2254 /* convert it to uint32_t */
2255 errno = 0;
2256 endptr = NULL;
2257 val = strtoul(value, &endptr, 10);
2258 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002259 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002260 goto error;
2261 }
2262 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002264 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 } else if (!strcmp(sub->name, "presence")) {
2266 /* container */
2267 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002268 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 goto error;
2270 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 /* check possibility of statements combination */
2273 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002274 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002276 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2277 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 goto error;
2279 }
2280 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002281 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284 GETVAL(value, sub, "value");
2285 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2286 } else if (!strcmp(sub->name, "must")) {
2287 /* leaf-list, list, container or anyxml */
2288 /* check possibility of statements combination */
2289 if (rfn->target_type) {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002290 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002292 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2293 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002294 goto error;
2295 }
2296 } else {
Michal Vaskobc18a9d2016-05-23 15:13:35 +02002297 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002300 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002301 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002304 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 goto error;
2306 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002307
Michal Vasko345da0a2015-12-02 10:35:55 +01002308 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 /* process nodes with cardinality of 0..n */
2312 if (c_must) {
2313 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002314 if (!rfn->must) {
2315 LOGMEM;
2316 goto error;
2317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 }
Radek Krejci73adb602015-07-02 18:07:40 +02002319 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002320 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2321 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002322 if (r) {
2323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002328
2329error:
2330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002332}
2333
Michal Vasko0d343d12015-08-24 14:57:36 +02002334/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335static int
Radek Krejcib8048692015-08-05 13:36:34 +02002336fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002337{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 struct lyxml_elem *child;
2339 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002342 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2343 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002344 continue;
2345 }
2346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 if (!strcmp(child->name, "prefix")) {
2348 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002349 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 goto error;
2351 }
2352 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2353 } else if (!strcmp(child->name, "revision-date")) {
2354 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002355 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2356 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 }
2358 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002359 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 goto error;
2361 }
2362 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002363 } else if ((module->version == 2) && !strcmp(child->name, "description")) {
2364 if (imp->dsc) {
2365 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2366 goto error;
2367 }
2368 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2369 if (!imp->dsc) {
2370 goto error;
2371 }
2372 } else if ((module->version == 2) && !strcmp(child->name, "reference")) {
2373 if (imp->ref) {
2374 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2375 goto error;
2376 }
2377 imp->ref = read_yin_subnode(module->ctx, child, "text");
2378 if (!imp->ref) {
2379 goto error;
2380 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002382 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 goto error;
2384 }
2385 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 /* check mandatory information */
2388 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002389 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002390 goto error;
2391 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002394
Pavol Vicane994fda2016-03-22 10:47:58 +01002395 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002396
2397error:
2398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002400}
2401
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002402/* logs directly
2403 * returns:
2404 * 0 - inc successfully filled
2405 * -1 - error, inc is cleaned
2406 * 1 - duplication, ignore the inc structure, inc is cleaned
2407 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002409fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2410 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002411{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 struct lyxml_elem *child;
2413 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002415 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002416 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2417 /* garbage */
2418 continue;
2419 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 if (!strcmp(child->name, "revision-date")) {
2421 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002422 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002423 goto error;
2424 }
2425 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002426 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 goto error;
2428 }
2429 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Michal Vasko8bfe3812016-07-27 13:37:52 +02002430 } else if ((module->version == 2) && !strcmp(child->name, "description")) {
2431 if (inc->dsc) {
2432 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2433 goto error;
2434 }
2435 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2436 if (!inc->dsc) {
2437 goto error;
2438 }
2439 } else if ((module->version == 2) && !strcmp(child->name, "reference")) {
2440 if (inc->ref) {
2441 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2442 goto error;
2443 }
2444 inc->ref = read_yin_subnode(module->ctx, child, "text");
2445 if (!inc->ref) {
2446 goto error;
2447 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002449 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 goto error;
2451 }
2452 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002454 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002455
Pavol Vican0adf01d2016-03-22 12:29:33 +01002456 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002457
2458error:
2459
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002460 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002461}
2462
Michal Vasko0d343d12015-08-24 14:57:36 +02002463/* logs directly
2464 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002465 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002466 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002467 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002468 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469static int
Radek Krejcib8048692015-08-05 13:36:34 +02002470read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002472{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 const char *value;
2474 struct lyxml_elem *sub, *next;
2475 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002478 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002481 if (opt & OPT_IDENT) {
2482 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002483 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 goto error;
2485 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002488
Radek Krejci6764bb32015-07-03 15:16:04 +02002489 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002490 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002491 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002492 }
2493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 /* process local parameters */
2495 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002496 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002497 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002498 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002499 continue;
2500 }
2501 if (strcmp(sub->ns->value, LY_NSYIN)) {
2502 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002503 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002504 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002505 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002506 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002507 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002508 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002509 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002510 goto error;
2511 }
2512 }
2513
2514 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002515 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002516 continue;
2517 }
2518
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002520 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002521 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002522 goto error;
2523 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002524 node->dsc = read_yin_subnode(ctx, sub, "text");
2525 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002526 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 }
2528 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002529 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002530 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 goto error;
2532 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002533 node->ref = read_yin_subnode(ctx, sub, "text");
2534 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002535 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002536 }
2537 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002538 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002539 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 goto error;
2541 }
2542 GETVAL(value, sub, "value");
2543 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002544 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002546 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002547 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002548 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002550 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002551 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 }
2553 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002554 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002555 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 goto error;
2557 }
2558 GETVAL(value, sub, "value");
2559 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002560 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002561 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002562 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002563 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002564 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002565 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02002567 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002569 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002570 continue;
2571 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002572 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002574
Radek Krejci1d82ef62015-08-07 14:44:40 +02002575 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002576 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02002577 if (parent && (parent->flags & LYS_CONFIG_R)) {
2578 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002579 } else {
2580 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002581 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 }
2583 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002586
2587error:
2588
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002589 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002590}
2591
Michal Vasko0d343d12015-08-24 14:57:36 +02002592/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002593static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002594read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002595{
Radek Krejci76512572015-08-04 09:47:08 +02002596 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002597 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002598 const char *value;
2599
2600 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002601 if (!retval) {
2602 LOGMEM;
2603 return NULL;
2604 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002605
2606 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01002607 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02002608 if (!retval->cond) {
2609 goto error;
2610 }
Radek Krejci48464ed2016-03-17 15:44:09 +01002611 if (lyxp_syntax_check(retval->cond)) {
Michal Vasko77dc5652016-02-15 12:32:42 +01002612 goto error;
2613 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002614
Radek Krejci73adb602015-07-02 18:07:40 +02002615 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002616 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2617 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002618 continue;
2619 }
2620
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002621 if (!strcmp(child->name, "description")) {
2622 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002623 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002624 goto error;
2625 }
2626 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2627 if (!retval->dsc) {
2628 goto error;
2629 }
2630 } else if (!strcmp(child->name, "reference")) {
2631 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002632 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002633 goto error;
2634 }
2635 retval->ref = read_yin_subnode(module->ctx, child, "text");
2636 if (!retval->ref) {
2637 goto error;
2638 }
2639 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002640 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002641 goto error;
2642 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002643 }
2644
2645 return retval;
2646
2647error:
2648
Michal Vasko0308dd62015-10-07 09:14:40 +02002649 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002650 return NULL;
2651}
2652
Michal Vasko0d343d12015-08-24 14:57:36 +02002653/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002654static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002655read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2656 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002657{
Michal Vasko29fc0182015-08-24 15:02:39 +02002658 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002659 struct lys_node_case *cs;
2660 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002661 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002662
Radek Krejcie867c852015-08-27 09:52:34 +02002663 /* init */
2664 memset(&root, 0, sizeof root);
2665
Radek Krejci1d82ef62015-08-07 14:44:40 +02002666 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002667 if (!cs) {
2668 LOGMEM;
2669 return NULL;
2670 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002671 cs->nodetype = LYS_CASE;
2672 cs->prev = (struct lys_node *)cs;
2673 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002674
Radek Krejci6a113852015-07-03 16:04:20 +02002675 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002676 goto error;
2677 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002678
Radek Krejcia9544502015-08-14 08:24:29 +02002679 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2680
Michal Vasko3a0043f2015-08-12 12:11:30 +02002681 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002682 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002683 goto error;
2684 }
2685
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002686 /* process choice's specific children */
2687 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002688 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2689 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002690 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002691 continue;
2692 }
2693
Michal Vasko29fc0182015-08-24 15:02:39 +02002694 if (!strcmp(sub->name, "container") ||
2695 !strcmp(sub->name, "leaf-list") ||
2696 !strcmp(sub->name, "leaf") ||
2697 !strcmp(sub->name, "list") ||
2698 !strcmp(sub->name, "uses") ||
2699 !strcmp(sub->name, "choice") ||
2700 !strcmp(sub->name, "anyxml")) {
2701
Michal Vaskof3930de2015-10-22 12:03:59 +02002702 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002703 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002704 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002705 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002706 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002707 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002708 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002709 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002710 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002711 goto error;
2712 }
2713
Radek Krejci1d82ef62015-08-07 14:44:40 +02002714 cs->when = read_yin_when(module, sub);
2715 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002716 goto error;
2717 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002718
Michal Vasko345da0a2015-12-02 10:35:55 +01002719 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002725
Radek Krejci3cf9e222015-06-18 11:37:50 +02002726 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002727 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
2728 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002729 LOGMEM;
2730 goto error;
2731 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002732 }
Radek Krejci73adb602015-07-02 18:07:40 +02002733 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002734 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
2735 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002736 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002737 goto error;
2738 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 }
Radek Krejcib388c152015-06-04 17:03:03 +02002740
Michal Vasko29fc0182015-08-24 15:02:39 +02002741 /* last part - process data nodes */
2742 LY_TREE_FOR_SAFE(root.child, next, sub) {
2743 if (!strcmp(sub->name, "container")) {
2744 node = read_yin_container(module, retval, sub, resolve, unres);
2745 } else if (!strcmp(sub->name, "leaf-list")) {
2746 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2747 } else if (!strcmp(sub->name, "leaf")) {
2748 node = read_yin_leaf(module, retval, sub, resolve, unres);
2749 } else if (!strcmp(sub->name, "list")) {
2750 node = read_yin_list(module, retval, sub, resolve, unres);
2751 } else if (!strcmp(sub->name, "choice")) {
2752 node = read_yin_choice(module, retval, sub, resolve, unres);
2753 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002754 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02002755 } else if (!strcmp(sub->name, "anyxml")) {
2756 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2757 }
2758 if (!node) {
2759 goto error;
2760 }
2761
Michal Vasko345da0a2015-12-02 10:35:55 +01002762 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002763 }
2764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002766
2767error:
2768
Michal Vasko29fc0182015-08-24 15:02:39 +02002769 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002770 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002771 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002772 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002775}
2776
Michal Vasko0d343d12015-08-24 14:57:36 +02002777/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002778static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002779read_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 +02002780{
Radek Krejci629cdef2016-06-06 15:06:36 +02002781 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002783 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002784 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02002785 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02002786 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002788 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002789 if (!choice) {
2790 LOGMEM;
2791 return NULL;
2792 }
Radek Krejci76512572015-08-04 09:47:08 +02002793 choice->nodetype = LYS_CHOICE;
2794 choice->prev = (struct lys_node *)choice;
2795 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002796
Michal Vaskoe0c59842015-09-24 13:52:20 +02002797 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2798 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 goto error;
2800 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002801
Radek Krejcia9544502015-08-14 08:24:29 +02002802 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2803
Michal Vasko3a0043f2015-08-12 12:11:30 +02002804 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002805 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002806 goto error;
2807 }
2808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 /* process choice's specific children */
2810 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002811 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2812 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002813 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002814 continue;
2815 }
2816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002818 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 goto error;
2820 }
2821 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002822 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 goto error;
2824 }
2825 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002826 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 goto error;
2828 }
2829 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002830 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 goto error;
2832 }
2833 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002834 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835 goto error;
2836 }
2837 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002838 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 goto error;
2840 }
2841 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02002842 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002843 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 goto error;
2845 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002846 dflt = sub;
2847 lyxml_unlink_elem(ctx, dflt, 0);
2848
Radek Krejcif9a312c2016-06-06 15:14:30 +02002849 continue;
2850 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
2851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 } else if (!strcmp(sub->name, "mandatory")) {
2853 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002854 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 goto error;
2856 }
2857 /* just checking the flags in leaf is not sufficient, we would allow
2858 * multiple mandatory statements with the "false" value
2859 */
2860 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 GETVAL(value, sub, "value");
2863 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002864 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002865 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002866 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002867 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002868 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 goto error;
2870 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002871 } else if (!strcmp(sub->name, "when")) {
2872 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002873 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002874 goto error;
2875 }
2876
2877 choice->when = read_yin_when(module, sub);
2878 if (!choice->when) {
2879 goto error;
2880 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002881 } else if (!strcmp(sub->name, "if-feature")) {
2882 c_ftrs++;
2883
Michal Vasko345da0a2015-12-02 10:35:55 +01002884 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002885 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002887 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002889 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002890
Radek Krejci1d82ef62015-08-07 14:44:40 +02002891 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002892 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002894
Radek Krejci3cf9e222015-06-18 11:37:50 +02002895 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002896 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
2897 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002898 LOGMEM;
2899 goto error;
2900 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002901 }
2902
Radek Krejci73adb602015-07-02 18:07:40 +02002903 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002904 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
2905 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002906 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002907 goto error;
2908 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002909 }
2910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02002912 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002913 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
2914 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 goto error;
2916 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02002919 if (dflt) {
2920 GETVAL(value, dflt, "value");
2921 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002922 goto error;
2923 }
Radek Krejci629cdef2016-06-06 15:06:36 +02002924 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002926
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002927 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002928
2929error:
2930
Radek Krejci629cdef2016-06-06 15:06:36 +02002931 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01002932 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002935}
2936
Michal Vasko0d343d12015-08-24 14:57:36 +02002937/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002938static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002939read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002940 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002941{
Radek Krejci76512572015-08-04 09:47:08 +02002942 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002943 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002944 struct lyxml_elem *sub, *next;
2945 const char *value;
2946 int r;
2947 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002948 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002951 if (!anyxml) {
2952 LOGMEM;
2953 return NULL;
2954 }
Radek Krejci76512572015-08-04 09:47:08 +02002955 anyxml->nodetype = LYS_ANYXML;
2956 anyxml->prev = (struct lys_node *)anyxml;
2957 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002958
Michal Vaskoe0c59842015-09-24 13:52:20 +02002959 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2960 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 goto error;
2962 }
Radek Krejci863c2852015-06-03 15:47:11 +02002963
Radek Krejcia9544502015-08-14 08:24:29 +02002964 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002965
Radek Krejciadb30652016-07-11 15:27:07 +02002966 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02002967 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002968 goto error;
2969 }
2970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002972 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2973 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002974 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002975 continue;
2976 }
2977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 if (!strcmp(sub->name, "mandatory")) {
2979 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002980 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 goto error;
2982 }
2983 /* just checking the flags in leaf is not sufficient, we would allow
2984 * multiple mandatory statements with the "false" value
2985 */
2986 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002987
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 GETVAL(value, sub, "value");
2989 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002990 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002991 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002992 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002993 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002994 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002995 goto error;
2996 }
2997 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002998 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002999 } else if (!strcmp(sub->name, "when")) {
3000 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003001 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003002 goto error;
3003 }
3004
3005 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003006 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003007 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003008 goto error;
3009 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003010 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 } else if (!strcmp(sub->name, "must")) {
3012 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003013 } else if (!strcmp(sub->name, "if-feature")) {
3014 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003017 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 }
3020 }
Radek Krejci863c2852015-06-03 15:47:11 +02003021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 /* middle part - process nodes with cardinality of 0..n */
3023 if (c_must) {
3024 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003025 if (!anyxml->must) {
3026 LOGMEM;
3027 goto error;
3028 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003030 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003031 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3032 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003033 LOGMEM;
3034 goto error;
3035 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003036 }
Radek Krejci863c2852015-06-03 15:47:11 +02003037
Radek Krejci73adb602015-07-02 18:07:40 +02003038 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003040 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3041 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 if (r) {
3043 goto error;
3044 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003045 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003046 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3047 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003048 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003049 goto error;
3050 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 }
Radek Krejci863c2852015-06-03 15:47:11 +02003053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003054 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003055
3056error:
3057
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003058 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003061}
3062
Michal Vasko0d343d12015-08-24 14:57:36 +02003063/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003064static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003065read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003066 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003067{
Radek Krejci76512572015-08-04 09:47:08 +02003068 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003069 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 struct lyxml_elem *sub, *next;
3071 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003072 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003073 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003076 if (!leaf) {
3077 LOGMEM;
3078 return NULL;
3079 }
Radek Krejci76512572015-08-04 09:47:08 +02003080 leaf->nodetype = LYS_LEAF;
3081 leaf->prev = (struct lys_node *)leaf;
3082 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003083
Michal Vaskoe0c59842015-09-24 13:52:20 +02003084 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3085 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 goto error;
3087 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003088
Radek Krejcia9544502015-08-14 08:24:29 +02003089 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003090
Radek Krejciadb30652016-07-11 15:27:07 +02003091 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003092 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003093 goto error;
3094 }
3095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003097 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3098 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003099 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003100 continue;
3101 }
3102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003103 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003104 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003105 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 goto error;
3107 }
Michal Vasko88c29542015-11-27 14:57:53 +01003108 /* HACK for unres */
3109 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003110 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003111 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003112 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003113 goto error;
3114 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003115 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 } else if (!strcmp(sub->name, "default")) {
3117 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003118 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003119 goto error;
3120 }
3121 GETVAL(value, sub, "value");
3122 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3123 } else if (!strcmp(sub->name, "units")) {
3124 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003125 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003126 goto error;
3127 }
3128 GETVAL(value, sub, "name");
3129 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3130 } else if (!strcmp(sub->name, "mandatory")) {
3131 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003132 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 goto error;
3134 }
3135 /* just checking the flags in leaf is not sufficient, we would allow
3136 * multiple mandatory statements with the "false" value
3137 */
3138 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 GETVAL(value, sub, "value");
3141 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003142 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003143 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003144 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003145 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003146 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 goto error;
3148 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003149 } else if (!strcmp(sub->name, "when")) {
3150 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003151 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003152 goto error;
3153 }
3154
3155 leaf->when = read_yin_when(module, sub);
3156 if (!leaf->when) {
3157 goto error;
3158 }
3159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003161 c_must++;
3162 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003163 } else if (!strcmp(sub->name, "if-feature")) {
3164 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003168 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003171
Michal Vasko88c29542015-11-27 14:57:53 +01003172 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003176 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003177 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 goto error;
3179 }
Michal Vasko478c4652016-07-21 12:55:01 +02003180 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3181 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3182 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3183 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3184 goto error;
3185 }
3186
3187 /* check default value (if not defined, there still could be some restrictions
3188 * that need to be checked against a default value from a derived type) */
3189 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3190 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 /* middle part - process nodes with cardinality of 0..n */
3194 if (c_must) {
3195 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003196 if (!leaf->must) {
3197 LOGMEM;
3198 goto error;
3199 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003201 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003202 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3203 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003204 LOGMEM;
3205 goto error;
3206 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003207 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003208
Radek Krejci73adb602015-07-02 18:07:40 +02003209 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003211 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3212 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 if (r) {
3214 goto error;
3215 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003216 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003217 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3218 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003219 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003220 goto error;
3221 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003226
3227error:
3228
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003229 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003232}
3233
Michal Vasko0d343d12015-08-24 14:57:36 +02003234/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003235static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003236read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003237 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003238{
Radek Krejci76512572015-08-04 09:47:08 +02003239 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003240 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 struct lyxml_elem *sub, *next;
3242 const char *value;
3243 char *endptr;
3244 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003245 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003246 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003247 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003250 if (!llist) {
3251 LOGMEM;
3252 return NULL;
3253 }
Radek Krejci76512572015-08-04 09:47:08 +02003254 llist->nodetype = LYS_LEAFLIST;
3255 llist->prev = (struct lys_node *)llist;
3256 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003257
Michal Vaskoe0c59842015-09-24 13:52:20 +02003258 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3259 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 goto error;
3261 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003262
Radek Krejcia9544502015-08-14 08:24:29 +02003263 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003264
Radek Krejciadb30652016-07-11 15:27:07 +02003265 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003266 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003267 goto error;
3268 }
3269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003271 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3272 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003273 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003274 continue;
3275 }
3276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003278 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003279 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 goto error;
3281 }
Michal Vasko88c29542015-11-27 14:57:53 +01003282 /* HACK for unres */
3283 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003284 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003285 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003286 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287 goto error;
3288 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003289 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 } else if (!strcmp(sub->name, "units")) {
3291 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003292 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 goto error;
3294 }
3295 GETVAL(value, sub, "name");
3296 llist->units = lydict_insert(module->ctx, value, strlen(value));
3297 } else if (!strcmp(sub->name, "ordered-by")) {
3298 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003299 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 goto error;
3301 }
3302 /* just checking the flags in llist is not sufficient, we would
3303 * allow multiple ordered-by statements with the "system" value
3304 */
3305 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003306
Radek Krejci1574a8d2015-08-03 14:16:52 +02003307 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3309 * state data
3310 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003311 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 continue;
3313 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003314
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 GETVAL(value, sub, "value");
3316 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003317 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003319 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003321 } /* else system is the default value, so we can ignore it */
3322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 } else if (!strcmp(sub->name, "must")) {
3324 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003325 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003326 } else if (!strcmp(sub->name, "if-feature")) {
3327 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003330 } else if (!strcmp(sub->name, "min-elements")) {
3331 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003332 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003333 goto error;
3334 }
3335 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 GETVAL(value, sub, "value");
3338 while (isspace(value[0])) {
3339 value++;
3340 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 /* convert it to uint32_t */
3343 errno = 0;
3344 endptr = NULL;
3345 val = strtoul(value, &endptr, 10);
3346 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003347 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 goto error;
3349 }
3350 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003351 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003352 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3353 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003354 goto error;
3355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 } else if (!strcmp(sub->name, "max-elements")) {
3357 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003358 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 goto error;
3360 }
3361 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 GETVAL(value, sub, "value");
3364 while (isspace(value[0])) {
3365 value++;
3366 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003367
Radek Krejci0d7b2472016-02-12 11:11:03 +01003368 if (!strcmp(value, "unbounded")) {
3369 llist->max = 0;
3370 } else {
3371 /* convert it to uint32_t */
3372 errno = 0;
3373 endptr = NULL;
3374 val = strtoul(value, &endptr, 10);
3375 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003376 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003377 goto error;
3378 }
3379 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003380 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003381 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3382 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003383 goto error;
3384 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003386 } else if (!strcmp(sub->name, "when")) {
3387 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003388 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003389 goto error;
3390 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003391
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003392 llist->when = read_yin_when(module, sub);
3393 if (!llist->when) {
3394 goto error;
3395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003397 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003400
Michal Vasko88c29542015-11-27 14:57:53 +01003401 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003402 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003405 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003406 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 goto error;
3408 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 /* middle part - process nodes with cardinality of 0..n */
3411 if (c_must) {
3412 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003413 if (!llist->must) {
3414 LOGMEM;
3415 goto error;
3416 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003418 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003419 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3420 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003421 LOGMEM;
3422 goto error;
3423 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003424 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003425
Radek Krejci73adb602015-07-02 18:07:40 +02003426 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003428 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3429 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 if (r) {
3431 goto error;
3432 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003433 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003434 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3435 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003436 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003437 goto error;
3438 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003439 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003441
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443
3444error:
3445
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003446 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003449}
3450
Michal Vasko0d343d12015-08-24 14:57:36 +02003451/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003452static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003453read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3454 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003455{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003456 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003457 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01003459 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003460 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003462 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 char *auxs;
3464 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 /* init */
3467 memset(&root, 0, sizeof root);
3468 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003471 if (!list) {
3472 LOGMEM;
3473 return NULL;
3474 }
Radek Krejci76512572015-08-04 09:47:08 +02003475 list->nodetype = LYS_LIST;
3476 list->prev = (struct lys_node *)list;
3477 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003478
Michal Vaskoe0c59842015-09-24 13:52:20 +02003479 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3480 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 goto error;
3482 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003483
Radek Krejcia9544502015-08-14 08:24:29 +02003484 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3485
Radek Krejciadb30652016-07-11 15:27:07 +02003486 /* insert the node into the schema tree */
3487 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3488 goto error;
3489 }
3490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 /* process list's specific children */
3492 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003493 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3494 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003495 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003496 continue;
3497 }
3498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 /* data statements */
3500 if (!strcmp(sub->name, "container") ||
3501 !strcmp(sub->name, "leaf-list") ||
3502 !strcmp(sub->name, "leaf") ||
3503 !strcmp(sub->name, "list") ||
3504 !strcmp(sub->name, "choice") ||
3505 !strcmp(sub->name, "uses") ||
3506 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003507 !strcmp(sub->name, "anyxml") ||
3508 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003509 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003510 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 /* array counters */
3513 } else if (!strcmp(sub->name, "key")) {
3514 /* check cardinality 0..1 */
3515 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003516 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 goto error;
3518 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 /* count the number of keys */
3521 GETVAL(value, sub, "value");
3522 key_str = value;
3523 while ((value = strpbrk(value, " \t\n"))) {
3524 list->keys_size++;
3525 while (isspace(*value)) {
3526 value++;
3527 }
3528 }
3529 list->keys_size++;
3530 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003531 if (!list->keys) {
3532 LOGMEM;
3533 goto error;
3534 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 } else if (!strcmp(sub->name, "unique")) {
3536 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003537 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003538 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 } else if (!strcmp(sub->name, "typedef")) {
3540 c_tpdf++;
3541 } else if (!strcmp(sub->name, "must")) {
3542 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003543 } else if (!strcmp(sub->name, "if-feature")) {
3544 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 /* optional stetments */
3547 } else if (!strcmp(sub->name, "ordered-by")) {
3548 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003549 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 goto error;
3551 }
3552 /* just checking the flags in llist is not sufficient, we would
3553 * allow multiple ordered-by statements with the "system" value
3554 */
3555 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003556
Radek Krejci1574a8d2015-08-03 14:16:52 +02003557 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3559 * state data
3560 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003561 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 continue;
3563 }
Radek Krejci345ad742015-06-03 11:04:18 +02003564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 GETVAL(value, sub, "value");
3566 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003567 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003569 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 goto error;
3571 }
3572 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003573 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 } else if (!strcmp(sub->name, "min-elements")) {
3575 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003576 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 goto error;
3578 }
3579 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 GETVAL(value, sub, "value");
3582 while (isspace(value[0])) {
3583 value++;
3584 }
Radek Krejci345ad742015-06-03 11:04:18 +02003585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 /* convert it to uint32_t */
3587 errno = 0;
3588 auxs = NULL;
3589 val = strtoul(value, &auxs, 10);
3590 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003591 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 goto error;
3593 }
3594 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003595 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003596 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3597 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003598 lyxml_free(module->ctx, sub);
3599 goto error;
3600 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003601 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003602 } else if (!strcmp(sub->name, "max-elements")) {
3603 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003604 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 goto error;
3606 }
3607 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 GETVAL(value, sub, "value");
3610 while (isspace(value[0])) {
3611 value++;
3612 }
Radek Krejci345ad742015-06-03 11:04:18 +02003613
Radek Krejci0d7b2472016-02-12 11:11:03 +01003614 if (!strcmp(value, "unbounded")) {
3615 list->max = 0;;
3616 } else {
3617 /* convert it to uint32_t */
3618 errno = 0;
3619 auxs = NULL;
3620 val = strtoul(value, &auxs, 10);
3621 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003622 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003623 goto error;
3624 }
3625 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003626 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003627 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3628 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003629 goto error;
3630 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003632 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003633 } else if (!strcmp(sub->name, "when")) {
3634 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003635 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003636 goto error;
3637 }
3638
3639 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003640 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003641 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003642 goto error;
3643 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003644 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003645 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003646 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003647 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003648 }
3649 }
Radek Krejci345ad742015-06-03 11:04:18 +02003650
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003652 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003653 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 goto error;
3655 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3658 if (c_tpdf) {
3659 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003660 if (!list->tpdf) {
3661 LOGMEM;
3662 goto error;
3663 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003665 if (c_must) {
3666 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003667 if (!list->must) {
3668 LOGMEM;
3669 goto error;
3670 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003671 }
3672 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003673 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
3674 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003675 LOGMEM;
3676 goto error;
3677 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003678 }
Radek Krejci73adb602015-07-02 18:07:40 +02003679 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003681 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3682 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 if (r) {
3684 goto error;
3685 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003686 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003687 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
3688 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003689 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003690 goto error;
3691 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003692 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003693 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3694 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003695 if (r) {
3696 goto error;
3697 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 }
3699 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 /* last part - process data nodes */
3702 LY_TREE_FOR_SAFE(root.child, next, sub) {
3703 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003704 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003706 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003708 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003710 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003712 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003714 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003716 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003718 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003719 } else if (!strcmp(sub->name, "action")) {
3720 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003721 } else {
3722 LOGINT;
3723 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003725 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 goto error;
3727 }
Radek Krejci73adb602015-07-02 18:07:40 +02003728
Michal Vasko345da0a2015-12-02 10:35:55 +01003729 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003731
Radek Krejci461efb92016-02-12 15:52:18 +01003732 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003733 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01003734 goto error;
3735 }
3736 } /* 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 +02003737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 /* process unique statements */
3739 if (c_uniq) {
3740 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003741 if (!list->unique) {
3742 LOGMEM;
3743 goto error;
3744 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003745
Radek Krejci461efb92016-02-12 15:52:18 +01003746 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
3747 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3748 list->unique_size++;
3749 if (r) {
3750 goto error;
3751 }
3752
3753 lyxml_free(module->ctx, sub);
3754 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003758
3759error:
3760
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003761 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003763 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 }
3765 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003766 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003768
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003769 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003770}
3771
Michal Vasko0d343d12015-08-24 14:57:36 +02003772/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003773static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003774read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3775 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003778 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003779 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003780 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003781 const char *value;
3782 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003783 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 /* init */
3786 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003789 if (!cont) {
3790 LOGMEM;
3791 return NULL;
3792 }
Radek Krejci76512572015-08-04 09:47:08 +02003793 cont->nodetype = LYS_CONTAINER;
3794 cont->prev = (struct lys_node *)cont;
3795 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003796
Michal Vaskoe0c59842015-09-24 13:52:20 +02003797 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3798 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 goto error;
3800 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801
Radek Krejcia9544502015-08-14 08:24:29 +02003802 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3803
Radek Krejciadb30652016-07-11 15:27:07 +02003804 /* insert the node into the schema tree */
3805 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3806 goto error;
3807 }
3808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 /* process container's specific children */
3810 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003811 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003812 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003813 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003814 continue;
3815 }
3816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003817 if (!strcmp(sub->name, "presence")) {
3818 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003819 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 goto error;
3821 }
3822 GETVAL(value, sub, "value");
3823 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003824
Michal Vasko345da0a2015-12-02 10:35:55 +01003825 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003826 } else if (!strcmp(sub->name, "when")) {
3827 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003828 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003829 goto error;
3830 }
3831
3832 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003833 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003834 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003835 goto error;
3836 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003837 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 /* data statements */
3840 } else if (!strcmp(sub->name, "container") ||
3841 !strcmp(sub->name, "leaf-list") ||
3842 !strcmp(sub->name, "leaf") ||
3843 !strcmp(sub->name, "list") ||
3844 !strcmp(sub->name, "choice") ||
3845 !strcmp(sub->name, "uses") ||
3846 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003847 !strcmp(sub->name, "anyxml") ||
3848 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003849 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003850 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 /* array counters */
3853 } else if (!strcmp(sub->name, "typedef")) {
3854 c_tpdf++;
3855 } else if (!strcmp(sub->name, "must")) {
3856 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003857 } else if (!strcmp(sub->name, "if-feature")) {
3858 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003860 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 }
3863 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3866 if (c_tpdf) {
3867 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003868 if (!cont->tpdf) {
3869 LOGMEM;
3870 goto error;
3871 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
3873 if (c_must) {
3874 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003875 if (!cont->must) {
3876 LOGMEM;
3877 goto error;
3878 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003880 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003881 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
3882 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003883 LOGMEM;
3884 goto error;
3885 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003886 }
Radek Krejci800af702015-06-02 13:46:01 +02003887
Radek Krejci73adb602015-07-02 18:07:40 +02003888 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003890 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3891 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 if (r) {
3893 goto error;
3894 }
3895 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003896 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3897 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 if (r) {
3899 goto error;
3900 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003901 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003902 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
3903 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003904 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003905 goto error;
3906 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003908 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910 /* last part - process data nodes */
3911 LY_TREE_FOR_SAFE(root.child, next, sub) {
3912 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003913 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003915 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003916 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003917 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003919 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003920 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003921 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003923 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003924 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003925 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003926 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003927 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02003928 } else if (!strcmp(sub->name, "action")) {
3929 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003931 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 goto error;
3933 }
Radek Krejci73adb602015-07-02 18:07:40 +02003934
Michal Vasko345da0a2015-12-02 10:35:55 +01003935 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003938 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003939
3940error:
3941
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003942 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003944 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003947 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003948}
3949
Michal Vasko0d343d12015-08-24 14:57:36 +02003950/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003951static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003953 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003954{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003955 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003957 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003958 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003959 int r;
3960 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 /* init */
3963 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003964
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003965 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003966 if (!grp) {
3967 LOGMEM;
3968 return NULL;
3969 }
Radek Krejci76512572015-08-04 09:47:08 +02003970 grp->nodetype = LYS_GROUPING;
3971 grp->prev = (struct lys_node *)grp;
3972 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003973
Michal Vasko71e1aa82015-08-12 12:17:51 +02003974 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 goto error;
3976 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003977
Radek Krejcia9544502015-08-14 08:24:29 +02003978 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3979
Radek Krejciadb30652016-07-11 15:27:07 +02003980 /* insert the node into the schema tree */
3981 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
3982 goto error;
3983 }
3984
Radek Krejci1d82ef62015-08-07 14:44:40 +02003985 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003986 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3987 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003988 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003989 continue;
3990 }
3991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003992 /* data statements */
3993 if (!strcmp(sub->name, "container") ||
3994 !strcmp(sub->name, "leaf-list") ||
3995 !strcmp(sub->name, "leaf") ||
3996 !strcmp(sub->name, "list") ||
3997 !strcmp(sub->name, "choice") ||
3998 !strcmp(sub->name, "uses") ||
3999 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004000 !strcmp(sub->name, "anyxml") ||
4001 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004002 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004003 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004005 /* array counters */
4006 } else if (!strcmp(sub->name, "typedef")) {
4007 c_tpdf++;
4008 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004009 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004010 goto error;
4011 }
4012 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004014 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4015 if (c_tpdf) {
4016 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004017 if (!grp->tpdf) {
4018 LOGMEM;
4019 goto error;
4020 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004022 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004023 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4024 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004025 if (r) {
4026 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004027 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004030 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004031 if (!root.child) {
4032 LOGWRN("Grouping \"%s\" without children.", retval->name);
4033 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004034 LY_TREE_FOR_SAFE(root.child, next, sub) {
4035 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004036 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004037 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004038 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004040 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004042 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004044 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004046 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004048 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004049 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004050 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004051 } else if (!strcmp(sub->name, "action")) {
4052 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004053 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004054 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 goto error;
4056 }
Radek Krejci73adb602015-07-02 18:07:40 +02004057
Michal Vasko345da0a2015-12-02 10:35:55 +01004058 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004059 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004062
4063error:
4064
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004065 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004066 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004067 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004071}
4072
Michal Vasko0d343d12015-08-24 14:57:36 +02004073/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004074static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004075read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4076 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004077{
Radek Krejcie0674f82015-06-15 13:58:51 +02004078 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004079 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004080 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004081 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004082 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004083 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004084
Radek Krejcie0674f82015-06-15 13:58:51 +02004085 /* init */
4086 memset(&root, 0, sizeof root);
4087
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004089 if (!inout) {
4090 LOGMEM;
4091 return NULL;
4092 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004093 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004094
4095 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004096 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004097 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004099 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004100 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004102 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004103 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004104 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004105 }
4106
Radek Krejci76512572015-08-04 09:47:08 +02004107 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004108
Radek Krejci6a113852015-07-03 16:04:20 +02004109 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004110 goto error;
4111 }
4112
Radek Krejcia9544502015-08-14 08:24:29 +02004113 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4114
Radek Krejciadb30652016-07-11 15:27:07 +02004115 /* insert the node into the schema tree */
4116 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4117 goto error;
4118 }
4119
Michal Vasko38d01f72015-06-15 09:41:06 +02004120 /* data statements */
4121 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004122 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4123 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004124 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004125 continue;
4126 }
4127
Michal Vasko38d01f72015-06-15 09:41:06 +02004128 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004129 !strcmp(sub->name, "leaf-list") ||
4130 !strcmp(sub->name, "leaf") ||
4131 !strcmp(sub->name, "list") ||
4132 !strcmp(sub->name, "choice") ||
4133 !strcmp(sub->name, "uses") ||
4134 !strcmp(sub->name, "grouping") ||
4135 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004136 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004137 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004139 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004140 } else if (!strcmp(sub->name, "typedef")) {
4141 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004142
Radek Krejci19332802016-07-29 10:39:46 +02004143 } else if (!strcmp(sub->name, "must")) {
4144 if (module->version < 2) {
4145 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
4146 goto error;
4147 }
4148 c_must++;
4149
Michal Vasko38d01f72015-06-15 09:41:06 +02004150 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004151 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004152 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 }
4154 }
4155
4156 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4157 if (c_tpdf) {
4158 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004159 if (!inout->tpdf) {
4160 LOGMEM;
4161 goto error;
4162 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 }
Radek Krejci19332802016-07-29 10:39:46 +02004164 if (c_must) {
4165 inout->must = calloc(c_must, sizeof *inout->must);
4166 if (!inout->must) {
4167 LOGMEM;
4168 goto error;
4169 }
4170 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004171
Radek Krejci73adb602015-07-02 18:07:40 +02004172 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004173 if (!strcmp(sub->name, "must")) {
4174 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4175 inout->must_size++;
4176 if (r) {
4177 goto error;
4178 }
4179 } else { /* typedef */
4180 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4181 inout->tpdf_size++;
4182 if (r) {
4183 goto error;
4184 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004185 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004186 }
4187
4188 /* last part - process data nodes */
4189 LY_TREE_FOR_SAFE(root.child, next, sub) {
4190 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004191 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004192 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004193 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004194 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004195 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004196 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004197 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004198 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004199 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004200 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004201 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004202 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004203 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004204 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004205 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004206 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004207 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004208 goto error;
4209 }
Radek Krejci73adb602015-07-02 18:07:40 +02004210
Michal Vasko345da0a2015-12-02 10:35:55 +01004211 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004212 }
4213
Michal Vasko38d01f72015-06-15 09:41:06 +02004214 return retval;
4215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004216error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004217
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004218 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004219 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004220 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 }
4222
4223 return NULL;
4224}
4225
Michal Vasko0d343d12015-08-24 14:57:36 +02004226/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004227static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004228read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4229 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004230{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004231 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004232 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004233 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004234 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004235 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004236 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004237
Michal Vaskoc6551b32015-06-16 10:51:43 +02004238 memset(&root, 0, sizeof root);
4239
Michal Vasko0ea41032015-06-16 08:53:55 +02004240 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004241 if (!notif) {
4242 LOGMEM;
4243 return NULL;
4244 }
Radek Krejci76512572015-08-04 09:47:08 +02004245 notif->nodetype = LYS_NOTIF;
4246 notif->prev = (struct lys_node *)notif;
4247 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004248
Radek Krejci6a113852015-07-03 16:04:20 +02004249 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 goto error;
4251 }
4252
Radek Krejcia9544502015-08-14 08:24:29 +02004253 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4254
Radek Krejciadb30652016-07-11 15:27:07 +02004255 /* insert the node into the schema tree */
4256 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4257 goto error;
4258 }
4259
Michal Vasko0ea41032015-06-16 08:53:55 +02004260 /* process rpc's specific children */
4261 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004262 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4263 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004264 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004265 continue;
4266 }
4267
Michal Vasko0ea41032015-06-16 08:53:55 +02004268 /* data statements */
4269 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004270 !strcmp(sub->name, "leaf-list") ||
4271 !strcmp(sub->name, "leaf") ||
4272 !strcmp(sub->name, "list") ||
4273 !strcmp(sub->name, "choice") ||
4274 !strcmp(sub->name, "uses") ||
4275 !strcmp(sub->name, "grouping") ||
4276 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004277 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004278 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004281 } else if (!strcmp(sub->name, "typedef")) {
4282 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004283 } else if (!strcmp(sub->name, "if-feature")) {
4284 c_ftrs++;
Radek Krejci19332802016-07-29 10:39:46 +02004285 } else if (!strcmp(sub->name, "must")) {
4286 if (module->version < 2) {
4287 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
4288 goto error;
4289 }
4290 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004291 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004292 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004293 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004294 }
4295 }
4296
4297 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4298 if (c_tpdf) {
4299 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004300 if (!notif->tpdf) {
4301 LOGMEM;
4302 goto error;
4303 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004304 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004305 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004306 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4307 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004308 LOGMEM;
4309 goto error;
4310 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004311 }
Radek Krejci19332802016-07-29 10:39:46 +02004312 if (c_must) {
4313 notif->must = calloc(c_must, sizeof *notif->must);
4314 if (!notif->must) {
4315 LOGMEM;
4316 goto error;
4317 }
4318 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004319
Radek Krejci73adb602015-07-02 18:07:40 +02004320 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004321 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004322 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4323 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004324 if (r) {
4325 goto error;
4326 }
Radek Krejci96299152016-06-22 10:17:50 +02004327 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004328 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4329 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004330 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004331 goto error;
4332 }
Radek Krejci19332802016-07-29 10:39:46 +02004333 } else if (!strcmp(sub->name, "must")) {
4334 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4335 notif->must_size++;
4336 if (r) {
4337 goto error;
4338 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004339 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004340 }
4341
4342 /* last part - process data nodes */
4343 LY_TREE_FOR_SAFE(root.child, next, sub) {
4344 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004346 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004348 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004349 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004350 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004351 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004352 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004353 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004354 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004355 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004356 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004357 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004358 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004359 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004360 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004361 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004362 goto error;
4363 }
Radek Krejci73adb602015-07-02 18:07:40 +02004364
Michal Vasko345da0a2015-12-02 10:35:55 +01004365 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004366 }
4367
Michal Vasko0ea41032015-06-16 08:53:55 +02004368 return retval;
4369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004371
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004372 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004373 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004374 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004375 }
4376
4377 return NULL;
4378}
4379
Michal Vasko0d343d12015-08-24 14:57:36 +02004380/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004381static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004382read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4383 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004384{
Radek Krejcie0674f82015-06-15 13:58:51 +02004385 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004386 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004387 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004388 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004389 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004390 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004391
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004392 if (!strcmp(yin->name, "action")) {
Michal Vaskobb174852016-07-25 11:00:21 +02004393 if (module->version != 2) {
4394 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
4395 return NULL;
4396 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004397 for (node = parent; node; node = lys_parent(node)) {
4398 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
4399 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
4400 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
4401 return NULL;
4402 }
4403 }
4404 }
4405
Radek Krejcie0674f82015-06-15 13:58:51 +02004406 /* init */
4407 memset(&root, 0, sizeof root);
4408
Michal Vasko38d01f72015-06-15 09:41:06 +02004409 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004410 if (!rpc) {
4411 LOGMEM;
4412 return NULL;
4413 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004414 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02004415 rpc->prev = (struct lys_node *)rpc;
4416 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004417
Radek Krejci6a113852015-07-03 16:04:20 +02004418 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004419 goto error;
4420 }
4421
Radek Krejcia9544502015-08-14 08:24:29 +02004422 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4423
Radek Krejciadb30652016-07-11 15:27:07 +02004424 /* insert the node into the schema tree */
4425 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4426 goto error;
4427 }
4428
Michal Vasko38d01f72015-06-15 09:41:06 +02004429 /* process rpc's specific children */
4430 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004431 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4432 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004433 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004434 continue;
4435 }
4436
Michal Vasko38d01f72015-06-15 09:41:06 +02004437 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004439 && (rpc->child->nodetype == LYS_INPUT
4440 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004441 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004442 goto error;
4443 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004444 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004445 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004446 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 if (rpc->child
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004448 && (rpc->child->nodetype == LYS_OUTPUT
4449 || (rpc->child->next && rpc->child->next->nodetype == LYS_OUTPUT))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004450 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004451 goto error;
4452 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004453 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004454 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004457 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004458 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004459 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004462 } else if (!strcmp(sub->name, "typedef")) {
4463 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004464 } else if (!strcmp(sub->name, "if-feature")) {
4465 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004466 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004467 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004468 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004469 }
4470 }
4471
4472 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4473 if (c_tpdf) {
4474 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004475 if (!rpc->tpdf) {
4476 LOGMEM;
4477 goto error;
4478 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004479 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004480 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004481 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
4482 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004483 LOGMEM;
4484 goto error;
4485 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004486 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004487
Radek Krejci73adb602015-07-02 18:07:40 +02004488 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004489 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004490 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4491 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004492 if (r) {
4493 goto error;
4494 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004495 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004496 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
4497 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004498 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004499 goto error;
4500 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004501 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004502 }
4503
4504 /* last part - process data nodes */
4505 LY_TREE_FOR_SAFE(root.child, next, sub) {
4506 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004507 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004508 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004509 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004510 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004512 goto error;
4513 }
Radek Krejci73adb602015-07-02 18:07:40 +02004514
Michal Vasko345da0a2015-12-02 10:35:55 +01004515 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004516 }
4517
Michal Vasko38d01f72015-06-15 09:41:06 +02004518 return retval;
4519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004521
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004522 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004523 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004524 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004525 }
4526
4527 return NULL;
4528}
4529
Michal Vasko0d343d12015-08-24 14:57:36 +02004530/* logs directly
4531 *
Radek Krejci74705112015-06-05 10:25:44 +02004532 * resolve - referenced grouping should be bounded to the namespace (resolved)
4533 * only when uses does not appear in grouping. In a case of grouping's uses,
4534 * we just get information but we do not apply augment or refine to it.
4535 */
Radek Krejci76512572015-08-04 09:47:08 +02004536static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02004537read_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 +02004538{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004540 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004541 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004543 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004547 if (!uses) {
4548 LOGMEM;
4549 return NULL;
4550 }
Radek Krejci76512572015-08-04 09:47:08 +02004551 uses->nodetype = LYS_USES;
4552 uses->prev = (struct lys_node *)uses;
4553 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004554
Radek Krejcia9544502015-08-14 08:24:29 +02004555 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004556 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004557
Michal Vaskoe0c59842015-09-24 13:52:20 +02004558 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02004559 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 goto error;
4561 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004562
Radek Krejcia9544502015-08-14 08:24:29 +02004563 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4564
Radek Krejciadb30652016-07-11 15:27:07 +02004565 /* insert the node into the schema tree */
4566 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4567 goto error;
4568 }
4569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004570 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004571 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004572 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4573 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004574 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004575 continue;
4576 }
4577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 if (!strcmp(sub->name, "refine")) {
4579 c_ref++;
4580 } else if (!strcmp(sub->name, "augment")) {
4581 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004582 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004583 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004584 } else if (!strcmp(sub->name, "when")) {
4585 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004586 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004587 goto error;
4588 }
4589
4590 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004591 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004592 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004593 goto error;
4594 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004595 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004597 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004599 }
4600 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004601
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 /* process properties with cardinality 0..n */
4603 if (c_ref) {
4604 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004605 if (!uses->refine) {
4606 LOGMEM;
4607 goto error;
4608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 }
4610 if (c_aug) {
4611 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004612 if (!uses->augment) {
4613 LOGMEM;
4614 goto error;
4615 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004616 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004617 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004618 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
4619 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004620 LOGMEM;
4621 goto error;
4622 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004623 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004624
Radek Krejcia9544502015-08-14 08:24:29 +02004625 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004627 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4628 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004629 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004630 goto error;
4631 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004632 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004633 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4634 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004635 if (r) {
4636 goto error;
4637 }
4638 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004639 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
4640 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004641 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004642 goto error;
4643 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 }
4645 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004646
Radek Krejci48464ed2016-03-17 15:44:09 +01004647 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004648 goto error;
4649 }
Radek Krejci74705112015-06-05 10:25:44 +02004650
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004652
4653error:
4654
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004655 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004658}
4659
Michal Vasko0d343d12015-08-24 14:57:36 +02004660/* logs directly
4661 *
4662 * common code for yin_read_module() and yin_read_submodule()
4663 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664static int
Radek Krejcic071c542016-01-27 14:57:51 +01004665read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4666 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004667{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004669 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004671 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01004672 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01004674 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02004675 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01004676 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004677 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004678 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 +02004679
Radek Krejcic071c542016-01-27 14:57:51 +01004680 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02004681 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01004682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 /* init */
4684 memset(&root, 0, sizeof root);
4685 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004686 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 /*
4689 * in the first run, we process elements with cardinality of 1 or 0..1 and
4690 * count elements with cardinality 0..n. Data elements (choices, containers,
4691 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4692 * need have all top-level and groupings already prepared at that time. In
4693 * the middle loop, we process other elements with carinality of 0..n since
4694 * we need to allocate arrays to store them.
4695 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 LY_TREE_FOR_SAFE(yin->child, next, child) {
4697 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004698 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004699 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 continue;
4701 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004702
Radek Krejcic071c542016-01-27 14:57:51 +01004703 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004705 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 goto error;
4707 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004708 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004710 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004711 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004712 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004713 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 goto error;
4715 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004716 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01004717 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
4719 }
4720 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004721 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004722 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4723 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004724 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004725 goto error;
4726 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004727 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01004728 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004729 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 goto error;
4731 }
Radek Krejcif3886932015-06-04 17:36:06 +02004732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004733 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004734 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004735 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004737 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004738 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004740 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004741 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
4743 }
4744 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004745 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 /* check here differs from a generic prefix check, since this prefix
4747 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004748 */
Radek Krejci48464ed2016-03-17 15:44:09 +01004749 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 goto error;
4751 }
Radek Krejcic071c542016-01-27 14:57:51 +01004752 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004753
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004755 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004756
4757 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004758 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004760 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004763 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004764 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004765 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004766 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004768 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004769 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004770 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004771 lyxml_unlink_elem(ctx, child, 2);
4772 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004773
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004775 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004776 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004777 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004780 } else if (!strcmp(child->name, "container") ||
4781 !strcmp(child->name, "leaf-list") ||
4782 !strcmp(child->name, "leaf") ||
4783 !strcmp(child->name, "list") ||
4784 !strcmp(child->name, "choice") ||
4785 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004786 !strcmp(child->name, "anyxml") ||
4787 !strcmp(child->name, "rpc") ||
4788 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004789 lyxml_unlink_elem(ctx, child, 2);
4790 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004791
Radek Krejci1d82ef62015-08-07 14:44:40 +02004792 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004793 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004794 lyxml_unlink_elem(ctx, child, 2);
4795 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004798 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004799 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004800 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004801 goto error;
4802 }
Radek Krejcic071c542016-01-27 14:57:51 +01004803 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004804 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004805 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 goto error;
4807 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004808 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004809 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004810 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 goto error;
4812 }
Radek Krejcic071c542016-01-27 14:57:51 +01004813 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004814 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004815 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004816 goto error;
4817 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004818 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004819 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004820 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004821 goto error;
4822 }
Radek Krejcic071c542016-01-27 14:57:51 +01004823 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004824 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004825 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004826 goto error;
4827 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004828 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004829 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004830 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 goto error;
4832 }
Radek Krejcic071c542016-01-27 14:57:51 +01004833 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004834 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004835 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 goto error;
4837 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004838 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004839 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004840 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004841 goto error;
4842 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004843 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02004844 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004845 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 goto error;
4847 }
Radek Krejcic071c542016-01-27 14:57:51 +01004848 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02004849 if (!strcmp(value, "1")) {
4850 if (submodule) {
4851 if (module->version > 1) {
4852 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4853 goto error;
4854 }
4855 } else {
4856 module->version = 1;
4857 }
4858 } else {
4859 if (submodule) {
4860 if (module->version != 2) {
4861 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
4862 goto error;
4863 }
4864 } else {
4865 module->version = 2;
4866 }
4867 }
4868
Michal Vasko345da0a2015-12-02 10:35:55 +01004869 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004870
Radek Krejci1d82ef62015-08-07 14:44:40 +02004871 } else if (!strcmp(child->name, "extension")) {
4872 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004873
Radek Krejci3d468122015-10-02 13:36:12 +02004874 /* we have the following supported (hardcoded) extensions: */
4875 /* ietf-netconf's get-filter-element-attributes */
4876 if (!strcmp(module->ns, LY_NSNC) &&
4877 !strcmp(value, "get-filter-element-attributes")) {
4878 LOGDBG("NETCONF filter extension found");
4879 /* NACM's default-deny-write and default-deny-all */
4880 } else if (!strcmp(module->ns, LY_NSNACM) &&
4881 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4882 LOGDBG("NACM extension found");
4883 /* other extensions are not supported, so inform about such an extension */
4884 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004885 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004886 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004887 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004889 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 }
4892 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004893
Radek Krejcic071c542016-01-27 14:57:51 +01004894 /* check for mandatory statements */
4895 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004896 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004897 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004898 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004900 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 goto error;
4902 }
4903 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004904 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 goto error;
4906 }
4907 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 /* allocate arrays for elements with cardinality of 0..n */
4910 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004911 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
4912 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004913 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004914 LOGMEM;
4915 goto error;
4916 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004917 /* set stop block for possible realloc */
4918 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 }
4920 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004921 trg->rev = calloc(c_rev, sizeof *trg->rev);
4922 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004923 LOGMEM;
4924 goto error;
4925 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004926 }
4927 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004928 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4929 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004930 LOGMEM;
4931 goto error;
4932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 }
4934 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004935 trg->ident = calloc(c_ident, sizeof *trg->ident);
4936 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004937 LOGMEM;
4938 goto error;
4939 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004940 }
4941 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02004942 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
4943 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01004944 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004945 LOGMEM;
4946 goto error;
4947 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02004948 /* set stop block for possible realloc */
4949 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004950 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004951 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004952 trg->augment = calloc(c_aug, sizeof *trg->augment);
4953 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004954 LOGMEM;
4955 goto error;
4956 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004957 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004958 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004959 trg->features = calloc(c_ftrs, sizeof *trg->features);
4960 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004961 LOGMEM;
4962 goto error;
4963 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004964 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004965 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004966 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4967 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004968 LOGMEM;
4969 goto error;
4970 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004971 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004972
Michal Vasko2f7925f2015-10-21 15:06:56 +02004973 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4974 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004975 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004976 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4977 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004978 if (r) {
4979 goto error;
4980 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004981
Radek Krejci1d82ef62015-08-07 14:44:40 +02004982 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004983 memset(&inc, 0, sizeof inc);
4984 /* 1) pass module, not trg, since we want to pass the main module
4985 * 2) we cannot pass directly the structure in the array since
4986 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01004987 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004988 if (!r) {
4989 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02004990 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
4991 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02004992 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 goto error;
4994 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004995
Radek Krejci1d82ef62015-08-07 14:44:40 +02004996 } else if (!strcmp(child->name, "revision")) {
4997 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01004998 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 goto error;
5000 }
Radek Krejcic071c542016-01-27 14:57:51 +01005001 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005002 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005003 for (i = 0; i < trg->rev_size; i++) {
5004 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005005 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5006 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005007 }
5008 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005009
Radek Krejci1d82ef62015-08-07 14:44:40 +02005010 LY_TREE_FOR(child->child, child2) {
5011 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005012 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005013 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005014 goto error;
5015 }
Radek Krejcic071c542016-01-27 14:57:51 +01005016 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5017 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005018 goto error;
5019 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005020 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005021 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005022 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 goto error;
5024 }
Radek Krejcic071c542016-01-27 14:57:51 +01005025 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5026 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 goto error;
5028 }
5029 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005030 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005031 goto error;
5032 }
5033 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005036 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005038 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005039 if (!value) {
5040 LOGMEM;
5041 goto error;
5042 }
Radek Krejcic071c542016-01-27 14:57:51 +01005043 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5044 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005045 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005046
Radek Krejci749190d2016-02-18 16:26:25 +01005047 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005048 value = trg->rev[0].dsc;
5049 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5050 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005051 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005052
Radek Krejci749190d2016-02-18 16:26:25 +01005053 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005054 value = trg->rev[0].ref;
5055 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5056 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005057 }
5058 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005059
Radek Krejcic071c542016-01-27 14:57:51 +01005060 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005061
Radek Krejci1d82ef62015-08-07 14:44:40 +02005062 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005063 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5064 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 if (r) {
5066 goto error;
5067 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005068
Radek Krejci1d82ef62015-08-07 14:44:40 +02005069 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005070 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5071 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005072 if (r) {
5073 goto error;
5074 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005075
Radek Krejci1d82ef62015-08-07 14:44:40 +02005076 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005077 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5078 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005079 if (r) {
5080 goto error;
5081 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005082
Radek Krejci1d82ef62015-08-07 14:44:40 +02005083 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005084 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5085 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005086 if (r) {
5087 goto error;
5088 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005089 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5090 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005092 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005093 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005094
Radek Krejcib8f98c12016-06-24 10:30:46 +02005095 if (!submodule) {
5096 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005097 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005098 if (module->inc_size) {
5099 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5100 if (!module->inc) {
5101 LOGMEM;
5102 goto error;
5103 }
5104 }
5105 if (module->imp_size) {
5106 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5107 if (!module->imp) {
5108 LOGMEM;
5109 goto error;
5110 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005111 }
5112 }
Radek Krejcic071c542016-01-27 14:57:51 +01005113
Radek Krejcif5be10f2015-06-16 13:29:36 +02005114 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005115 * refer to them. Submodule's data nodes are stored in the
5116 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005117 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005118 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005119 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005120 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005121 goto error;
5122 }
Radek Krejci74705112015-06-05 10:25:44 +02005123
Michal Vasko345da0a2015-12-02 10:35:55 +01005124 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005125 }
Radek Krejci74705112015-06-05 10:25:44 +02005126
Radek Krejcif5be10f2015-06-16 13:29:36 +02005127 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005128 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005129
Radek Krejci1d82ef62015-08-07 14:44:40 +02005130 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005131 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005132 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005133 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005134 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005135 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005136 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005137 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005138 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005139 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005140 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005141 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005142 } else if (!strcmp(child->name, "anyxml")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005143 node = read_yin_anyxml(trg, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005144 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005145 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005146 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005147 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005148 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005149 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005150 goto error;
5151 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005152
Michal Vasko345da0a2015-12-02 10:35:55 +01005153 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005154 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005155
Michal Vasko2f7925f2015-10-21 15:06:56 +02005156 /* ... and finally augments (last, so we can augment our data, for instance) */
5157 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005158 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5159 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005160
Michal Vasko2f7925f2015-10-21 15:06:56 +02005161 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005162 goto error;
5163 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005164 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005165 }
5166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005168
5169error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 /* cleanup */
5171 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005172 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 }
5174 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005175 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005177 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005178 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005179 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005181 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005182}
5183
Michal Vasko0d343d12015-08-24 14:57:36 +02005184/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005185struct lys_submodule *
5186yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005187{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005188 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005189 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005191
Michal Vasko5a721fd2016-02-16 12:16:48 +01005192 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005193
Radek Krejci722b0072016-02-01 17:09:45 +01005194 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005195 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005196 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005197 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005199 /* check root element */
5200 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005201 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005202 goto error;
5203 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005205 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005206 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005207 goto error;
5208 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005209
Michal Vasko5a721fd2016-02-16 12:16:48 +01005210 submodule = calloc(1, sizeof *submodule);
5211 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005212 LOGMEM;
5213 goto error;
5214 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005215
Michal Vasko5a721fd2016-02-16 12:16:48 +01005216 submodule->ctx = module->ctx;
5217 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5218 submodule->type = 1;
5219 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005220
Michal Vasko5a721fd2016-02-16 12:16:48 +01005221 LOGVRB("Reading submodule \"%s\".", submodule->name);
5222 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 goto error;
5224 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005227 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005228
Michal Vasko5a721fd2016-02-16 12:16:48 +01005229 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005230 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005231
5232error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005233 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005234 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005235 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005236
Michal Vasko5a721fd2016-02-16 12:16:48 +01005237 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005238 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005239 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005240 }
5241
Michal Vasko5a721fd2016-02-16 12:16:48 +01005242 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005243
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005244 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5245 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005246 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005247 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005248}
5249
Michal Vasko0d343d12015-08-24 14:57:36 +02005250/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005251struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005252yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005253{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005254 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005255 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005256 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005258 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005259
Radek Krejcic071c542016-01-27 14:57:51 +01005260 unres = calloc(1, sizeof *unres);
5261 if (!unres) {
5262 LOGMEM;
5263 return NULL;
5264 }
5265
Radek Krejci722b0072016-02-01 17:09:45 +01005266 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005268 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005269 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005271 /* check root element */
5272 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005273 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005274 goto error;
5275 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005277 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005278 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 goto error;
5280 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005282 module = calloc(1, sizeof *module);
5283 if (!module) {
5284 LOGMEM;
5285 goto error;
5286 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 module->ctx = ctx;
5289 module->name = lydict_insert(ctx, value, strlen(value));
5290 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005291 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005292
Michal Vasko9f258e42016-02-11 11:36:27 +01005293 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005294 if (read_sub_module(module, NULL, yin, unres)) {
5295 goto error;
5296 }
5297
5298 /* resolve rest of unres items */
5299 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005300 goto error;
5301 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005302
Radek Krejciff4874d2016-03-07 12:30:50 +01005303 if (revision) {
5304 /* check revision of the parsed model */
5305 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005306 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5307 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005308 goto error;
5309 }
5310 }
5311
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005312 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005313 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005314 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005315
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005316 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005317 if (!module->implemented) {
5318 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5319 }
Michal Vasko26055752016-05-03 11:36:31 +02005320 if (lys_module_set_implement(module)) {
5321 goto error;
5322 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005323
Michal Vasko26055752016-05-03 11:36:31 +02005324 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5325 goto error;
5326 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005327 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005328 if (!module->inc[i].submodule) {
5329 continue;
5330 }
Michal Vasko26055752016-05-03 11:36:31 +02005331 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5332 goto error;
5333 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005334 }
5335 }
5336
Michal Vasko345da0a2015-12-02 10:35:55 +01005337 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005338 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005339 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005341
5342error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005343 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005344 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005345 unres_schema_free(module, &unres);
5346
5347 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005348 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005349 return NULL;
5350 }
5351
5352 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005353
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005354 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005355 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005356 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005357}