blob: c2d3aa75b07cdae9b6c5b27bd89436ac468dbf56 [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 Krejcibf2abff2016-08-23 15:51:52 +020056static struct lys_node *read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
57 LYS_NODE type, 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 Krejcif1ee2e22016-08-02 16:36:48 +0200125 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200126 const char *value;
Radek Krejci018f1f52016-08-03 16:01:20 +0200127 int rc;
128 int c_ftrs = 0, c_base = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200129
Michal Vasko4cfcd252015-08-03 14:31:10 +0200130 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100131 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200132
Radek Krejci76512572015-08-04 09:47:08 +0200133 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200134 return EXIT_FAILURE;
135 }
Radek Krejci04581c62015-05-22 21:24:00 +0200136
Pavol Vicand6cda452016-07-13 15:08:29 +0200137 if (dup_identities_check(ident->name, module)) {
138 return EXIT_FAILURE;
139 }
140
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200141 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200142 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
143 /* garbage */
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200144 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200145 continue;
146 }
147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 if (!strcmp(node->name, "base")) {
Radek Krejci018f1f52016-08-03 16:01:20 +0200149 if (c_base && (module->version < 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100150 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200151 return EXIT_FAILURE;
152 }
Radek Krejci018f1f52016-08-03 16:01:20 +0200153 c_base++;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100154
Radek Krejci018f1f52016-08-03 16:01:20 +0200155 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
156 c_ftrs++;
157
158 } else {
159 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name, "identity");
160 return EXIT_FAILURE;
161 }
162 }
163
164 if (c_base) {
165 ident->base_size = 0;
166 ident->base = calloc(c_base, sizeof *ident->base);
167 if (!ident->base) {
168 LOGMEM;
169 return EXIT_FAILURE;
170 }
171 }
172
173 if (c_ftrs) {
174 ident->iffeature = calloc(c_ftrs, sizeof *ident->iffeature);
175 if (!ident->iffeature) {
176 LOGMEM;
177 return EXIT_FAILURE;
178 }
179 }
180
181 LY_TREE_FOR(yin->child, node) {
182 if (!strcmp(node->name, "base")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200183 GETVAL(value, node, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100184 value = transform_schema2json(module, value);
Michal Vaskoc94283a2015-10-29 09:07:20 +0100185 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200186 return EXIT_FAILURE;
187 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100188
Radek Krejci48464ed2016-03-17 15:44:09 +0100189 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value) == -1) {
Michal Vaskoc94283a2015-10-29 09:07:20 +0100190 lydict_remove(module->ctx, value);
191 return EXIT_FAILURE;
192 }
193 lydict_remove(module->ctx, value);
Radek Krejci018f1f52016-08-03 16:01:20 +0200194 } else if (!strcmp(node->name, "if-feature")) {
195 rc = fill_yin_iffeature((struct lys_node *)ident, node, &ident->iffeature[ident->iffeature_size], unres);
196 ident->iffeature_size++;
197 if (rc) {
198 return EXIT_FAILURE;
199 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200200 }
201 }
202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200203 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200204
205error:
206 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200207}
208
Michal Vasko0d343d12015-08-24 14:57:36 +0200209/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200210static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200211read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200212{
Radek Krejci73adb602015-07-02 18:07:40 +0200213 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200214 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200215
Radek Krejci73adb602015-07-02 18:07:40 +0200216 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200217 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
218 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200219 continue;
220 }
221
Radek Krejci41726f92015-06-19 13:11:05 +0200222 if (!strcmp(child->name, "description")) {
223 if (restr->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100224 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200225 return EXIT_FAILURE;
226 }
227 restr->dsc = read_yin_subnode(ctx, child, "text");
228 if (!restr->dsc) {
229 return EXIT_FAILURE;
230 }
231 } else if (!strcmp(child->name, "reference")) {
232 if (restr->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100233 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200234 return EXIT_FAILURE;
235 }
236 restr->ref = read_yin_subnode(ctx, child, "text");
237 if (!restr->ref) {
238 return EXIT_FAILURE;
239 }
240 } else if (!strcmp(child->name, "error-app-tag")) {
241 if (restr->eapptag) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100242 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200243 return EXIT_FAILURE;
244 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200245 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200246 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200247 } else if (!strcmp(child->name, "error-message")) {
248 if (restr->emsg) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100249 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200250 return EXIT_FAILURE;
251 }
252 restr->emsg = read_yin_subnode(ctx, child, "value");
253 if (!restr->emsg) {
254 return EXIT_FAILURE;
255 }
256 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100257 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200258 return EXIT_FAILURE;
259 }
Radek Krejci41726f92015-06-19 13:11:05 +0200260 }
261
262 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200263
264error:
265 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200266}
267
Michal Vasko88c29542015-11-27 14:57:53 +0100268/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
269int
Radek Krejcib8048692015-08-05 13:36:34 +0200270fill_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 +0200271 int tpdftype, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200272{
Michal Vasko0aee5c12016-06-17 14:27:26 +0200273 const char *value, *name;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200274 struct lys_node *siter;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200275 struct lyxml_elem *next, *next2, *node, *child;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200276 struct lys_restr **restr;
Radek Krejci1c5890d2016-08-02 13:15:42 +0200277 struct lys_type_bit bit, *bits_sc = NULL;
278 struct lys_type_enum *enms_sc = NULL; /* shortcut */
Radek Krejcie663e012016-08-01 17:12:34 +0200279 struct lys_type *dertype;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200280 int i, j, rc, val_set, c_ftrs;
Radek Krejcidc008d72016-02-17 13:12:14 +0100281 int ret = -1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200282 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200283 int64_t p, p_;
Radek Krejci0d23e7a2016-08-04 12:46:17 +0200284 size_t len;
285 char *buf, modifier;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200286
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200287 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100288 value = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +0200289 if (!value) {
290 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200291 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200292
293 i = parse_identifier(value);
294 if (i < 1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100295 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100296 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200297 goto error;
298 }
299 /* module name */
Radek Krejci225376f2016-02-16 17:36:22 +0100300 name = value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200301 if (value[i]) {
302 type->module_name = lydict_insert(module->ctx, value, i);
Radek Krejci225376f2016-02-16 17:36:22 +0100303 name += i;
304 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100305 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Michal Vasko88c29542015-11-27 14:57:53 +0100306 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200307 goto error;
308 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200309 /* name is in dictionary, but moved */
Radek Krejci225376f2016-02-16 17:36:22 +0100310 ++name;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200311 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200312
Radek Krejci225376f2016-02-16 17:36:22 +0100313 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200314 if (rc == -1) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100315 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200316 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200317 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100318
319 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200320 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200321 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200322 lydict_remove(module->ctx, value);
Radek Krejcidc008d72016-02-17 13:12:14 +0100323 ret = EXIT_FAILURE;
324 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200325 }
Michal Vasko5b61c6d2016-06-06 15:15:30 +0200326 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200327
328 if (type->base == LY_TYPE_INGRP) {
329 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
330 * unresolved item left inside the grouping */
331 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
332 if (siter) {
333 if (!((struct lys_node_grp *)siter)->nacm) {
334 LOGINT;
335 goto error;
336 }
337 ((struct lys_node_grp *)siter)->nacm--;
338 } else {
339 LOGINT;
340 goto error;
341 }
342 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200344
Radek Krejcicf509982015-12-15 09:22:44 +0100345 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100346 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejci48464ed2016-03-17 15:44:09 +0100347 type->der->flags, type->der->module, type->der->name, parent)) {
Radek Krejcicf509982015-12-15 09:22:44 +0100348 return -1;
349 }
350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200351 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200352 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200353 /* RFC 6020 9.7.4 - bit */
354
355 /* get bit specifications, at least one must be present */
356 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200357 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
358 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100359 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200360 continue;
361 }
362
Radek Krejci994b6f62015-06-18 16:47:27 +0200363 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200364 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200365 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100366 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200367 type->info.bits.count = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200368 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200369 }
370 }
Radek Krejcie663e012016-08-01 17:12:34 +0200371 dertype = &type->der->type;
372 if (!dertype->der) {
373 if (!type->info.bits.count) {
374 /* type is derived directly from buit-in bits type and bit statement is required */
375 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
376 goto error;
377 }
378 } else {
379 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
380 if (module->version < 2 && type->info.bits.count) {
381 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
382 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
383 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Radek Krejci69794c62016-08-02 11:01:21 +0200384 type->info.bits.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200385 goto error;
386 }
Radek Krejciac781922015-07-09 15:35:14 +0200387 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200388
389 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100390 if (!type->info.bits.bit) {
391 LOGMEM;
392 goto error;
393 }
Radek Krejci73adb602015-07-02 18:07:40 +0200394 p = 0;
395 i = -1;
396 LY_TREE_FOR(yin->child, next) {
397 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200398 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200399
400 GETVAL(value, next, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +0100401 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100402 goto error;
403 }
404
Radek Krejci994b6f62015-06-18 16:47:27 +0200405 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200406 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200407 type->info.bits.count = i + 1;
408 goto error;
409 }
410
Radek Krejcie663e012016-08-01 17:12:34 +0200411 if (!dertype->der) { /* directly derived type from bits built-in type */
412 /* check the name uniqueness */
413 for (j = 0; j < i; j++) {
414 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
415 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
416 type->info.bits.count = i + 1;
417 goto error;
418 }
419 }
420 } else {
421 /* restricted bits type - the name MUST be used in the base type */
422 bits_sc = dertype->info.bits.bit;
423 for (j = 0; j < dertype->info.bits.count; j++) {
424 if (ly_strequal(bits_sc[j].name, value, 1)) {
425 break;
426 }
427 }
428 if (j == dertype->info.bits.count) {
429 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci994b6f62015-06-18 16:47:27 +0200430 type->info.bits.count = i + 1;
431 goto error;
432 }
433 }
434
Radek Krejcie663e012016-08-01 17:12:34 +0200435
Radek Krejci0d70c372015-07-02 16:23:10 +0200436 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200437 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200438 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
439 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200440 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200441 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200442
Radek Krejci0d70c372015-07-02 16:23:10 +0200443 if (!strcmp(node->name, "position")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200444 if (p_ != -1) {
445 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
446 type->info.bits.count = i + 1;
447 goto error;
448 }
449
Radek Krejci0d70c372015-07-02 16:23:10 +0200450 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200451 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200452
453 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200454 if (p_ < 0 || p_ > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100455 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200456 type->info.bits.count = i + 1;
457 goto error;
458 }
459 type->info.bits.bit[i].pos = (uint32_t)p_;
460
Radek Krejcie663e012016-08-01 17:12:34 +0200461 if (!dertype->der) { /* directly derived type from bits built-in type */
462 /* keep the highest enum value for automatic increment */
463 if (type->info.bits.bit[i].pos >= p) {
464 p = type->info.bits.bit[i].pos;
465 p++;
466 } else {
467 /* check that the value is unique */
468 for (j = 0; j < i; j++) {
469 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
470 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL,
471 type->info.bits.bit[i].pos, type->info.bits.bit[i].name,
472 type->info.bits.bit[j].name);
473 type->info.bits.count = i + 1;
474 goto error;
475 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200476 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200477 }
478 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200479
480 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
481 c_ftrs++;
Radek Krejci0d70c372015-07-02 16:23:10 +0200482 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100483 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200484 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200485 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200486 }
Radek Krejcie663e012016-08-01 17:12:34 +0200487
488 if (!dertype->der) { /* directly derived type from bits built-in type */
489 if (p_ == -1) {
490 /* assign value automatically */
491 if (p > UINT32_MAX) {
492 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
493 type->info.bits.count = i + 1;
494 goto error;
495 }
496 type->info.bits.bit[i].pos = (uint32_t)p;
497 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
498 p++;
Radek Krejci994b6f62015-06-18 16:47:27 +0200499 }
Radek Krejcie663e012016-08-01 17:12:34 +0200500 } else { /* restricted bits type */
501 if (p_ == -1) {
502 /* automatically assign position from base type */
503 type->info.bits.bit[i].pos = bits_sc[j].pos;
504 type->info.bits.bit[i].flags |= LYS_AUTOASSIGNED;
505 } else {
506 /* check that the assigned position corresponds to the original
507 * position of the bit in the base type */
508 if (p_ != bits_sc[j].pos) {
509 /* p_ - assigned position in restricted bits
510 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
511 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
Radek Krejci541a45d2016-08-02 13:12:07 +0200512 type->info.bits.bit[i].name, bits_sc[j].pos);
Radek Krejcie663e012016-08-01 17:12:34 +0200513 type->info.bits.count = i + 1;
514 goto error;
515 }
516 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200517 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200518
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200519 /* if-features */
520 if (c_ftrs) {
521 bits_sc = &type->info.bits.bit[i];
522 bits_sc->iffeature = calloc(c_ftrs, sizeof *bits_sc->iffeature);
523 if (!bits_sc->iffeature) {
524 LOGMEM;
525 type->info.bits.count = i + 1;
526 goto error;
527 }
528
529 LY_TREE_FOR(next->child, node) {
530 if (!strcmp(node->name, "if-feature")) {
531 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
532 &bits_sc->iffeature[bits_sc->iffeature_size], unres);
533 bits_sc->iffeature_size++;
534 if (rc) {
535 type->info.bits.count = i + 1;
536 goto error;
537 }
538 }
539 }
540 }
541
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200542 /* keep them ordered by position */
543 j = i;
544 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
545 /* switch them */
546 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
547 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
548 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
549 j--;
550 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200551 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200554 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200555 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200556 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200557 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
558 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200559 continue;
560 }
561
Radek Krejcif9401c32015-06-26 16:47:36 +0200562 if (!strcmp(node->name, "range")) {
563 if (type->info.dec64.range) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100564 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200565 goto error;
566 }
567
568 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200569 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100570 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200571 goto error;
572 }
573 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100574 if (!type->info.dec64.range) {
575 LOGMEM;
576 goto error;
577 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200578 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
579
580 /* get possible substatements */
581 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
582 goto error;
583 }
584 } else if (!strcmp(node->name, "fraction-digits")) {
585 if (type->info.dec64.dig) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100586 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200587 goto error;
588 }
589 GETVAL(value, node, "value");
590 v = strtol(value, NULL, 10);
591
592 /* range check */
593 if (v < 1 || v > 18) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100594 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200595 goto error;
596 }
597 type->info.dec64.dig = (uint8_t)v;
Radek Krejci8c3b4b62016-06-17 14:32:12 +0200598 type->info.dec64.div = 10;
599 for (i = 1; i < v; i++) {
600 type->info.dec64.div *= 10;
601 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200602 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100603 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200604 goto error;
605 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200606 }
607
608 /* mandatory sub-statement(s) check */
609 if (!type->info.dec64.dig && !type->der->type.der) {
610 /* decimal64 type directly derived from built-in type requires fraction-digits */
Radek Krejci48464ed2016-03-17 15:44:09 +0100611 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200612 goto error;
613 }
Radek Krejci7511f402015-07-10 09:56:30 +0200614 if (type->info.dec64.dig && type->der->type.der) {
615 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Radek Krejci48464ed2016-03-17 15:44:09 +0100616 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200617 goto error;
618 }
Radek Krejcib51d5932016-09-08 14:02:52 +0200619
620 /* copy fraction-digits specification from parent type for easier internal use */
621 if (type->der->type.der) {
622 type->info.dec64.dig = type->der->type.info.dec64.dig;
623 type->info.dec64.div = type->der->type.info.dec64.div;
624 }
625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200628 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200629 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200630
Radek Krejci994b6f62015-06-18 16:47:27 +0200631 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200632 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200633 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
634 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100635 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200636 continue;
637 }
638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200640 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200641 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100642 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci69794c62016-08-02 11:01:21 +0200643 type->info.enums.count = 0;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200644 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200645 }
646 }
Radek Krejcie663e012016-08-01 17:12:34 +0200647 dertype = &type->der->type;
648 if (!dertype->der) {
649 if (!type->info.enums.count) {
650 /* type is derived directly from buit-in enumeartion type and enum statement is required */
651 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
652 goto error;
653 }
654 } else {
655 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
656 if (module->version < 2 && type->info.enums.count) {
657 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
658 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
659 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Radek Krejci69794c62016-08-02 11:01:21 +0200660 type->info.enums.count = 0;
Radek Krejcie663e012016-08-01 17:12:34 +0200661 goto error;
662 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200663 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200664
Radek Krejci1574a8d2015-08-03 14:16:52 +0200665 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100666 if (!type->info.enums.enm) {
667 LOGMEM;
668 goto error;
669 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200670
Radek Krejcie663e012016-08-01 17:12:34 +0200671 v = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200672 i = -1;
673 LY_TREE_FOR(yin->child, next) {
674 i++;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200675 c_ftrs = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200676
677 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100678 if (!value[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100679 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
680 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100681 goto error;
682 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200683 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200684 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200685 type->info.enums.count = i + 1;
686 goto error;
687 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200689 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200690 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100692 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200693 type->info.enums.count = i + 1;
694 goto error;
695 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200696
Radek Krejcie663e012016-08-01 17:12:34 +0200697 if (!dertype->der) { /* directly derived type from enumeration built-in type */
698 /* check the name uniqueness */
699 for (j = 0; j < i; j++) {
700 if (ly_strequal(type->info.enums.enm[j].name, value, 1)) {
701 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, value);
702 type->info.enums.count = i + 1;
703 goto error;
704 }
705 }
706 } else {
707 /* restricted enumeration type - the name MUST be used in the base type */
708 enms_sc = dertype->info.enums.enm;
709 for (j = 0; j < dertype->info.enums.count; j++) {
710 if (ly_strequal(enms_sc[j].name, value, 1)) {
711 break;
712 }
713 }
714 if (j == dertype->info.enums.count) {
715 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 type->info.enums.count = i + 1;
717 goto error;
718 }
719 }
Radek Krejci04581c62015-05-22 21:24:00 +0200720
Radek Krejcie663e012016-08-01 17:12:34 +0200721 val_set = 0;
Radek Krejci73adb602015-07-02 18:07:40 +0200722 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200723 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
724 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200725 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200726 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727
Radek Krejci0d70c372015-07-02 16:23:10 +0200728 if (!strcmp(node->name, "value")) {
Radek Krejcie663e012016-08-01 17:12:34 +0200729 if (val_set) {
730 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, next->name);
731 type->info.enums.count = i + 1;
732 goto error;
733 }
734
Radek Krejci0d70c372015-07-02 16:23:10 +0200735 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200736 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200737
738 /* range check */
739 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100740 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200741 type->info.enums.count = i + 1;
742 goto error;
743 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200744 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200745
Radek Krejcie663e012016-08-01 17:12:34 +0200746 if (!dertype->der) { /* directly derived type from enumeration built-in type */
Pavol Vican5de389c2016-08-30 08:55:15 +0200747 if (!i) {
748 /* change value, which is assigned automatically, if first enum has value. */
Radek Krejcie663e012016-08-01 17:12:34 +0200749 v = type->info.enums.enm[i].value;
750 v++;
751 } else {
Pavol Vican5de389c2016-08-30 08:55:15 +0200752 /* keep the highest enum value for automatic increment */
753 if (type->info.enums.enm[i].value >= v) {
754 v = type->info.enums.enm[i].value;
755 v++;
756 } else {
757 /* check that the value is unique */
758 for (j = 0; j < i; j++) {
759 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
760 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
761 type->info.enums.enm[i].value, type->info.enums.enm[i].name,
762 type->info.enums.enm[j].name);
763 type->info.enums.count = i + 1;
764 goto error;
765 }
Radek Krejcie663e012016-08-01 17:12:34 +0200766 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 }
769 }
Radek Krejcifc8d8322016-06-24 11:23:23 +0200770 val_set = 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200771
772 } else if ((module->version >= 2) && !strcmp(node->name, "if-feature")) {
773 c_ftrs++;
774
Radek Krejci0d70c372015-07-02 16:23:10 +0200775 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100776 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200777 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200778 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200779 }
Radek Krejcie663e012016-08-01 17:12:34 +0200780
781 if (!dertype->der) { /* directly derived type from enumeration */
782 if (!val_set) {
783 /* assign value automatically */
784 if (v > INT32_MAX) {
785 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
786 type->info.enums.count = i + 1;
787 goto error;
788 }
789 type->info.enums.enm[i].value = v;
790 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
791 v++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792 }
Radek Krejcie663e012016-08-01 17:12:34 +0200793 } else { /* restricted enum type */
794 if (!val_set) {
795 /* automatically assign value from base type */
796 type->info.enums.enm[i].value = enms_sc[j].value;
797 type->info.enums.enm[i].flags |= LYS_AUTOASSIGNED;
798 } else {
799 /* check that the assigned value corresponds to the original
800 * value of the enum in the base type */
801 if (v_ != enms_sc[j].value) {
802 /* v_ - assigned value in restricted enum
803 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
804 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL,
Radek Krejci541a45d2016-08-02 13:12:07 +0200805 type->info.enums.enm[i].value, type->info.enums.enm[i].name, enms_sc[j].value);
Radek Krejcie663e012016-08-01 17:12:34 +0200806 type->info.enums.count = i + 1;
807 goto error;
808 }
809 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200810 }
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200811
812 /* if-features */
813 if (c_ftrs) {
814 enms_sc = &type->info.enums.enm[i];
815 enms_sc->iffeature = calloc(c_ftrs, sizeof *enms_sc->iffeature);
816 if (!enms_sc->iffeature) {
817 LOGMEM;
818 type->info.enums.count = i + 1;
819 goto error;
820 }
821
822 LY_TREE_FOR(next->child, node) {
823 if (!strcmp(node->name, "if-feature")) {
824 rc = fill_yin_iffeature((struct lys_node *)type->parent, node,
825 &enms_sc->iffeature[enms_sc->iffeature_size], unres);
826 enms_sc->iffeature_size++;
827 if (rc) {
828 type->info.enums.count = i + 1;
829 goto error;
830 }
831 }
832 }
833 }
834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200835 }
836 break;
837
838 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200839 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200840
Michal Vaskof2d43962016-09-02 11:10:16 +0200841 /* get base specification, at least one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200842 LY_TREE_FOR_SAFE(yin->child, next, node) {
843 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
844 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100845 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200846 continue;
847 }
848
Michal Vaskoe29c6622015-11-27 15:02:31 +0100849 if (strcmp(node->name, "base")) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100850 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200851 goto error;
852 }
Michal Vaskof2d43962016-09-02 11:10:16 +0200853
854 GETVAL(value, yin->child, "name");
855 /* store in the JSON format */
856 value = transform_schema2json(module, value);
857 if (!value) {
858 goto error;
859 }
860 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
861 lydict_remove(module->ctx, value);
862
863 if (rc == -1) {
864 goto error;
865 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200866 }
867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200869 if (type->der->type.der) {
Michal Vaskof2d43962016-09-02 11:10:16 +0200870 /* this is just a derived type with no base required */
Radek Krejci65c889c2015-06-22 10:17:22 +0200871 break;
872 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100873 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200874 goto error;
Pavol Vicanf0046f42016-09-07 15:11:09 +0200875 } else {
876 if (type->der->type.der) {
877 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
878 goto error;
879 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200880 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 if (yin->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100882 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200883 goto error;
884 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200885 break;
886
887 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200888 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200889 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200890 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
891 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200892 continue;
893 }
894
Radek Krejciaf351422015-06-19 14:49:38 +0200895 if (!strcmp(node->name, "require-instance")) {
896 if (type->info.inst.req) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100897 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200898 goto error;
899 }
900 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200901 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200902 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200903 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200904 type->info.inst.req = -1;
905 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100906 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200907 goto error;
908 }
909 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100910 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200911 goto error;
912 }
Radek Krejciaf351422015-06-19 14:49:38 +0200913 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200915 break;
916
Radek Krejcif2860132015-06-20 12:37:20 +0200917 case LY_TYPE_BINARY:
918 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200919 case LY_TYPE_INT8:
920 case LY_TYPE_INT16:
921 case LY_TYPE_INT32:
922 case LY_TYPE_INT64:
923 case LY_TYPE_UINT8:
924 case LY_TYPE_UINT16:
925 case LY_TYPE_UINT32:
926 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200927 /* RFC 6020 9.2.4 - range */
928
929 /* length and range are actually the same restriction, so process
930 * them by this common code, we just need to differ the name and
931 * structure where the information will be stored
932 */
933 if (type->base == LY_TYPE_BINARY) {
934 restr = &type->info.binary.length;
935 name = "length";
936 } else {
937 restr = &type->info.num.range;
938 name = "range";
939 }
940
Radek Krejci73adb602015-07-02 18:07:40 +0200941 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200942 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
943 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200944 continue;
945 }
946
Radek Krejcif2860132015-06-20 12:37:20 +0200947 if (!strcmp(node->name, name)) {
948 if (*restr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100949 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200950 goto error;
951 }
952
953 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200954 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100955 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200956 goto error;
957 }
958 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100959 if (!(*restr)) {
960 LOGMEM;
961 goto error;
962 }
Radek Krejcif2860132015-06-20 12:37:20 +0200963 (*restr)->expr = lydict_insert(module->ctx, value, 0);
964
965 /* get possible substatements */
966 if (read_restr_substmt(module->ctx, *restr, node)) {
967 goto error;
968 }
969 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +0100970 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200971 goto error;
972 }
Radek Krejcif2860132015-06-20 12:37:20 +0200973 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200974 break;
975
976 case LY_TYPE_LEAFREF:
Radek Krejci3a5501d2016-07-18 22:03:34 +0200977 /* flag resolving for later use */
978 if (!tpdftype) {
979 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
980 if (siter) {
981 /* just a flag - do not resolve */
982 tpdftype = 1;
983 }
984 }
985
Radek Krejcidc4c1412015-06-19 15:39:54 +0200986 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200987 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200988 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
989 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200990 continue;
991 }
992
Michal Vasko88c29542015-11-27 14:57:53 +0100993 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200994 if (type->info.lref.path) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100995 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200996 goto error;
997 }
998
999 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +02001000 /* store in the JSON format */
Radek Krejci48464ed2016-03-17 15:44:09 +01001001 type->info.lref.path = transform_schema2json(module, value);
Michal Vasko1dca6882015-10-22 14:29:42 +02001002 if (!type->info.lref.path) {
1003 goto error;
1004 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001005
1006 /* try to resolve leafref path only when this is instantiated
1007 * leaf, so it is not:
1008 * - typedef's type,
1009 * - in grouping definition,
1010 * - just instantiated in a grouping definition,
1011 * because in those cases the nodes referenced in path might not be present
1012 * and it is not a bug. */
1013 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001014 goto error;
1015 }
Michal Vasko08ae53e2016-09-02 12:40:04 +02001016 } else if (!strcmp(node->name, "require-instance")) {
1017 if (type->info.lref.req) {
1018 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
1019 goto error;
1020 }
1021 GETVAL(value, node, "value");
1022 if (!strcmp(value, "true")) {
1023 type->info.lref.req = 1;
1024 } else if (!strcmp(value, "false")) {
1025 type->info.lref.req = -1;
1026 } else {
1027 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
1028 goto error;
1029 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001030 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001031 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001032 goto error;
1033 }
Radek Krejci73adb602015-07-02 18:07:40 +02001034 }
1035
Radek Krejci742be352016-07-17 12:18:54 +02001036 if (!type->info.lref.path) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001037 if (!type->der->type.der) {
1038 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Michal Vasko01c6fd22016-05-20 11:43:05 +02001039 goto error;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001040 } else {
1041 /* copy leafref definition into the derived type */
1042 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
1043 /* and resolve the path at the place we are (if not in grouping/typedef) */
1044 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
1045 goto error;
1046 }
1047
1048 /* add pointer to leafref target, only on leaves (not in typedefs) */
1049 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
1050 goto error;
1051 }
Michal Vasko01c6fd22016-05-20 11:43:05 +02001052 }
Radek Krejcidc4c1412015-06-19 15:39:54 +02001053 }
Radek Krejci742be352016-07-17 12:18:54 +02001054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001055 break;
1056
1057 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001058 /* RFC 6020 9.4.4 - length */
1059 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001060 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001061 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001062 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1063 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001064 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001065 continue;
1066 }
1067
Radek Krejci3733a802015-06-19 13:43:21 +02001068 if (!strcmp(node->name, "length")) {
1069 if (type->info.str.length) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001070 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001071 goto error;
1072 }
1073
1074 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +02001075 if (lyp_check_length_range(value, type)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001076 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +02001077 goto error;
1078 }
1079 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +01001080 if (!type->info.str.length) {
1081 LOGMEM;
1082 goto error;
1083 }
Radek Krejci3733a802015-06-19 13:43:21 +02001084 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1085
Radek Krejci5fbc9162015-06-19 14:11:11 +02001086 /* get possible sub-statements */
1087 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001088 goto error;
1089 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001090 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001091 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001092 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001093 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001094 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001095 goto error;
1096 }
1097 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001098 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001099 if (i) {
1100 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +01001101 if (!type->info.str.patterns) {
1102 LOGMEM;
1103 goto error;
1104 }
Radek Krejci73adb602015-07-02 18:07:40 +02001105 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001106 GETVAL(value, node, "value");
Michal Vasko0aee5c12016-06-17 14:27:26 +02001107 if (lyp_check_pattern(value, NULL)) {
Michal Vasko69068852015-07-13 14:34:31 +02001108 free(type->info.str.patterns);
Radek Krejci9f1e8532016-06-16 11:18:21 +02001109 type->info.str.patterns = NULL;
Michal Vasko69068852015-07-13 14:34:31 +02001110 goto error;
1111 }
Michal Vasko69068852015-07-13 14:34:31 +02001112
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001113 modifier = 0x06; /* ACK */
1114 name = NULL;
1115 LY_TREE_FOR_SAFE(node->child, next2, child) {
1116 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1117 /* garbage */
1118 lyxml_free(module->ctx, child);
1119 continue;
1120 }
1121
1122 if (module->version >= 2 && !strcmp(child->name, "modifier")) {
1123 if (name) {
1124 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
1125 goto error;
1126 }
1127
1128 GETVAL(name, child, "value");
1129 if (!strcmp(name, "invert-match")) {
1130 modifier = 0x15; /* NACK */
1131 } else {
1132 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
1133 goto error;
1134 }
1135 lyxml_free(module->ctx, child);
1136 }
1137 }
1138
1139 len = strlen(value);
1140 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
1141 buf[0] = modifier;
1142 strcpy(&buf[1], value);
1143
1144 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, buf);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001145
1146 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +01001147 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +02001148 free(type->info.str.patterns);
Pavol Vican9fc5d642016-08-30 15:23:19 +02001149 type->info.str.patterns = NULL;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001150 goto error;
1151 }
Radek Krejci73adb602015-07-02 18:07:40 +02001152 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001153 }
1154 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001155 break;
1156
1157 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001158 /* RFC 6020 7.4 - type */
1159 /* count number of types in union */
1160 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001161 LY_TREE_FOR_SAFE(yin->child, next, node) {
1162 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1163 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001164 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +02001165 continue;
1166 }
1167
Radek Krejcie4c366b2015-07-02 10:11:31 +02001168 if (!strcmp(node->name, "type")) {
Radek Krejci038d5d92016-09-12 15:07:15 +02001169 if (type->der->type.der) {
1170 /* type can be a substatement only in "union" type, not in derived types */
1171 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1172 goto error;
1173 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001174 i++;
1175 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001176 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001177 goto error;
1178 }
1179 }
1180
Radek Krejci038d5d92016-09-12 15:07:15 +02001181 if (!i && !type->der->type.der) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001182 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001183 goto error;
1184 }
1185
1186 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001187 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +01001188 if (!type->info.uni.types) {
1189 LOGMEM;
1190 goto error;
1191 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001192 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001193 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +01001194 type->info.uni.types[type->info.uni.count].parent = type->parent;
Radek Krejci3a5501d2016-07-18 22:03:34 +02001195 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], tpdftype, unres);
Michal Vasko88c29542015-11-27 14:57:53 +01001196 if (!rc) {
1197 type->info.uni.count++;
1198
Radek Krejci7de36cf2016-09-12 16:18:50 +02001199 if (module->version < 2) {
1200 /* union's type cannot be empty or leafref */
1201 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
1202 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", node->name);
1203 rc = -1;
1204 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
1205 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", node->name);
1206 rc = -1;
1207 }
Michal Vasko88c29542015-11-27 14:57:53 +01001208 }
1209 }
1210 if (rc) {
1211 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
1212 for (i = 0; i < type->info.uni.count; ++i) {
1213 lys_type_free(module->ctx, &type->info.uni.types[i]);
1214 }
1215 free(type->info.uni.types);
1216 type->info.uni.types = NULL;
1217 type->info.uni.count = 0;
Michal Vaskoeac08182016-07-21 12:16:32 +02001218 type->der = NULL;
1219 type->base = LY_TYPE_DER;
Michal Vasko88c29542015-11-27 14:57:53 +01001220
1221 if (rc == EXIT_FAILURE) {
Radek Krejcidc008d72016-02-17 13:12:14 +01001222 ret = EXIT_FAILURE;
Michal Vasko88c29542015-11-27 14:57:53 +01001223 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001224 goto error;
1225 }
Michal Vasko88c29542015-11-27 14:57:53 +01001226 }
1227 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001228
Michal Vasko88c29542015-11-27 14:57:53 +01001229 case LY_TYPE_BOOL:
1230 case LY_TYPE_EMPTY:
1231 /* no sub-statement allowed */
1232 LY_TREE_FOR(yin->child, node) {
1233 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001234 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001235 goto error;
1236 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001237 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 break;
1239
1240 default:
Michal Vasko88c29542015-11-27 14:57:53 +01001241 LOGINT;
1242 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001243 }
1244
1245 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001246
1247error:
Radek Krejcidc008d72016-02-17 13:12:14 +01001248 if (type->module_name) {
1249 lydict_remove(module->ctx, type->module_name);
1250 type->module_name = NULL;
1251 }
1252 return ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001253}
1254
Michal Vasko0d343d12015-08-24 14:57:36 +02001255/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001256static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001257fill_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 +02001258{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001259 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +01001260 struct lyxml_elem *node, *next;
Radek Krejci48464ed2016-03-17 15:44:09 +01001261 int has_type = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001263 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001264 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001265 goto error;
1266 }
1267 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001269 /* generic part - status, description, reference */
Radek Krejci225376f2016-02-16 17:36:22 +01001270 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001271 goto error;
1272 }
Radek Krejcieac35532015-05-31 19:09:15 +02001273
Michal Vasko88c29542015-11-27 14:57:53 +01001274 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001275 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1276 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001277 continue;
1278 }
1279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001280 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01001281 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001282 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001283 goto error;
1284 }
Michal Vasko88c29542015-11-27 14:57:53 +01001285 /* HACK for unres */
1286 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +01001287 tpdf->type.parent = tpdf;
Michal Vasko5d631402016-07-21 13:15:15 +02001288 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Radek Krejci73adb602015-07-02 18:07:40 +02001289 goto error;
1290 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001291 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001292 } else if (!strcmp(node->name, "default")) {
1293 if (tpdf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001294 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001295 goto error;
1296 }
1297 GETVAL(value, node, "value");
1298 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
1299 } else if (!strcmp(node->name, "units")) {
1300 if (tpdf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001301 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001302 goto error;
1303 }
1304 GETVAL(value, node, "name");
1305 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1306 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001307 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001308 goto error;
1309 }
1310 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001312 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001313 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001314 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001315 goto error;
1316 }
Radek Krejcieac35532015-05-31 19:09:15 +02001317
Michal Vasko478c4652016-07-21 12:55:01 +02001318 /* check default value (if not defined, there still could be some restrictions
1319 * that need to be checked against a default value from a derived type) */
1320 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt) == -1) {
1321 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001324 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001325
1326error:
1327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001328 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001329}
1330
Michal Vasko0d343d12015-08-24 14:57:36 +02001331/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001332static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001333fill_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 +02001334{
1335 const char *value;
1336 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001337 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001338
Radek Krejcib05774c2015-06-18 13:52:59 +02001339 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01001340 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +02001341 goto error;
1342 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001343 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001344 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001345
Radek Krejci76512572015-08-04 09:47:08 +02001346 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001347 goto error;
1348 }
1349
1350 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001351 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1352 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001353 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001354 continue;
1355 }
1356
Radek Krejci3cf9e222015-06-18 11:37:50 +02001357 if (!strcmp(child->name, "if-feature")) {
1358 c++;
1359 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001360 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001361 goto error;
1362 }
1363 }
1364
1365 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001366 f->iffeature = calloc(c, sizeof *f->iffeature);
1367 if (!f->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01001368 LOGMEM;
1369 goto error;
1370 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001371 }
Radek Krejci73adb602015-07-02 18:07:40 +02001372 LY_TREE_FOR(yin->child, child) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02001373 ret = fill_yin_iffeature((struct lys_node *)f, child, &f->iffeature[f->iffeature_size], unres);
1374 f->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01001375 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001376 goto error;
1377 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001378 }
1379
Radek Krejcic79c6b12016-07-26 15:11:49 +02001380 /* check for circular dependencies */
1381 if (f->iffeature_size) {
1382 if (unres_schema_add_node(module, unres, f, UNRES_FEATURE, NULL) == -1) {
1383 goto error;
1384 }
1385 }
1386
Radek Krejci3cf9e222015-06-18 11:37:50 +02001387 return EXIT_SUCCESS;
1388
1389error:
1390
1391 return EXIT_FAILURE;
1392}
1393
Michal Vasko0d343d12015-08-24 14:57:36 +02001394/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001395static int
Radek Krejcib8048692015-08-05 13:36:34 +02001396fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001397{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001398 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001400 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01001401 must->expr = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02001402 if (!must->expr) {
1403 goto error;
1404 }
Radek Krejci800af702015-06-02 13:46:01 +02001405
Radek Krejci41726f92015-06-19 13:11:05 +02001406 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001407
Michal Vasko77dc5652016-02-15 12:32:42 +01001408error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001409 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001410}
1411
Radek Krejci581ce772015-11-10 17:22:40 +01001412static int
Michal Vasko88c29542015-11-27 14:57:53 +01001413fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1414 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001415{
1416 int i, j;
1417 const char *value, *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +02001418 struct unres_list_uniq *unique_info;
Radek Krejci581ce772015-11-10 17:22:40 +01001419
1420 /* get unique value (list of leafs supposed to be unique */
1421 GETVAL(value, yin, "tag");
1422
1423 /* count the number of unique leafs in the value */
1424 vaux = value;
1425 while ((vaux = strpbrk(vaux, " \t\n"))) {
Michal Vasko98645db2016-03-07 14:38:49 +01001426 unique->expr_size++;
Radek Krejci581ce772015-11-10 17:22:40 +01001427 while (isspace(*vaux)) {
1428 vaux++;
1429 }
1430 }
1431 unique->expr_size++;
1432 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001433 if (!unique->expr) {
1434 LOGMEM;
1435 goto error;
1436 }
Radek Krejci581ce772015-11-10 17:22:40 +01001437
1438 for (i = 0; i < unique->expr_size; i++) {
1439 vaux = strpbrk(value, " \t\n");
1440 if (!vaux) {
1441 /* the last token, lydict_insert() will count its size on its own */
1442 vaux = value;
1443 }
1444
1445 /* store token into unique structure */
1446 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1447
1448 /* check that the expression does not repeat */
1449 for (j = 0; j < i; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01001450 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001451 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, unique->expr[i], "unique");
1452 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Radek Krejci581ce772015-11-10 17:22:40 +01001453 goto error;
1454 }
1455 }
1456
1457 /* try to resolve leaf */
1458 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001459 unique_info = malloc(sizeof *unique_info);
1460 unique_info->list = parent;
1461 unique_info->expr = unique->expr[i];
1462 unique_info->trg_type = &unique->trg_type;
1463 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1){
Pavol Vican18b10212016-04-11 15:41:52 +02001464 goto error;
1465 }
Radek Krejci581ce772015-11-10 17:22:40 +01001466 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +02001467 if (resolve_unique(parent, unique->expr[i], &unique->trg_type)) {
Radek Krejci581ce772015-11-10 17:22:40 +01001468 goto error;
1469 }
1470 }
1471
1472 /* move to next token */
1473 value = vaux;
1474 while(isspace(*value)) {
1475 value++;
1476 }
1477 }
1478
1479 return EXIT_SUCCESS;
1480
1481error:
1482 return EXIT_FAILURE;
1483}
1484
Michal Vasko0d343d12015-08-24 14:57:36 +02001485/* logs directly
1486 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001487 * type: 0 - min, 1 - max
1488 */
1489static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001490deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001491{
1492 const char *value;
1493 char *endptr;
1494 unsigned long val;
Pavol Vican09adcc32016-08-25 10:51:36 +02001495 uint32_t *ui32val, *min, *max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001496
Michal Vaskof7e57d52016-03-07 11:31:09 +01001497 /* del min/max is forbidden */
1498 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001499 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, (type ? "max-elements" : "min-elements"), "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001500 goto error;
1501 }
1502
Radek Krejcieb00f512015-07-01 16:44:58 +02001503 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001504 if (target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001505 max = &((struct lys_node_leaflist *)target)->max;
1506 min = &((struct lys_node_leaflist *)target)->min;
Radek Krejci76512572015-08-04 09:47:08 +02001507 } else if (target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02001508 max = &((struct lys_node_list *)target)->max;
1509 min = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001510 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001511 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1512 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 goto error;
1514 }
1515
1516 GETVAL(value, node, "value");
1517 while (isspace(value[0])) {
1518 value++;
1519 }
1520
Radek Krejci0d7b2472016-02-12 11:11:03 +01001521 if (type && !strcmp(value, "unbounded")) {
1522 d->max = val = 0;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001523 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001524 ui32val = max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001525 } else {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001526 /* convert it to uint32_t */
1527 errno = 0;
1528 endptr = NULL;
1529 val = strtoul(value, &endptr, 10);
1530 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001531 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, node->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01001532 goto error;
1533 }
1534 if (type) {
1535 d->max = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001536 d->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001537 ui32val = max;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001538 } else {
1539 d->min = (uint32_t)val;
Radek Krejcia31ca7a2016-03-07 15:05:20 +01001540 d->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02001541 ui32val = min;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001542 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 }
1544
1545 if (d->mod == LY_DEVIATE_ADD) {
1546 /* check that there is no current value */
1547 if (*ui32val) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001548 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, node->name);
1549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 goto error;
1551 }
Michal Vasko21be1b32016-03-07 12:31:34 +01001552 } else if (d->mod == LY_DEVIATE_RPL) {
1553 /* unfortunately, there is no way to check reliably that there
1554 * was a value before, it could have been the default */
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 }
1556
Michal Vaskof7e57d52016-03-07 11:31:09 +01001557 /* add (already checked) and replace */
1558 /* set new value specified in deviation */
1559 *ui32val = (uint32_t)val;
Radek Krejcieb00f512015-07-01 16:44:58 +02001560
Pavol Vican09adcc32016-08-25 10:51:36 +02001561 /* check min-elements is smaller than max-elements */
1562 if (*max && *min > *max) {
1563 if (type) {
1564 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1565 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1566 } else {
1567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1568 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1569 }
1570 goto error;
1571 }
1572
Radek Krejcieb00f512015-07-01 16:44:58 +02001573 return EXIT_SUCCESS;
1574
1575error:
1576
1577 return EXIT_FAILURE;
1578}
1579
Michal Vasko0d343d12015-08-24 14:57:36 +02001580/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001581static int
Michal Vasko88c29542015-11-27 14:57:53 +01001582fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1583 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001584{
1585 const char *value, **stritem;
1586 struct lyxml_elem *next, *child, *develem;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001587 int c_dev = 0, c_must, c_uniq, c_dflt;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001588 int f_min = 0, f_max = 0; /* flags */
Michal Vaskob40b4512016-02-11 11:35:37 +01001589 int i, j, rc;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001590 unsigned int u;
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001591 struct ly_ctx *ctx;
Radek Krejcia52656e2015-08-05 13:41:50 +02001592 struct lys_deviate *d = NULL;
Radek Krejcie00d2312016-08-12 15:27:49 +02001593 struct lys_node *node = NULL, *parent, *dev_target = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001594 struct lys_node_choice *choice = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001595 struct lys_node_leaf *leaf = NULL;
1596 struct ly_set *dflt_check = ly_set_new();
Radek Krejcib8048692015-08-05 13:36:34 +02001597 struct lys_node_list *list = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001598 struct lys_node_leaflist *llist = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001599 struct lys_type *t = NULL;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001600 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001601 struct lys_restr **trg_must = NULL;
Michal Vaskoff006c12016-02-17 11:15:19 +01001602 struct unres_schema tmp_unres;
Radek Krejcieb00f512015-07-01 16:44:58 +02001603
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001604 ctx = module->ctx;
1605
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01001607 dev->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02001608 if (!dev->target_name) {
1609 goto error;
1610 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001611
1612 /* resolve target node */
Michal Vasko60f4b452016-02-12 11:02:55 +01001613 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1614 if (rc || !dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001615 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001616 goto error;
1617 }
Radek Krejcic4283442016-04-22 09:19:27 +02001618 if (dev_target->module == lys_main_module(module)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001619 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, yin->name);
1620 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001621 goto error;
1622 }
Michal Vasko89563fc2016-07-28 16:19:35 +02001623 lys_node_module(dev_target)->deviated = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001624
1625 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001626 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1627 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001628 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001629 continue;
1630 }
1631
Radek Krejcieb00f512015-07-01 16:44:58 +02001632 if (!strcmp(child->name, "description")) {
1633 if (dev->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001634 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 goto error;
1636 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001637 dev->dsc = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 if (!dev->dsc) {
1639 goto error;
1640 }
1641 } else if (!strcmp(child->name, "reference")) {
1642 if (dev->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001643 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 goto error;
1645 }
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001646 dev->ref = read_yin_subnode(ctx, child, "text");
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 if (!dev->ref) {
1648 goto error;
1649 }
1650 } else if (!strcmp(child->name, "deviate")) {
1651 c_dev++;
1652
Michal Vasko345da0a2015-12-02 10:35:55 +01001653 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 * further processed later
1655 */
1656 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001657
Radek Krejcieb00f512015-07-01 16:44:58 +02001658 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001659 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 goto error;
1661 }
1662
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001663 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001664 }
1665
1666 if (c_dev) {
1667 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001668 if (!dev->deviate) {
1669 LOGMEM;
1670 goto error;
1671 }
Pavol Vican09adcc32016-08-25 10:51:36 +02001672 } else {
1673 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
1674 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001675 }
1676
1677 LY_TREE_FOR(yin->child, develem) {
1678 /* init */
1679 f_min = 0;
Radek Krejci0d7b2472016-02-12 11:11:03 +01001680 f_max = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001681 c_must = 0;
1682 c_uniq = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02001683 c_dflt = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02001684
1685 /* get deviation type */
1686 GETVAL(value, develem, "value");
1687 if (!strcmp(value, "not-supported")) {
1688 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1689 /* no property expected in this case */
1690 if (develem->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001691 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 goto error;
1693 }
1694
Radek Krejci5b917642015-07-02 09:03:13 +02001695 /* and neither any other deviate statement is expected,
1696 * not-supported deviation must be the only deviation of the target
1697 */
1698 if (dev->deviate_size || develem->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001699 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1700 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001701 goto error;
1702 }
1703
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001704 /* you cannot remove a key leaf */
Michal Vasko43c94772016-05-03 11:47:44 +02001705 if ((dev_target->nodetype == LYS_LEAF) && lys_parent(dev_target) && (lys_parent(dev_target)->nodetype == LYS_LIST)) {
1706 for (i = 0; i < ((struct lys_node_list *)lys_parent(dev_target))->keys_size; ++i) {
1707 if (((struct lys_node_list *)lys_parent(dev_target))->keys[i] == (struct lys_node_leaf *)dev_target) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001708 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
1709 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Michal Vaskoad1f7b72016-02-17 11:13:58 +01001710 goto error;
1711 }
1712 }
1713 }
Radek Krejci5b917642015-07-02 09:03:13 +02001714
Michal Vaskoff006c12016-02-17 11:15:19 +01001715 /* unlink and store the original node */
1716 lys_node_unlink(dev_target);
1717 dev->orig_node = dev_target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001718
Radek Krejci5b917642015-07-02 09:03:13 +02001719 dev->deviate_size = 1;
Pavol Vican85991ec2016-08-16 14:58:12 +02001720 ly_set_free(dflt_check);
Radek Krejci5b917642015-07-02 09:03:13 +02001721 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001722 } else if (!strcmp(value, "add")) {
1723 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1724 } else if (!strcmp(value, "replace")) {
1725 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1726 } else if (!strcmp(value, "delete")) {
1727 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1728 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001729 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001730 goto error;
1731 }
1732 d = &dev->deviate[dev->deviate_size];
Michal Vasko0f7d7ee2016-03-08 09:20:25 +01001733 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734
Michal Vaskoff006c12016-02-17 11:15:19 +01001735 /* store a shallow copy of the original node */
1736 if (!dev->orig_node) {
1737 memset(&tmp_unres, 0, sizeof tmp_unres);
1738 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, 0, &tmp_unres, 1);
1739 /* just to be safe */
1740 if (tmp_unres.count) {
1741 LOGINT;
1742 goto error;
1743 }
1744 }
1745
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 /* process deviation properties */
1747 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001748 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1749 /* garbage */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001750 lyxml_free(ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001751 continue;
1752 }
1753
Radek Krejcieb00f512015-07-01 16:44:58 +02001754 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001755 if (d->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001756 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001757 goto error;
1758 }
1759
1760 /* for we deviate from RFC 6020 and allow config property even it is/is not
1761 * specified in the target explicitly since config property inherits. So we expect
1762 * that config is specified in every node. But for delete, we check that the value
1763 * is the same as here in deviation
1764 */
1765 GETVAL(value, child, "value");
1766 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001767 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001768 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001769 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001771 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001772 goto error;
1773 }
1774
1775 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001776 /* del config is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001777 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "config", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001778 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 } else { /* add and replace are the same in this case */
1780 /* remove current config value of the target ... */
Michal Vasko60f4b452016-02-12 11:02:55 +01001781 dev_target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001782
1783 /* ... and replace it with the value specified in deviation */
Michal Vasko60f4b452016-02-12 11:02:55 +01001784 dev_target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001785 }
1786 } else if (!strcmp(child->name, "default")) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02001787 c_dflt++;
1788
1789 /* check target node type */
1790 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1791 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1792 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1793 goto error;
1794 } else if (c_dflt > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1795 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1796 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1797 goto error;
1798 } else if (c_dflt == 1 && (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE)))) {
1799 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1800 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001801 goto error;
1802 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001803
Radek Krejcid5a5c282016-08-15 15:38:08 +02001804 /* skip lyxml_free() at the end of the loop, this node will be processed later */
1805 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02001806
Radek Krejcieb00f512015-07-01 16:44:58 +02001807 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001808 if (d->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001809 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001810 goto error;
1811 }
1812
1813 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001814 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001815 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1816 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001817 goto error;
1818 }
1819
1820 GETVAL(value, child, "value");
1821 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001822 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001824 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001826 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001827 goto error;
1828 }
1829
1830 if (d->mod == LY_DEVIATE_ADD) {
1831 /* check that there is no current value */
Michal Vasko60f4b452016-02-12 11:02:55 +01001832 if (dev_target->flags & LYS_MAND_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001833 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1834 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001835 goto error;
1836 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001837
Radek Krejci841ec082016-04-05 13:05:17 +02001838 /* check collision with default-stmt */
Radek Krejcie00d2312016-08-12 15:27:49 +02001839 if (d->flags & LYS_MAND_TRUE) {
1840 if (dev_target->nodetype == LYS_CHOICE) {
1841 if (((struct lys_node_choice *)(dev_target))->dflt) {
1842 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1843 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1844 "Adding the \"mandatory\" statement is forbidden on choice with the \"default\" statement.");
1845 goto error;
1846 }
1847 } else if (dev_target->nodetype == LYS_LEAF) {
1848 if (((struct lys_node_leaf *)(dev_target))->dflt) {
1849 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
1850 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1851 "Adding the \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
1852 goto error;
1853 }
1854 }
Radek Krejci841ec082016-04-05 13:05:17 +02001855 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001856
Michal Vasko21be1b32016-03-07 12:31:34 +01001857 dev_target->flags |= d->flags & LYS_MAND_MASK;
1858 } else if (d->mod == LY_DEVIATE_RPL) {
1859 /* check that there was a value before */
1860 if (!(dev_target->flags & LYS_MAND_MASK)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001861 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1862 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001863 goto error;
1864 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001865
Michal Vasko21be1b32016-03-07 12:31:34 +01001866 dev_target->flags &= ~LYS_MAND_MASK;
Michal Vasko60f4b452016-02-12 11:02:55 +01001867 dev_target->flags |= d->flags & LYS_MAND_MASK;
Michal Vasko21be1b32016-03-07 12:31:34 +01001868 } else if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01001869 /* del mandatory is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01001870 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001871 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02001872 }
Radek Krejcie00d2312016-08-12 15:27:49 +02001873
1874 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
1875 for (parent = dev_target->parent;
1876 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1877 parent = parent->parent) {
1878 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1879 /* stop also on presence containers */
1880 break;
1881 }
1882 }
1883 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1884 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1885 if (lyp_check_mandatory_choice(parent)) {
1886 goto error;
1887 }
1888 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001889 } else if (!strcmp(child->name, "min-elements")) {
1890 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001891 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001892 goto error;
1893 }
1894 f_min = 1;
1895
Michal Vasko60f4b452016-02-12 11:02:55 +01001896 if (deviate_minmax(dev_target, child, d, 0)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001897 goto error;
1898 }
1899 } else if (!strcmp(child->name, "max-elements")) {
Radek Krejci0d7b2472016-02-12 11:11:03 +01001900 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001901 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001902 goto error;
1903 }
Radek Krejci0d7b2472016-02-12 11:11:03 +01001904 f_max = 1;
Radek Krejcieb00f512015-07-01 16:44:58 +02001905
Michal Vasko60f4b452016-02-12 11:02:55 +01001906 if (deviate_minmax(dev_target, child, d, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001907 goto error;
1908 }
1909 } else if (!strcmp(child->name, "must")) {
1910 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001911 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 continue;
1913 } else if (!strcmp(child->name, "type")) {
1914 if (d->type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001915 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001916 goto error;
1917 }
1918
Michal Vaskof7e57d52016-03-07 11:31:09 +01001919 /* add, del type is forbidden */
1920 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001921 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate add");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001922 goto error;
1923 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001924 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "deviate delete");
Michal Vaskof7e57d52016-03-07 11:31:09 +01001925 goto error;
1926 }
1927
Radek Krejcieb00f512015-07-01 16:44:58 +02001928 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001929 if (dev_target->nodetype == LYS_LEAF) {
1930 t = &((struct lys_node_leaf *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001931 if (((struct lys_node_leaf *)dev_target)->dflt) {
1932 ly_set_add(dflt_check, dev_target, 0);
1933 }
Michal Vasko60f4b452016-02-12 11:02:55 +01001934 } else if (dev_target->nodetype == LYS_LEAFLIST) {
1935 t = &((struct lys_node_leaflist *)dev_target)->type;
Pavol Vican2e322822016-09-07 15:48:13 +02001936 if (((struct lys_node_leaflist *)dev_target)->dflt) {
1937 ly_set_add(dflt_check, dev_target, 0);
1938 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001939 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001940 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1941 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001942 goto error;
1943 }
1944
Radek Krejcieb00f512015-07-01 16:44:58 +02001945 /* replace */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001946 lys_type_free(ctx, t);
Michal Vasko88c29542015-11-27 14:57:53 +01001947 /* HACK for unres */
1948 t->der = (struct lys_tpdf *)child;
Michal Vasko3767fb22016-07-21 12:10:57 +02001949 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev_target) == -1) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001950 goto error;
1951 }
1952 d->type = t;
1953 } else if (!strcmp(child->name, "unique")) {
1954 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001955 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 continue;
1957 } else if (!strcmp(child->name, "units")) {
1958 if (d->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001959 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001960 goto error;
1961 }
1962
1963 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01001964 if (dev_target->nodetype == LYS_LEAFLIST) {
1965 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1966 } else if (dev_target->nodetype == LYS_LEAF) {
1967 stritem = &((struct lys_node_leaf *)dev_target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001968 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01001969 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1970 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001971 goto error;
1972 }
1973
1974 /* get units value */
1975 GETVAL(value, child, "name");
Michal Vaskodc48e7f2016-02-11 12:35:27 +01001976 d->units = lydict_insert(ctx, value, 0);
Radek Krejcieb00f512015-07-01 16:44:58 +02001977
1978 /* apply to target */
1979 if (d->mod == LY_DEVIATE_ADD) {
1980 /* check that there is no current value */
1981 if (*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001982 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001984 goto error;
1985 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001986
Michal Vasko21be1b32016-03-07 12:31:34 +01001987 *stritem = lydict_insert(ctx, value, 0);
1988 } else if (d->mod == LY_DEVIATE_RPL) {
1989 /* check that there was a value before */
1990 if (!*stritem) {
Radek Krejci48464ed2016-03-17 15:44:09 +01001991 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
1992 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Michal Vasko21be1b32016-03-07 12:31:34 +01001993 goto error;
1994 }
1995
1996 lydict_remove(ctx, *stritem);
1997 *stritem = lydict_insert(ctx, value, 0);
1998 } else if (d->mod == LY_DEVIATE_DEL) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001999 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02002000 if (!ly_strequal(*stritem, d->units, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002001 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
2002 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002003 goto error;
2004 }
2005 /* remove current units value of the target */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002006 lydict_remove(ctx, *stritem);
Radek Krejcieb00f512015-07-01 16:44:58 +02002007 }
2008 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002009 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 goto error;
2011 }
2012
Michal Vasko88c29542015-11-27 14:57:53 +01002013 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 }
2015
2016 if (c_must) {
2017 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002018 switch (dev_target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02002019 case LYS_LEAF:
Michal Vasko60f4b452016-02-12 11:02:55 +01002020 trg_must = &((struct lys_node_leaf *)dev_target)->must;
2021 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002022 break;
Radek Krejci76512572015-08-04 09:47:08 +02002023 case LYS_CONTAINER:
Michal Vasko60f4b452016-02-12 11:02:55 +01002024 trg_must = &((struct lys_node_container *)dev_target)->must;
2025 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002026 break;
Radek Krejci76512572015-08-04 09:47:08 +02002027 case LYS_LEAFLIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002028 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
2029 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002030 break;
Radek Krejci76512572015-08-04 09:47:08 +02002031 case LYS_LIST:
Michal Vasko60f4b452016-02-12 11:02:55 +01002032 trg_must = &((struct lys_node_list *)dev_target)->must;
2033 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002034 break;
Radek Krejci76512572015-08-04 09:47:08 +02002035 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002036 case LYS_ANYDATA:
2037 trg_must = &((struct lys_node_anydata *)dev_target)->must;
2038 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02002039 break;
2040 default:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002041 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
2042 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002043 goto error;
2044 }
2045
Michal Vasko508a50d2016-09-07 14:50:33 +02002046 dev_target->flags &= ~LYS_XPATH_DEP;
2047
Radek Krejcieb00f512015-07-01 16:44:58 +02002048 if (d->mod == LY_DEVIATE_RPL) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002049 /* replace must is forbidden */
Radek Krejci48464ed2016-03-17 15:44:09 +01002050 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "must", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002051 goto error;
Radek Krejcieb00f512015-07-01 16:44:58 +02002052 } else if (d->mod == LY_DEVIATE_ADD) {
2053 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002054 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002055 if (!d->must) {
2056 LOGMEM;
2057 goto error;
2058 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002059 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02002060 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002061 d->must_size = c_must;
2062 } else { /* LY_DEVIATE_DEL */
2063 d->must = calloc(c_must, sizeof *d->must);
2064 }
Michal Vasko253035f2015-12-17 16:58:13 +01002065 if (!d->must) {
2066 LOGMEM;
2067 goto error;
2068 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002069 }
2070 if (c_uniq) {
Michal Vaskof7e57d52016-03-07 11:31:09 +01002071 /* replace unique is forbidden */
2072 if (d->mod == LY_DEVIATE_RPL) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002073 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "unique", "deviate replace");
Michal Vaskof7e57d52016-03-07 11:31:09 +01002074 goto error;
2075 }
2076
Radek Krejcieb00f512015-07-01 16:44:58 +02002077 /* check target node type */
Michal Vasko60f4b452016-02-12 11:02:55 +01002078 if (dev_target->nodetype != LYS_LIST) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002079 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
2080 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002081 goto error;
2082 }
2083
Michal Vasko60f4b452016-02-12 11:02:55 +01002084 list = (struct lys_node_list *)dev_target;
Michal Vaskof7e57d52016-03-07 11:31:09 +01002085 if (d->mod == LY_DEVIATE_ADD) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002086 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01002087 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02002088 list->unique = d->unique;
2089 d->unique = &list->unique[list->unique_size];
2090 d->unique_size = c_uniq;
2091 } else { /* LY_DEVIATE_DEL */
2092 d->unique = calloc(c_uniq, sizeof *d->unique);
2093 }
Michal Vasko253035f2015-12-17 16:58:13 +01002094 if (!d->unique) {
2095 LOGMEM;
2096 goto error;
2097 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002098 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002099 if (c_dflt) {
2100 if (d->mod == LY_DEVIATE_ADD) {
2101 /* check that there is no current value */
2102 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
2103 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
2104 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2105 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
2106 goto error;
2107 }
2108
2109 /* check collision with mandatory/min-elements */
2110 if ((dev_target->flags & LYS_MAND_TRUE) ||
2111 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
2112 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, child->name, child->parent->name);
2113 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2114 "Adding the \"default\" statement is forbidden on %s statement.",
2115 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2116 goto error;
2117 }
2118 } else if (d->mod == LY_DEVIATE_RPL) {
2119 /* check that there was a value before */
2120 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
2121 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
2122 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
2123 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2124 goto error;
2125 }
2126 }
2127
2128 if (dev_target->nodetype == LYS_LEAFLIST) {
2129 /* reallocate default list in the target */
2130 llist = (struct lys_node_leaflist *)dev_target;
2131 if (d->mod == LY_DEVIATE_ADD) {
2132 /* reallocate (enlarge) the unique array of the target */
2133 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *d->dflt);
2134 } else if (d->mod == LY_DEVIATE_RPL) {
2135 /* reallocate (replace) the unique array of the target */
2136 for (i = 0; i < llist->dflt_size; i++) {
2137 lydict_remove(llist->module->ctx, llist->dflt[i]);
2138 }
2139 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *d->dflt);
2140 llist->dflt_size = 0;
2141 }
2142 }
2143 d->dflt = calloc(c_dflt, sizeof *d->dflt);
2144 if (!d->dflt) {
2145 LOGMEM;
2146 goto error;
2147 }
2148 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002149
2150 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02002151 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002152 if (!strcmp(child->name, "must")) {
2153 if (d->mod == LY_DEVIATE_DEL) {
2154 if (fill_yin_must(module, child, &d->must[d->must_size])) {
2155 goto error;
2156 }
2157
2158 /* find must to delete, we are ok with just matching conditions */
2159 for (i = 0; i < *trg_must_size; i++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002160 if (ly_strequal(d->must[d->must_size].expr, (*trg_must)[i].expr, 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002161 /* we have a match, free the must structure ... */
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002162 lys_restr_free(ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02002163 /* ... and maintain the array */
2164 (*trg_must_size)--;
2165 if (i != *trg_must_size) {
2166 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
2167 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
2168 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
2169 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
2170 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
2171 }
2172 if (!(*trg_must_size)) {
2173 free(*trg_must);
2174 *trg_must = NULL;
2175 } else {
2176 (*trg_must)[*trg_must_size].expr = NULL;
2177 (*trg_must)[*trg_must_size].dsc = NULL;
2178 (*trg_must)[*trg_must_size].ref = NULL;
2179 (*trg_must)[*trg_must_size].eapptag = NULL;
2180 (*trg_must)[*trg_must_size].emsg = NULL;
2181 }
2182
2183 i = -1; /* set match flag */
2184 break;
2185 }
2186 }
2187 d->must_size++;
2188 if (i != -1) {
2189 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002190 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL,
Radek Krejciadb57612016-02-16 13:34:34 +01002191 d->must[d->must_size - 1].expr, child->name);
Radek Krejci48464ed2016-03-17 15:44:09 +01002192 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002193 goto error;
2194 }
2195 } else { /* replace or add */
Michal Vaskof92a7282016-02-11 12:35:57 +01002196 memset(&((*trg_must)[*trg_must_size]), 0, sizeof **trg_must);
2197 if (fill_yin_must(module, child, &((*trg_must)[*trg_must_size]))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002198 goto error;
2199 }
2200 (*trg_must_size)++;
2201 }
Michal Vasko508a50d2016-09-07 14:50:33 +02002202
2203 /* check XPath dependencies again */
2204 if (*trg_must_size && unres_schema_add_node(dev_target->module, unres, dev_target, UNRES_XPATH, NULL)) {
2205 goto error;
2206 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002207 } else if (!strcmp(child->name, "unique")) {
2208 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002209 memset(&d->unique[d->unique_size], 0, sizeof *d->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002210 if (fill_yin_unique(module, dev_target, child, &d->unique[d->unique_size], NULL)) {
Radek Krejci581ce772015-11-10 17:22:40 +01002211 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002212 goto error;
2213 }
2214
2215 /* find unique structures to delete */
2216 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002217 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002218 continue;
2219 }
2220
Radek Krejci581ce772015-11-10 17:22:40 +01002221 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
Radek Krejci749190d2016-02-18 16:26:25 +01002222 if (!ly_strequal(list->unique[i].expr[j], d->unique[d->unique_size].expr[j], 1)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002223 break;
2224 }
2225 }
2226
Radek Krejci581ce772015-11-10 17:22:40 +01002227 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002228 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01002229 for (j = 0; j < list->unique[i].expr_size; j++) {
Michal Vaskodc48e7f2016-02-11 12:35:27 +01002230 lydict_remove(ctx, list->unique[i].expr[j]);
Radek Krejci581ce772015-11-10 17:22:40 +01002231 }
2232 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002233 /* ... and maintain the array */
2234 list->unique_size--;
2235 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01002236 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2237 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02002238 }
2239
2240 if (!list->unique_size) {
2241 free(list->unique);
2242 list->unique = NULL;
2243 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01002244 list->unique[list->unique_size].expr_size = 0;
2245 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02002246 }
2247
2248 i = -1; /* set match flag */
2249 break;
2250 }
2251 }
2252
2253 d->unique_size++;
2254 if (i != -1) {
2255 /* no match found */
Radek Krejci48464ed2016-03-17 15:44:09 +01002256 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, lyxml_get_attr(child, "tag", NULL), child->name);
2257 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002258 goto error;
2259 }
2260 } else { /* replace or add */
Michal Vaskoa0a10ab2016-03-07 14:41:23 +01002261 memset(&list->unique[list->unique_size], 0, sizeof *list->unique);
Michal Vasko60f4b452016-02-12 11:02:55 +01002262 i = fill_yin_unique(module, dev_target, child, &list->unique[list->unique_size], NULL);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002263 list->unique_size++;
2264 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002265 goto error;
2266 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002267 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002268 } else if (!strcmp(child->name, "default")) {
2269 GETVAL(value, child, "value");
2270 u = strlen(value);
2271 d->dflt[d->dflt_size++] = lydict_insert(module->ctx, value, u);
2272
2273 if (dev_target->nodetype == LYS_CHOICE) {
2274 choice = (struct lys_node_choice *)dev_target;
2275 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2276 if (rc || !node) {
2277 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2278 goto error;
2279 }
2280 if (d->mod == LY_DEVIATE_DEL) {
2281 if (!choice->dflt || (choice->dflt != node)) {
2282 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2283 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2284 goto error;
2285 }
2286 } else { /* add or replace */
2287 choice->dflt = node;
2288 if (!choice->dflt) {
2289 /* default branch not found */
2290 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2291 goto error;
2292 }
2293 }
2294 } else if (dev_target->nodetype == LYS_LEAF) {
2295 leaf = (struct lys_node_leaf *)dev_target;
2296 if (d->mod == LY_DEVIATE_DEL) {
2297 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2298 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2299 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2300 goto error;
2301 }
2302 /* remove value */
2303 lydict_remove(ctx, leaf->dflt);
2304 leaf->dflt = NULL;
2305 } else { /* add (already checked) and replace */
2306 /* remove value */
2307 lydict_remove(ctx, leaf->dflt);
2308
2309 /* set new value */
2310 leaf->dflt = lydict_insert(ctx, value, u);
2311
2312 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2313 ly_set_add(dflt_check, dev_target, 0);
2314 }
2315 } else { /* LYS_LEAFLIST */
2316 llist = (struct lys_node_leaflist *)dev_target;
2317 if (d->mod == LY_DEVIATE_DEL) {
2318 /* find and remove the value in target list */
2319 for (i = 0; i < llist->dflt_size; i++) {
2320 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2321 /* match, remove the value */
2322 lydict_remove(llist->module->ctx, llist->dflt[i]);
2323 llist->dflt[i] = NULL;
2324 break;
2325 }
2326 }
2327 if (i == llist->dflt_size) {
2328 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2329 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2330 goto error;
2331 }
2332 } else {
2333 /* add or replace, anyway we place items into the deviate's list
2334 which propagates to the target */
2335 /* we just want to check that the value isn't already in the list */
2336 for (i = 0; i < llist->dflt_size; i++) {
2337 if (ly_strequal(llist->dflt[i], value, 1)) {
2338 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2339 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2340 goto error;
2341 }
2342 }
2343 /* store it in target node */
2344 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, u);
2345
2346 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2347 ly_set_add(dflt_check, dev_target, 0);
2348 }
2349 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002350 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002351 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002352
2353 if (c_dflt && dev_target->nodetype == LYS_LEAFLIST && d->mod == LY_DEVIATE_DEL) {
2354 /* consolidate the final list in the target after removing items from it */
2355 llist = (struct lys_node_leaflist *)dev_target;
2356 for (i = j = 0; j < llist->dflt_size; j++) {
2357 llist->dflt[i] = llist->dflt[j];
2358 if (llist->dflt[i]) {
2359 i++;
2360 }
2361 }
2362 llist->dflt_size = i + 1;
2363 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002364 }
2365
Michal Vasko43a1feb2016-03-07 12:03:02 +01002366 /* now check whether default value, if any, matches the type */
Pavol Vican85991ec2016-08-16 14:58:12 +02002367 for (u = 0; u < dflt_check->number; ++u) {
Radek Krejcid5a5c282016-08-15 15:38:08 +02002368 value = NULL;
2369 rc = EXIT_SUCCESS;
2370 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2371 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2372 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2373 } else { /* LYS_LEAFLIST */
2374 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2375 for (j = 0; j < llist->dflt_size; j++) {
2376 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[j]);
2377 if (rc == -1) {
2378 break;
2379 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002380 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02002381
2382 }
2383 if (rc == -1) {
2384 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2385 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2386 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2387 dev->target_name);
2388 goto error;
Michal Vasko43a1feb2016-03-07 12:03:02 +01002389 }
2390 }
Michal Vasko43a1feb2016-03-07 12:03:02 +01002391
Radek Krejcid5a5c282016-08-15 15:38:08 +02002392 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002393 return EXIT_SUCCESS;
2394
2395error:
Radek Krejcid5a5c282016-08-15 15:38:08 +02002396 ly_set_free(dflt_check);
Radek Krejcieb00f512015-07-01 16:44:58 +02002397 return EXIT_FAILURE;
2398}
2399
Michal Vasko0d343d12015-08-24 14:57:36 +02002400/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002401static int
Radek Krejcib8048692015-08-05 13:36:34 +02002402fill_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 +02002403 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002404{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002406 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002407 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002408 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002409
Michal Vasko591e0b22015-08-13 13:53:43 +02002410 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002411 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002412 aug->target_name = transform_schema2json(module, value);
Michal Vasko488c19e2015-10-20 15:21:00 +02002413 if (!aug->target_name) {
2414 goto error;
2415 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002417
Michal Vasko1d87a922015-08-21 12:57:16 +02002418 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002419 goto error;
2420 }
2421
2422 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002423 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2424 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002425 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02002426 continue;
2427 }
2428
Radek Krejci3cf9e222015-06-18 11:37:50 +02002429 if (!strcmp(child->name, "if-feature")) {
2430 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002431 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002432 } else if (!strcmp(child->name, "when")) {
2433 if (aug->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002434 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002435 goto error;
2436 }
2437
2438 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002439 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002440 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002441 goto error;
2442 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002443 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002444 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002445
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002446 /* check allowed data sub-statements */
2447 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002448 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002449 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002450 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002451 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002452 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002453 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002454 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002455 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02002456 node = read_yin_uses(module, (struct lys_node *)aug, child, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002457 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002458 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002459 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002460 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002461 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002462 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYXML, 0, unres);
2463 } else if (!strcmp(child->name, "anydata")) {
2464 node = read_yin_anydata(module, (struct lys_node *)aug, child, LYS_ANYDATA, 0, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02002465 } else if (!strcmp(child->name, "action")) {
2466 node = read_yin_rpc_action(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002467 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002468 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002469 goto error;
2470 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002471
Radek Krejci1d82ef62015-08-07 14:44:40 +02002472 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002473 goto error;
2474 }
2475
Radek Krejci1d82ef62015-08-07 14:44:40 +02002476 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002477 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002478 }
2479
2480 if (c) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002481 aug->iffeature = calloc(c, sizeof *aug->iffeature);
2482 if (!aug->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01002483 LOGMEM;
2484 goto error;
2485 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002486 }
2487
2488 LY_TREE_FOR_SAFE(yin->child, next, child) {
2489 if (!strcmp(child->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02002490 ret = fill_yin_iffeature((struct lys_node *)aug, child, &aug->iffeature[aug->iffeature_size], unres);
2491 aug->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01002492 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002493 goto error;
2494 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002495 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002496 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002497 }
2498
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002499 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002500 * connected to the tree and adjusted (if possible right now).
2501 * However, if this is augment in a uses, it gets resolved
2502 * when the uses does and cannot be resolved now for sure
2503 * (the grouping was not yet copied into uses).
2504 */
2505 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002506 if (unres_schema_add_node(module, unres, aug, UNRES_AUGMENT, NULL) == -1) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002507 goto error;
2508 }
Michal Vasko49291b32015-08-06 09:49:41 +02002509 }
Radek Krejci106efc02015-06-10 14:36:27 +02002510
Michal Vasko508a50d2016-09-07 14:50:33 +02002511 /* check XPath dependencies */
2512 if (aug->when && (unres_schema_add_node(module, unres, (struct lys_node *)aug, UNRES_XPATH, NULL) == -1)) {
2513 goto error;
2514 }
2515
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002517
2518error:
2519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002521}
2522
Michal Vasko0d343d12015-08-24 14:57:36 +02002523/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524static int
Radek Krejci363bd4a2016-07-29 14:30:20 +02002525fill_yin_refine(struct lys_node *uses, struct lyxml_elem *yin, struct lys_refine *rfn, struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002526{
Radek Krejci363bd4a2016-07-29 14:30:20 +02002527 struct lys_module *module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002528 struct lyxml_elem *sub, *next;
2529 const char *value;
2530 char *endptr;
2531 int f_mand = 0, f_min = 0, f_max = 0;
Radek Krejci200bf712016-08-16 17:11:04 +02002532 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002533 int r;
2534 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002535
Radek Krejci363bd4a2016-07-29 14:30:20 +02002536 assert(uses);
2537 module = uses->module; /* shorthand */
2538
Radek Krejci76512572015-08-04 09:47:08 +02002539 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 goto error;
2541 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002542
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002543 GETVAL(value, yin, "target-node");
Radek Krejci48464ed2016-03-17 15:44:09 +01002544 rfn->target_name = transform_schema2json(module, value);
Michal Vaskoa8b25952015-10-20 15:30:25 +02002545 if (!rfn->target_name) {
2546 goto error;
2547 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002550 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2551 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002552 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002553 continue;
2554 }
2555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 /* limited applicability */
2557 if (!strcmp(sub->name, "default")) {
Radek Krejci200bf712016-08-16 17:11:04 +02002558 /* leaf, leaf-list or choice */
Radek Krejci3bde87f2015-06-05 16:51:58 +02002559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 /* check possibility of statements combination */
2561 if (rfn->target_type) {
Radek Krejci200bf712016-08-16 17:11:04 +02002562 if (c_dflt) {
2563 /* multiple defaults are allowed only in leaf-list */
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002564 if (module->version < 2) {
2565 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
2566 goto error;
2567 }
Radek Krejci200bf712016-08-16 17:11:04 +02002568 rfn->target_type &= LYS_LEAFLIST;
2569 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002570 if (module->version < 2) {
2571 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
2572 } else {
2573 /* YANG 1.1 */
2574 rfn->target_type &= (LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE);
2575 }
Radek Krejci200bf712016-08-16 17:11:04 +02002576 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002578 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2579 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 goto error;
2581 }
2582 } else {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002583 if (module->version < 2) {
2584 rfn->target_type = LYS_LEAF | LYS_CHOICE;
2585 } else {
2586 /* YANG 1.1 */
2587 rfn->target_type = LYS_LEAFLIST | LYS_LEAF | LYS_CHOICE;
2588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002589 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002590
Radek Krejci200bf712016-08-16 17:11:04 +02002591 c_dflt++;
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002592 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002593 } else if (!strcmp(sub->name, "mandatory")) {
2594 /* leaf, choice or anyxml */
2595 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002596 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 goto error;
2598 }
2599 /* just checking the flags in leaf is not sufficient, we would allow
2600 * multiple mandatory statements with the "false" value
2601 */
2602 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 /* check possibility of statements combination */
2605 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002606 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002608 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2609 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002610 goto error;
2611 }
2612 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002613 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002614 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002616 GETVAL(value, sub, "value");
2617 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002618 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002619 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002620 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002621 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002622 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002623 goto error;
2624 }
2625 } else if (!strcmp(sub->name, "min-elements")) {
2626 /* list or leaf-list */
2627 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002628 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002629 goto error;
2630 }
2631 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002633 /* check possibility of statements combination */
2634 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002635 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002636 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002637 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2638 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002639 goto error;
2640 }
2641 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002642 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002644
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 GETVAL(value, sub, "value");
2646 while (isspace(value[0])) {
2647 value++;
2648 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002650 /* convert it to uint32_t */
2651 errno = 0;
2652 endptr = NULL;
2653 val = strtoul(value, &endptr, 10);
2654 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002655 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002656 goto error;
2657 }
2658 rfn->mod.list.min = (uint32_t) val;
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002659 rfn->flags |= LYS_RFN_MINSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 } else if (!strcmp(sub->name, "max-elements")) {
2661 /* list or leaf-list */
2662 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002663 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002664 goto error;
2665 }
2666 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002668 /* check possibility of statements combination */
2669 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002670 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002671 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002672 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2673 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 goto error;
2675 }
2676 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002677 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002678 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 GETVAL(value, sub, "value");
2681 while (isspace(value[0])) {
2682 value++;
2683 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002684
Radek Krejci0d7b2472016-02-12 11:11:03 +01002685 if (!strcmp(value, "unbounded")) {
2686 rfn->mod.list.max = 0;
2687 } else {
2688 /* convert it to uint32_t */
2689 errno = 0;
2690 endptr = NULL;
2691 val = strtoul(value, &endptr, 10);
2692 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002693 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01002694 goto error;
2695 }
2696 rfn->mod.list.max = (uint32_t) val;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002697 }
Radek Krejci0f04a6c2016-04-14 16:16:36 +02002698 rfn->flags |= LYS_RFN_MAXSET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 } else if (!strcmp(sub->name, "presence")) {
2700 /* container */
2701 if (rfn->mod.presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002702 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002703 goto error;
2704 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002706 /* check possibility of statements combination */
2707 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002708 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002709 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002710 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2711 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 goto error;
2713 }
2714 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002715 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002716 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002718 GETVAL(value, sub, "value");
2719 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2720 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002721 /* leafm leaf-list, list, container or anyxml */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 /* check possibility of statements combination */
2723 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002724 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 if (!rfn->target_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002726 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2727 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 goto error;
2729 }
2730 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002731 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002735 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002736
Radek Krejci363bd4a2016-07-29 14:30:20 +02002737 } else if ((module->version >= 2) && !strcmp(sub->name, "if-feature")) {
2738 /* leaf, leaf-list, list, container or anyxml */
2739 /* check possibility of statements combination */
2740 if (rfn->target_type) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002741 rfn->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002742 if (!rfn->target_type) {
2743 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, sub->name, yin->name);
2744 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2745 goto error;
2746 }
2747 } else {
Radek Krejcibf2abff2016-08-23 15:51:52 +02002748 rfn->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
Radek Krejci363bd4a2016-07-29 14:30:20 +02002749 }
2750
2751 c_ftrs++;
2752 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002754 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002755 goto error;
2756 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002757
Michal Vasko345da0a2015-12-02 10:35:55 +01002758 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002759 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 /* process nodes with cardinality of 0..n */
2762 if (c_must) {
2763 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002764 if (!rfn->must) {
2765 LOGMEM;
2766 goto error;
2767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 }
Radek Krejci363bd4a2016-07-29 14:30:20 +02002769 if (c_ftrs) {
Radek Krejci947e0342016-08-15 09:42:56 +02002770 rfn->iffeature = calloc(c_ftrs, sizeof *rfn->iffeature);
Radek Krejci363bd4a2016-07-29 14:30:20 +02002771 if (!rfn->iffeature) {
2772 LOGMEM;
Radek Krejci73adb602015-07-02 18:07:40 +02002773 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 }
Radek Krejci200bf712016-08-16 17:11:04 +02002776 if (c_dflt) {
Pavol Vican35aa9ea2016-08-17 10:27:43 +02002777 rfn->dflt = calloc(c_dflt, sizeof *rfn->dflt);
Radek Krejci200bf712016-08-16 17:11:04 +02002778 if (!rfn->dflt) {
2779 LOGMEM;
2780 goto error;
2781 }
2782 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002783
Radek Krejci363bd4a2016-07-29 14:30:20 +02002784 LY_TREE_FOR(yin->child, sub) {
2785 if (!strcmp(sub->name, "if-feature")) {
2786 r = fill_yin_iffeature(uses, sub, &rfn->iffeature[rfn->iffeature_size], unres);
2787 rfn->iffeature_size++;
2788 if (r) {
2789 goto error;
2790 }
Radek Krejci200bf712016-08-16 17:11:04 +02002791 } else if (!strcmp(sub->name, "must")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02002792 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2793 rfn->must_size++;
2794 if (r) {
2795 goto error;
2796 }
Radek Krejci200bf712016-08-16 17:11:04 +02002797 } else { /* default */
2798 GETVAL(value, sub, "value");
2799
2800 /* check for duplicity */
2801 for (r = 0; r < rfn->dflt_size; r++) {
2802 if (ly_strequal(rfn->dflt[r], value, 1)) {
2803 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2804 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2805 goto error;
2806 }
2807 }
2808 rfn->dflt[rfn->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci363bd4a2016-07-29 14:30:20 +02002809 }
2810 }
2811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002813
2814error:
2815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002817}
2818
Michal Vasko0d343d12015-08-24 14:57:36 +02002819/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820static int
Radek Krejcib8048692015-08-05 13:36:34 +02002821fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002822{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 struct lyxml_elem *child;
2824 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002827 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2828 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002829 continue;
2830 }
2831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 if (!strcmp(child->name, "prefix")) {
2833 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01002834 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002835 goto error;
2836 }
2837 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2838 } else if (!strcmp(child->name, "revision-date")) {
2839 if (imp->rev[0]) {
Radek Krejcid52195b2016-06-22 11:18:49 +02002840 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2841 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 }
2843 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002844 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002845 goto error;
2846 }
2847 memcpy(imp->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002848 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002849 if (imp->dsc) {
2850 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2851 goto error;
2852 }
2853 imp->dsc = read_yin_subnode(module->ctx, child, "text");
2854 if (!imp->dsc) {
2855 goto error;
2856 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002857 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002858 if (imp->ref) {
2859 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2860 goto error;
2861 }
2862 imp->ref = read_yin_subnode(module->ctx, child, "text");
2863 if (!imp->ref) {
2864 goto error;
2865 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002868 goto error;
2869 }
2870 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002872 /* check mandatory information */
2873 if (!imp->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002874 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002875 goto error;
2876 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002879
Pavol Vicane994fda2016-03-22 10:47:58 +01002880 return lyp_check_import(module, value, imp);
Radek Krejcice7fb782015-05-29 16:52:34 +02002881
2882error:
2883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002885}
2886
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002887/* logs directly
2888 * returns:
2889 * 0 - inc successfully filled
2890 * -1 - error, inc is cleaned
2891 * 1 - duplication, ignore the inc structure, inc is cleaned
2892 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893static int
Michal Vasko5ff78822016-02-12 09:33:31 +01002894fill_yin_include(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
2895 struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002896{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 struct lyxml_elem *child;
2898 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002900 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002901 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2902 /* garbage */
2903 continue;
2904 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002905 if (!strcmp(child->name, "revision-date")) {
2906 if (inc->rev[0]) {
Radek Krejci48464ed2016-03-17 15:44:09 +01002907 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002908 goto error;
2909 }
2910 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01002911 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002912 goto error;
2913 }
2914 memcpy(inc->rev, value, LY_REV_SIZE - 1);
Radek Krejci1a31efe2016-07-29 11:04:16 +02002915 } else if ((module->version >= 2) && !strcmp(child->name, "description")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002916 if (inc->dsc) {
2917 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2918 goto error;
2919 }
2920 inc->dsc = read_yin_subnode(module->ctx, child, "text");
2921 if (!inc->dsc) {
2922 goto error;
2923 }
Radek Krejci1a31efe2016-07-29 11:04:16 +02002924 } else if ((module->version >= 2) && !strcmp(child->name, "reference")) {
Michal Vasko8bfe3812016-07-27 13:37:52 +02002925 if (inc->ref) {
2926 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
2927 goto error;
2928 }
2929 inc->ref = read_yin_subnode(module->ctx, child, "text");
2930 if (!inc->ref) {
2931 goto error;
2932 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002934 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 goto error;
2936 }
2937 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002939 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002940
Pavol Vican0adf01d2016-03-22 12:29:33 +01002941 return lyp_check_include(module, submodule, value, inc, unres);
Radek Krejcice7fb782015-05-29 16:52:34 +02002942
2943error:
2944
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002945 return -1;
Radek Krejciefaeba32015-05-27 14:30:57 +02002946}
2947
Michal Vasko0d343d12015-08-24 14:57:36 +02002948/* logs directly
2949 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002950 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002951 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002952 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002953 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954static int
Radek Krejcib8048692015-08-05 13:36:34 +02002955read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002956 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002957{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 const char *value;
2959 struct lyxml_elem *sub, *next;
2960 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002961
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002962 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002963 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 if (opt & OPT_IDENT) {
2967 GETVAL(value, xmlnode, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01002968 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 goto error;
2970 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002971 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002972 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002973
Radek Krejci6764bb32015-07-03 15:16:04 +02002974 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002975 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002976 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002977 }
2978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 /* process local parameters */
2980 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002981 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002982 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002983 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002984 continue;
2985 }
2986 if (strcmp(sub->ns->value, LY_NSYIN)) {
2987 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002988 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002989 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002990 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002991 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002992 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002993 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01002994 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002995 goto error;
2996 }
2997 }
2998
2999 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003000 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003001 continue;
3002 }
3003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003004 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003005 if (node->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003006 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 goto error;
3008 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003009 node->dsc = read_yin_subnode(ctx, sub, "text");
3010 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02003011 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003012 }
3013 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003014 if (node->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003015 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 goto error;
3017 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003018 node->ref = read_yin_subnode(ctx, sub, "text");
3019 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02003020 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 }
3022 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003023 if (node->flags & LYS_STATUS_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003024 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 goto error;
3026 }
3027 GETVAL(value, sub, "value");
3028 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003029 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003030 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003031 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003033 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003035 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003036 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 }
3038 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003039 if (node->flags & LYS_CONFIG_MASK) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003040 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 goto error;
3042 }
3043 GETVAL(value, sub, "value");
3044 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003045 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003047 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003048 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003049 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02003050 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 }
Radek Krejci32c7bd62016-04-14 17:47:04 +02003052 node->flags |= LYS_CONFIG_SET;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01003054 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 continue;
3056 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003057 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003059
Radek Krejci1d82ef62015-08-07 14:44:40 +02003060 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 /* get config flag from parent */
Radek Krejci32c7bd62016-04-14 17:47:04 +02003062 if (parent && (parent->flags & LYS_CONFIG_R)) {
3063 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 } else {
3065 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02003066 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 }
3068 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02003071
3072error:
3073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003074 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003075}
3076
Michal Vasko0d343d12015-08-24 14:57:36 +02003077/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003078static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02003079read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003080{
Radek Krejci76512572015-08-04 09:47:08 +02003081 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02003082 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003083 const char *value;
3084
3085 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01003086 if (!retval) {
3087 LOGMEM;
3088 return NULL;
3089 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003090
3091 GETVAL(value, yin, "condition");
Radek Krejci48464ed2016-03-17 15:44:09 +01003092 retval->cond = transform_schema2json(module, value);
Michal Vaskof9893382015-10-09 14:03:04 +02003093 if (!retval->cond) {
3094 goto error;
3095 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003096
Radek Krejci73adb602015-07-02 18:07:40 +02003097 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003098 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
3099 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02003100 continue;
3101 }
3102
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003103 if (!strcmp(child->name, "description")) {
3104 if (retval->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003105 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003106 goto error;
3107 }
3108 retval->dsc = read_yin_subnode(module->ctx, child, "text");
3109 if (!retval->dsc) {
3110 goto error;
3111 }
3112 } else if (!strcmp(child->name, "reference")) {
3113 if (retval->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003114 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003115 goto error;
3116 }
3117 retval->ref = read_yin_subnode(module->ctx, child, "text");
3118 if (!retval->ref) {
3119 goto error;
3120 }
3121 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003122 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003123 goto error;
3124 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003125 }
3126
3127 return retval;
3128
3129error:
3130
Michal Vasko0308dd62015-10-07 09:14:40 +02003131 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003132 return NULL;
3133}
3134
Michal Vasko0d343d12015-08-24 14:57:36 +02003135/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003136static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003137read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3138 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02003139{
Michal Vasko29fc0182015-08-24 15:02:39 +02003140 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003141 struct lys_node_case *cs;
3142 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02003143 int c_ftrs = 0, ret;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003144
Radek Krejcie867c852015-08-27 09:52:34 +02003145 /* init */
3146 memset(&root, 0, sizeof root);
3147
Radek Krejci1d82ef62015-08-07 14:44:40 +02003148 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01003149 if (!cs) {
3150 LOGMEM;
3151 return NULL;
3152 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003153 cs->nodetype = LYS_CASE;
3154 cs->prev = (struct lys_node *)cs;
3155 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003156
Radek Krejci6a113852015-07-03 16:04:20 +02003157 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 goto error;
3159 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003160
Radek Krejcia9544502015-08-14 08:24:29 +02003161 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3162
Michal Vasko3a0043f2015-08-12 12:11:30 +02003163 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003164 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003165 goto error;
3166 }
3167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 /* process choice's specific children */
3169 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003170 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3171 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003172 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003173 continue;
3174 }
3175
Michal Vasko29fc0182015-08-24 15:02:39 +02003176 if (!strcmp(sub->name, "container") ||
3177 !strcmp(sub->name, "leaf-list") ||
3178 !strcmp(sub->name, "leaf") ||
3179 !strcmp(sub->name, "list") ||
3180 !strcmp(sub->name, "uses") ||
3181 !strcmp(sub->name, "choice") ||
3182 !strcmp(sub->name, "anyxml")) {
3183
Michal Vaskof3930de2015-10-22 12:03:59 +02003184 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02003185 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003186 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02003187 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01003188 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02003189 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003190 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003191 if (cs->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003192 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003193 goto error;
3194 }
3195
Radek Krejci1d82ef62015-08-07 14:44:40 +02003196 cs->when = read_yin_when(module, sub);
3197 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003198 goto error;
3199 }
Michal Vasko29fc0182015-08-24 15:02:39 +02003200
Michal Vasko345da0a2015-12-02 10:35:55 +01003201 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003203 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003206 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003207
Radek Krejci3cf9e222015-06-18 11:37:50 +02003208 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003209 cs->iffeature = calloc(c_ftrs, sizeof *cs->iffeature);
3210 if (!cs->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003211 LOGMEM;
3212 goto error;
3213 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003214 }
Radek Krejci73adb602015-07-02 18:07:40 +02003215 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003216 ret = fill_yin_iffeature(retval, sub, &cs->iffeature[cs->iffeature_size], unres);
3217 cs->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003218 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003219 goto error;
3220 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 }
Radek Krejcib388c152015-06-04 17:03:03 +02003222
Michal Vasko29fc0182015-08-24 15:02:39 +02003223 /* last part - process data nodes */
3224 LY_TREE_FOR_SAFE(root.child, next, sub) {
3225 if (!strcmp(sub->name, "container")) {
3226 node = read_yin_container(module, retval, sub, resolve, unres);
3227 } else if (!strcmp(sub->name, "leaf-list")) {
3228 node = read_yin_leaflist(module, retval, sub, resolve, unres);
3229 } else if (!strcmp(sub->name, "leaf")) {
3230 node = read_yin_leaf(module, retval, sub, resolve, unres);
3231 } else if (!strcmp(sub->name, "list")) {
3232 node = read_yin_list(module, retval, sub, resolve, unres);
3233 } else if (!strcmp(sub->name, "choice")) {
3234 node = read_yin_choice(module, retval, sub, resolve, unres);
3235 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02003236 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003237 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003238 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
3239 } else if (!strcmp(sub->name, "anydata")) {
3240 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko29fc0182015-08-24 15:02:39 +02003241 }
3242 if (!node) {
3243 goto error;
3244 }
3245
Michal Vasko345da0a2015-12-02 10:35:55 +01003246 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02003247 }
3248
Michal Vasko508a50d2016-09-07 14:50:33 +02003249 /* check XPath dependencies */
3250 if (cs->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3251 goto error;
3252 }
3253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003255
3256error:
3257
Michal Vasko29fc0182015-08-24 15:02:39 +02003258 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003259 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02003260 }
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003261 lys_node_free(retval, NULL, 0);
Radek Krejcib4cf2022015-06-03 14:40:05 +02003262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003264}
3265
Michal Vasko0d343d12015-08-24 14:57:36 +02003266/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003267static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02003268read_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 +02003269{
Radek Krejci629cdef2016-06-06 15:06:36 +02003270 struct lyxml_elem *sub, *next, *dflt = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003272 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02003273 struct lys_node_choice *choice;
Radek Krejci629cdef2016-06-06 15:06:36 +02003274 const char *value;
Michal Vasko2d851a92015-10-20 16:16:36 +02003275 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01003278 if (!choice) {
3279 LOGMEM;
3280 return NULL;
3281 }
Radek Krejci76512572015-08-04 09:47:08 +02003282 choice->nodetype = LYS_CHOICE;
3283 choice->prev = (struct lys_node *)choice;
3284 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003285
Michal Vaskoe0c59842015-09-24 13:52:20 +02003286 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3287 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003290
Radek Krejcia9544502015-08-14 08:24:29 +02003291 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3292
Michal Vasko3a0043f2015-08-12 12:11:30 +02003293 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003294 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003295 goto error;
3296 }
3297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 /* process choice's specific children */
3299 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003300 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3301 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003302 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003303 continue;
3304 }
3305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003307 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003308 goto error;
3309 }
3310 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003311 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 goto error;
3313 }
3314 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003315 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 goto error;
3317 }
3318 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003319 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 goto error;
3321 }
3322 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003323 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 goto error;
3325 }
3326 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02003327 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres))) {
3328 goto error;
3329 }
3330 } else if (!strcmp(sub->name, "anydata")) {
3331 if (!(node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
3334 } else if (!strcmp(sub->name, "default")) {
Radek Krejci629cdef2016-06-06 15:06:36 +02003335 if (dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003336 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 goto error;
3338 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003339 dflt = sub;
3340 lyxml_unlink_elem(ctx, dflt, 0);
3341
Radek Krejcif9a312c2016-06-06 15:14:30 +02003342 continue;
3343 /* skip lyxml_free() at the end of the loop, the sub node is processed later as dflt */
3344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 } else if (!strcmp(sub->name, "mandatory")) {
3346 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003347 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 goto error;
3349 }
3350 /* just checking the flags in leaf is not sufficient, we would allow
3351 * multiple mandatory statements with the "false" value
3352 */
3353 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02003354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003355 GETVAL(value, sub, "value");
3356 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003357 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003358 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003359 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003360 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003361 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003364 } else if (!strcmp(sub->name, "when")) {
3365 if (choice->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003366 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003367 goto error;
3368 }
3369
3370 choice->when = read_yin_when(module, sub);
3371 if (!choice->when) {
3372 goto error;
3373 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003374 } else if (!strcmp(sub->name, "if-feature")) {
3375 c_ftrs++;
3376
Michal Vasko345da0a2015-12-02 10:35:55 +01003377 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02003378 continue;
Radek Krejci2f792db2016-09-12 10:52:33 +02003379 } else if (module->version >= 2 && !strcmp(sub->name, "choice")) {
3380 if (!(node = read_yin_choice(module, retval, sub, resolve, unres))) {
3381 goto error;
3382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003384 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003387
Radek Krejci1d82ef62015-08-07 14:44:40 +02003388 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01003389 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003391
Radek Krejci3cf9e222015-06-18 11:37:50 +02003392 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003393 choice->iffeature = calloc(c_ftrs, sizeof *choice->iffeature);
3394 if (!choice->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003395 LOGMEM;
3396 goto error;
3397 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003398 }
3399
Radek Krejci73adb602015-07-02 18:07:40 +02003400 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003401 ret = fill_yin_iffeature(retval, sub, &choice->iffeature[choice->iffeature_size], unres);
3402 choice->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003403 if (ret) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003404 goto error;
3405 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003406 }
3407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 /* check - default is prohibited in combination with mandatory */
Radek Krejci629cdef2016-06-06 15:06:36 +02003409 if (dflt && (choice->flags & LYS_MAND_TRUE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003410 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
3411 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 goto error;
3413 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 /* link default with the case */
Radek Krejci629cdef2016-06-06 15:06:36 +02003416 if (dflt) {
3417 GETVAL(value, dflt, "value");
3418 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003419 goto error;
3420 }
Radek Krejci629cdef2016-06-06 15:06:36 +02003421 lyxml_free(ctx, dflt);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003423
Michal Vasko508a50d2016-09-07 14:50:33 +02003424 /* check XPath dependencies */
3425 if (choice->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3426 goto error;
3427 }
3428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003430
3431error:
3432
Radek Krejci629cdef2016-06-06 15:06:36 +02003433 lyxml_free(ctx, dflt);
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003434 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003437}
3438
Michal Vasko0d343d12015-08-24 14:57:36 +02003439/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003440static struct lys_node *
Radek Krejcibf2abff2016-08-23 15:51:52 +02003441read_yin_anydata(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, LYS_NODE type, int resolve,
3442 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003443{
Radek Krejci76512572015-08-04 09:47:08 +02003444 struct lys_node *retval;
Radek Krejcibf2abff2016-08-23 15:51:52 +02003445 struct lys_node_anydata *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003446 struct lyxml_elem *sub, *next;
3447 const char *value;
3448 int r;
3449 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003450 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01003453 if (!anyxml) {
3454 LOGMEM;
3455 return NULL;
3456 }
Radek Krejcibf2abff2016-08-23 15:51:52 +02003457 anyxml->nodetype = type;
Radek Krejci76512572015-08-04 09:47:08 +02003458 anyxml->prev = (struct lys_node *)anyxml;
3459 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003460
Michal Vaskoe0c59842015-09-24 13:52:20 +02003461 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3462 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 goto error;
3464 }
Radek Krejci863c2852015-06-03 15:47:11 +02003465
Radek Krejcia9544502015-08-14 08:24:29 +02003466 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003467
Radek Krejciadb30652016-07-11 15:27:07 +02003468 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003469 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003470 goto error;
3471 }
3472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003474 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3475 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003476 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003477 continue;
3478 }
3479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 if (!strcmp(sub->name, "mandatory")) {
3481 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003482 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 goto error;
3484 }
3485 /* just checking the flags in leaf is not sufficient, we would allow
3486 * multiple mandatory statements with the "false" value
3487 */
3488 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 GETVAL(value, sub, "value");
3491 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003492 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003493 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003494 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003495 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003496 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 goto error;
3498 }
3499 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003500 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003501 } else if (!strcmp(sub->name, "when")) {
3502 if (anyxml->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003503 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003504 goto error;
3505 }
3506
3507 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003508 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003509 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003510 goto error;
3511 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003512 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 } else if (!strcmp(sub->name, "must")) {
3514 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003515 } else if (!strcmp(sub->name, "if-feature")) {
3516 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003519 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 }
3522 }
Radek Krejci863c2852015-06-03 15:47:11 +02003523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 /* middle part - process nodes with cardinality of 0..n */
3525 if (c_must) {
3526 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003527 if (!anyxml->must) {
3528 LOGMEM;
3529 goto error;
3530 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003532 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003533 anyxml->iffeature = calloc(c_ftrs, sizeof *anyxml->iffeature);
3534 if (!anyxml->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003535 LOGMEM;
3536 goto error;
3537 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003538 }
Radek Krejci863c2852015-06-03 15:47:11 +02003539
Radek Krejci73adb602015-07-02 18:07:40 +02003540 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003542 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3543 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 if (r) {
3545 goto error;
3546 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003547 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003548 r = fill_yin_iffeature(retval, sub, &anyxml->iffeature[anyxml->iffeature_size], unres);
3549 anyxml->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003550 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003551 goto error;
3552 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 }
Radek Krejci863c2852015-06-03 15:47:11 +02003555
Michal Vasko508a50d2016-09-07 14:50:33 +02003556 /* check XPath dependencies */
3557 if ((anyxml->when || anyxml->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3558 goto error;
3559 }
3560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003561 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003562
3563error:
3564
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003565 lys_node_free(retval, NULL, 0);
Radek Krejci863c2852015-06-03 15:47:11 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003568}
3569
Michal Vasko0d343d12015-08-24 14:57:36 +02003570/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003571static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003572read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003573 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003574{
Radek Krejci76512572015-08-04 09:47:08 +02003575 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003576 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 struct lyxml_elem *sub, *next;
3578 const char *value;
Radek Krejci48464ed2016-03-17 15:44:09 +01003579 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003580 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003583 if (!leaf) {
3584 LOGMEM;
3585 return NULL;
3586 }
Radek Krejci76512572015-08-04 09:47:08 +02003587 leaf->nodetype = LYS_LEAF;
3588 leaf->prev = (struct lys_node *)leaf;
3589 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003590
Michal Vaskoe0c59842015-09-24 13:52:20 +02003591 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3592 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 goto error;
3594 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003595
Radek Krejcia9544502015-08-14 08:24:29 +02003596 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003597
Radek Krejciadb30652016-07-11 15:27:07 +02003598 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003599 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003600 goto error;
3601 }
3602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003604 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3605 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003606 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003607 continue;
3608 }
3609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003611 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003612 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 goto error;
3614 }
Michal Vasko88c29542015-11-27 14:57:53 +01003615 /* HACK for unres */
3616 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003617 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko3767fb22016-07-21 12:10:57 +02003618 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003619 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003620 goto error;
3621 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003622 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 } else if (!strcmp(sub->name, "default")) {
3624 if (leaf->dflt) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003625 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 goto error;
3627 }
3628 GETVAL(value, sub, "value");
3629 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
3630 } else if (!strcmp(sub->name, "units")) {
3631 if (leaf->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003632 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 goto error;
3634 }
3635 GETVAL(value, sub, "name");
3636 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3637 } else if (!strcmp(sub->name, "mandatory")) {
3638 if (f_mand) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003639 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 goto error;
3641 }
3642 /* just checking the flags in leaf is not sufficient, we would allow
3643 * multiple mandatory statements with the "false" value
3644 */
3645 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 GETVAL(value, sub, "value");
3648 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003649 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003650 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003651 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003652 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003653 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 goto error;
3655 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003656 } else if (!strcmp(sub->name, "when")) {
3657 if (leaf->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003658 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003659 goto error;
3660 }
3661
3662 leaf->when = read_yin_when(module, sub);
3663 if (!leaf->when) {
3664 goto error;
3665 }
3666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003667 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003668 c_must++;
3669 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003670 } else if (!strcmp(sub->name, "if-feature")) {
3671 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003675 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003678
Michal Vasko88c29542015-11-27 14:57:53 +01003679 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003683 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003684 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 goto error;
3686 }
Michal Vasko478c4652016-07-21 12:55:01 +02003687 if (leaf->dflt && (leaf->flags & LYS_MAND_TRUE)) {
3688 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
3689 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3690 "The \"mandatory\" statement is forbidden on leaf with the \"default\" statement.");
3691 goto error;
3692 }
3693
3694 /* check default value (if not defined, there still could be some restrictions
3695 * that need to be checked against a default value from a derived type) */
3696 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt) == -1) {
3697 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 /* middle part - process nodes with cardinality of 0..n */
3701 if (c_must) {
3702 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003703 if (!leaf->must) {
3704 LOGMEM;
3705 goto error;
3706 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003708 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003709 leaf->iffeature = calloc(c_ftrs, sizeof *leaf->iffeature);
3710 if (!leaf->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003711 LOGMEM;
3712 goto error;
3713 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003714 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003715
Radek Krejci73adb602015-07-02 18:07:40 +02003716 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003718 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3719 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 if (r) {
3721 goto error;
3722 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003723 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003724 r = fill_yin_iffeature(retval, sub, &leaf->iffeature[leaf->iffeature_size], unres);
3725 leaf->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003726 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003727 goto error;
3728 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003731
Michal Vasko508a50d2016-09-07 14:50:33 +02003732 /* check XPath dependencies */
3733 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3734 goto error;
3735 }
3736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003737 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003738
3739error:
3740
Michal Vaskod51d6ad2016-02-16 13:24:31 +01003741 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744}
3745
Michal Vasko0d343d12015-08-24 14:57:36 +02003746/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003747static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003748read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003749 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003750{
Radek Krejci76512572015-08-04 09:47:08 +02003751 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003752 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 struct lyxml_elem *sub, *next;
3754 const char *value;
3755 char *endptr;
3756 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003757 int r, has_type = 0;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003758 int c_must = 0, c_ftrs = 0, c_dflt = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003762 if (!llist) {
3763 LOGMEM;
3764 return NULL;
3765 }
Radek Krejci76512572015-08-04 09:47:08 +02003766 llist->nodetype = LYS_LEAFLIST;
3767 llist->prev = (struct lys_node *)llist;
3768 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Michal Vaskoe0c59842015-09-24 13:52:20 +02003770 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3771 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003774
Radek Krejcia9544502015-08-14 08:24:29 +02003775 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003776
Radek Krejciadb30652016-07-11 15:27:07 +02003777 /* insert the node into the schema tree */
Radek Krejcic4283442016-04-22 09:19:27 +02003778 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003779 goto error;
3780 }
3781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003783 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3784 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003785 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003786 continue;
3787 }
3788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003790 if (has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003791 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 goto error;
3793 }
Michal Vasko88c29542015-11-27 14:57:53 +01003794 /* HACK for unres */
3795 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003796 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko3767fb22016-07-21 12:10:57 +02003797 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, retval) == -1) {
Michal Vasko88c29542015-11-27 14:57:53 +01003798 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 goto error;
3800 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003801 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 } else if (!strcmp(sub->name, "units")) {
3803 if (llist->units) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003804 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003805 goto error;
3806 }
3807 GETVAL(value, sub, "name");
3808 llist->units = lydict_insert(module->ctx, value, strlen(value));
3809 } else if (!strcmp(sub->name, "ordered-by")) {
3810 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003811 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 goto error;
3813 }
3814 /* just checking the flags in llist is not sufficient, we would
3815 * allow multiple ordered-by statements with the "system" value
3816 */
3817 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003818
Radek Krejci1574a8d2015-08-03 14:16:52 +02003819 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3821 * state data
3822 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003823 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 continue;
3825 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003827 GETVAL(value, sub, "value");
3828 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003829 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003831 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003833 } /* else system is the default value, so we can ignore it */
3834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 } else if (!strcmp(sub->name, "must")) {
3836 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003837 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003838 } else if (!strcmp(sub->name, "if-feature")) {
3839 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 continue;
Radek Krejcid5a5c282016-08-15 15:38:08 +02003841 } else if ((module->version >= 2) && !strcmp(sub->name, "default")) {
3842 c_dflt++;
3843 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 } else if (!strcmp(sub->name, "min-elements")) {
3846 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003847 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 goto error;
3849 }
3850 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 GETVAL(value, sub, "value");
3853 while (isspace(value[0])) {
3854 value++;
3855 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 /* convert it to uint32_t */
3858 errno = 0;
3859 endptr = NULL;
3860 val = strtoul(value, &endptr, 10);
3861 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003862 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 goto error;
3864 }
3865 llist->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003866 if (llist->max && (llist->min > llist->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003867 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3868 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003869 goto error;
3870 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 } else if (!strcmp(sub->name, "max-elements")) {
3872 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003873 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 goto error;
3875 }
3876 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 GETVAL(value, sub, "value");
3879 while (isspace(value[0])) {
3880 value++;
3881 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003882
Radek Krejci0d7b2472016-02-12 11:11:03 +01003883 if (!strcmp(value, "unbounded")) {
3884 llist->max = 0;
3885 } else {
3886 /* convert it to uint32_t */
3887 errno = 0;
3888 endptr = NULL;
3889 val = strtoul(value, &endptr, 10);
3890 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003891 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01003892 goto error;
3893 }
3894 llist->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01003895 if (llist->min > llist->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003896 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
3897 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01003898 goto error;
3899 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003901 } else if (!strcmp(sub->name, "when")) {
3902 if (llist->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003903 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003904 goto error;
3905 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003906
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003907 llist->when = read_yin_when(module, sub);
3908 if (!llist->when) {
3909 goto error;
3910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01003912 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003914 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003915
Michal Vasko88c29542015-11-27 14:57:53 +01003916 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003917 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003920 if (!has_type) {
Radek Krejci48464ed2016-03-17 15:44:09 +01003921 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 goto error;
3923 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 /* middle part - process nodes with cardinality of 0..n */
3926 if (c_must) {
3927 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003928 if (!llist->must) {
3929 LOGMEM;
3930 goto error;
3931 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003933 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003934 llist->iffeature = calloc(c_ftrs, sizeof *llist->iffeature);
3935 if (!llist->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01003936 LOGMEM;
3937 goto error;
3938 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003939 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003940 if (c_dflt) {
3941 llist->dflt = calloc(c_dflt, sizeof *llist->dflt);
3942 if (!llist->dflt) {
3943 LOGMEM;
3944 goto error;
3945 }
3946 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003947
Radek Krejci73adb602015-07-02 18:07:40 +02003948 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003950 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3951 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 if (r) {
3953 goto error;
3954 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003955 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02003956 r = fill_yin_iffeature(retval, sub, &llist->iffeature[llist->iffeature_size], unres);
3957 llist->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01003958 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003959 goto error;
3960 }
Radek Krejcid5a5c282016-08-15 15:38:08 +02003961 } else if (!strcmp(sub->name, "default")) {
3962 GETVAL(value, sub, "value");
3963
3964 /* check for duplicity */
3965 for (r = 0; r < llist->dflt_size; r++) {
3966 if (ly_strequal(llist->dflt[r], value, 1)) {
3967 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3968 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
3969 goto error;
3970 }
3971 }
3972 llist->dflt[llist->dflt_size++] = lydict_insert(module->ctx, value, strlen(value));
3973 }
3974 }
3975
3976 if (llist->dflt_size && llist->min) {
Radek Krejci200bf712016-08-16 17:11:04 +02003977 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "leaf-list");
Radek Krejcid5a5c282016-08-15 15:38:08 +02003978 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3979 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
3980 goto error;
3981 }
3982
3983 /* check default value (if not defined, there still could be some restrictions
3984 * that need to be checked against a default value from a derived type) */
3985 for (r = 0; r < llist->dflt_size; r++) {
3986 if (unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, llist->dflt[r]) == -1) {
3987 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003990
Michal Vasko508a50d2016-09-07 14:50:33 +02003991 /* check XPath dependencies */
3992 if ((llist->when || llist->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
3993 goto error;
3994 }
3995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003997
3998error:
3999
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004000 lys_node_free(retval, NULL, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004001
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004003}
4004
Michal Vasko0d343d12015-08-24 14:57:36 +02004005/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004006static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004007read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4008 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004009{
Radek Krejci1d82ef62015-08-07 14:44:40 +02004010 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02004011 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 struct lyxml_elem *sub, *next, root, uniq;
Radek Krejci48464ed2016-03-17 15:44:09 +01004013 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004014 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004015 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02004016 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 char *auxs;
4018 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004020 /* init */
4021 memset(&root, 0, sizeof root);
4022 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02004023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004024 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01004025 if (!list) {
4026 LOGMEM;
4027 return NULL;
4028 }
Radek Krejci76512572015-08-04 09:47:08 +02004029 list->nodetype = LYS_LIST;
4030 list->prev = (struct lys_node *)list;
4031 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004032
Michal Vaskoe0c59842015-09-24 13:52:20 +02004033 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4034 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 goto error;
4036 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004037
Radek Krejcia9544502015-08-14 08:24:29 +02004038 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4039
Radek Krejciadb30652016-07-11 15:27:07 +02004040 /* insert the node into the schema tree */
4041 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4042 goto error;
4043 }
4044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 /* process list's specific children */
4046 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004047 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4048 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004049 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004050 continue;
4051 }
4052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004053 /* data statements */
4054 if (!strcmp(sub->name, "container") ||
4055 !strcmp(sub->name, "leaf-list") ||
4056 !strcmp(sub->name, "leaf") ||
4057 !strcmp(sub->name, "list") ||
4058 !strcmp(sub->name, "choice") ||
4059 !strcmp(sub->name, "uses") ||
4060 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004061 !strcmp(sub->name, "anyxml") ||
4062 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004063 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004064 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004066 /* array counters */
4067 } else if (!strcmp(sub->name, "key")) {
4068 /* check cardinality 0..1 */
4069 if (list->keys_size) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004070 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004071 goto error;
4072 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02004073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 /* count the number of keys */
4075 GETVAL(value, sub, "value");
4076 key_str = value;
4077 while ((value = strpbrk(value, " \t\n"))) {
4078 list->keys_size++;
4079 while (isspace(*value)) {
4080 value++;
4081 }
4082 }
4083 list->keys_size++;
4084 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01004085 if (!list->keys) {
4086 LOGMEM;
4087 goto error;
4088 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004089 } else if (!strcmp(sub->name, "unique")) {
4090 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02004091 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004092 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004093 } else if (!strcmp(sub->name, "typedef")) {
4094 c_tpdf++;
4095 } else if (!strcmp(sub->name, "must")) {
4096 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004097 } else if (!strcmp(sub->name, "if-feature")) {
4098 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02004099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004100 /* optional stetments */
4101 } else if (!strcmp(sub->name, "ordered-by")) {
4102 if (f_ordr) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004103 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004104 goto error;
4105 }
4106 /* just checking the flags in llist is not sufficient, we would
4107 * allow multiple ordered-by statements with the "system" value
4108 */
4109 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004110
Radek Krejci1574a8d2015-08-03 14:16:52 +02004111 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004112 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
4113 * state data
4114 */
Michal Vasko345da0a2015-12-02 10:35:55 +01004115 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004116 continue;
4117 }
Radek Krejci345ad742015-06-03 11:04:18 +02004118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004119 GETVAL(value, sub, "value");
4120 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004121 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004122 } else if (strcmp(value, "system")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004123 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004124 goto error;
4125 }
4126 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01004127 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 } else if (!strcmp(sub->name, "min-elements")) {
4129 if (f_min) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004130 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 goto error;
4132 }
4133 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 GETVAL(value, sub, "value");
4136 while (isspace(value[0])) {
4137 value++;
4138 }
Radek Krejci345ad742015-06-03 11:04:18 +02004139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 /* convert it to uint32_t */
4141 errno = 0;
4142 auxs = NULL;
4143 val = strtoul(value, &auxs, 10);
4144 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004145 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004146 goto error;
4147 }
4148 list->min = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004149 if (list->max && (list->min > list->max)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004150 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4151 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004152 lyxml_free(module->ctx, sub);
4153 goto error;
4154 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004155 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004156 } else if (!strcmp(sub->name, "max-elements")) {
4157 if (f_max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004158 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004159 goto error;
4160 }
4161 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02004162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004163 GETVAL(value, sub, "value");
4164 while (isspace(value[0])) {
4165 value++;
4166 }
Radek Krejci345ad742015-06-03 11:04:18 +02004167
Radek Krejci0d7b2472016-02-12 11:11:03 +01004168 if (!strcmp(value, "unbounded")) {
4169 list->max = 0;;
4170 } else {
4171 /* convert it to uint32_t */
4172 errno = 0;
4173 auxs = NULL;
4174 val = strtoul(value, &auxs, 10);
4175 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004176 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
Radek Krejci0d7b2472016-02-12 11:11:03 +01004177 goto error;
4178 }
4179 list->max = (uint32_t) val;
Michal Vasko6ea3e362016-03-11 10:25:36 +01004180 if (list->min > list->max) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004181 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, sub->name);
4182 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
Michal Vasko6ea3e362016-03-11 10:25:36 +01004183 goto error;
4184 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004186 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004187 } else if (!strcmp(sub->name, "when")) {
4188 if (list->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004189 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004190 goto error;
4191 }
4192
4193 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004194 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004195 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004196 goto error;
4197 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004198 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004199 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004200 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004201 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004202 }
4203 }
Radek Krejci345ad742015-06-03 11:04:18 +02004204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004205 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004206 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004207 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004208 goto error;
4209 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004211 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4212 if (c_tpdf) {
4213 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004214 if (!list->tpdf) {
4215 LOGMEM;
4216 goto error;
4217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004218 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004219 if (c_must) {
4220 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004221 if (!list->must) {
4222 LOGMEM;
4223 goto error;
4224 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004225 }
4226 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004227 list->iffeature = calloc(c_ftrs, sizeof *list->iffeature);
4228 if (!list->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004229 LOGMEM;
4230 goto error;
4231 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004232 }
Radek Krejci73adb602015-07-02 18:07:40 +02004233 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004234 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004235 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
4236 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 if (r) {
4238 goto error;
4239 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004240 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004241 r = fill_yin_iffeature(retval, sub, &list->iffeature[list->iffeature_size], unres);
4242 list->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004243 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004244 goto error;
4245 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004246 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004247 r = fill_yin_must(module, sub, &list->must[list->must_size]);
4248 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004249 if (r) {
4250 goto error;
4251 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 }
4253 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 /* last part - process data nodes */
4256 LY_TREE_FOR_SAFE(root.child, next, sub) {
4257 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004258 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004259 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004260 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004261 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004262 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004263 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004264 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004265 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004266 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004268 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004269 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004270 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004272 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4273 } else if (!strcmp(sub->name, "anydata")) {
4274 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004275 } else if (!strcmp(sub->name, "action")) {
4276 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02004277 } else {
4278 LOGINT;
4279 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004281 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 goto error;
4283 }
Radek Krejci73adb602015-07-02 18:07:40 +02004284
Michal Vasko345da0a2015-12-02 10:35:55 +01004285 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004287
Radek Krejci461efb92016-02-12 15:52:18 +01004288 if (key_str) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004289 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str) == -1) {
Radek Krejci461efb92016-02-12 15:52:18 +01004290 goto error;
4291 }
4292 } /* 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 +02004293
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 /* process unique statements */
4295 if (c_uniq) {
4296 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01004297 if (!list->unique) {
4298 LOGMEM;
4299 goto error;
4300 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004301
Radek Krejci461efb92016-02-12 15:52:18 +01004302 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
4303 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
4304 list->unique_size++;
4305 if (r) {
4306 goto error;
4307 }
4308
4309 lyxml_free(module->ctx, sub);
4310 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004311 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02004312
Michal Vasko508a50d2016-09-07 14:50:33 +02004313 /* check XPath dependencies */
4314 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4315 goto error;
4316 }
4317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004319
4320error:
4321
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004322 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004324 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 }
4326 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004327 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004331}
4332
Michal Vasko0d343d12015-08-24 14:57:36 +02004333/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004334static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004335read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4336 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004337{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004339 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004340 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004341 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 const char *value;
4343 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004344 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004346 /* init */
4347 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004349 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01004350 if (!cont) {
4351 LOGMEM;
4352 return NULL;
4353 }
Radek Krejci76512572015-08-04 09:47:08 +02004354 cont->nodetype = LYS_CONTAINER;
4355 cont->prev = (struct lys_node *)cont;
4356 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004357
Michal Vaskoe0c59842015-09-24 13:52:20 +02004358 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
4359 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 goto error;
4361 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004362
Radek Krejcia9544502015-08-14 08:24:29 +02004363 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4364
Radek Krejciadb30652016-07-11 15:27:07 +02004365 /* insert the node into the schema tree */
4366 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4367 goto error;
4368 }
4369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 /* process container's specific children */
4371 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02004372 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004373 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004374 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004375 continue;
4376 }
4377
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 if (!strcmp(sub->name, "presence")) {
4379 if (cont->presence) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004380 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 goto error;
4382 }
4383 GETVAL(value, sub, "value");
4384 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02004385
Michal Vasko345da0a2015-12-02 10:35:55 +01004386 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004387 } else if (!strcmp(sub->name, "when")) {
4388 if (cont->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01004389 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004390 goto error;
4391 }
4392
4393 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004394 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004395 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004396 goto error;
4397 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004398 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02004399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 /* data statements */
4401 } else if (!strcmp(sub->name, "container") ||
4402 !strcmp(sub->name, "leaf-list") ||
4403 !strcmp(sub->name, "leaf") ||
4404 !strcmp(sub->name, "list") ||
4405 !strcmp(sub->name, "choice") ||
4406 !strcmp(sub->name, "uses") ||
4407 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004408 !strcmp(sub->name, "anyxml") ||
4409 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004410 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004411 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 /* array counters */
4414 } else if (!strcmp(sub->name, "typedef")) {
4415 c_tpdf++;
4416 } else if (!strcmp(sub->name, "must")) {
4417 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004418 } else if (!strcmp(sub->name, "if-feature")) {
4419 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004421 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 }
4424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4427 if (c_tpdf) {
4428 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004429 if (!cont->tpdf) {
4430 LOGMEM;
4431 goto error;
4432 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 }
4434 if (c_must) {
4435 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01004436 if (!cont->must) {
4437 LOGMEM;
4438 goto error;
4439 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004441 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004442 cont->iffeature = calloc(c_ftrs, sizeof *cont->iffeature);
4443 if (!cont->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004444 LOGMEM;
4445 goto error;
4446 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004447 }
Radek Krejci800af702015-06-02 13:46:01 +02004448
Radek Krejci73adb602015-07-02 18:07:40 +02004449 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004450 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004451 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
4452 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 if (r) {
4454 goto error;
4455 }
4456 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004457 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
4458 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 if (r) {
4460 goto error;
4461 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004462 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004463 r = fill_yin_iffeature(retval, sub, &cont->iffeature[cont->iffeature_size], unres);
4464 cont->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004465 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004466 goto error;
4467 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 /* last part - process data nodes */
4472 LY_TREE_FOR_SAFE(root.child, next, sub) {
4473 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004474 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004476 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004478 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004480 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004482 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004483 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004484 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004486 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004487 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004488 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4489 } else if (!strcmp(sub->name, "anydata")) {
4490 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004491 } else if (!strcmp(sub->name, "action")) {
4492 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004494 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 goto error;
4496 }
Radek Krejci73adb602015-07-02 18:07:40 +02004497
Michal Vasko345da0a2015-12-02 10:35:55 +01004498 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004500
Michal Vasko508a50d2016-09-07 14:50:33 +02004501 /* check XPath dependencies */
4502 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4503 goto error;
4504 }
4505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004507
4508error:
4509
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004510 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004512 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004514
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004516}
4517
Michal Vasko0d343d12015-08-24 14:57:36 +02004518/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004519static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02004520read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004521 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004522{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004524 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004525 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004526 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 int r;
4528 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 /* init */
4531 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02004532
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01004534 if (!grp) {
4535 LOGMEM;
4536 return NULL;
4537 }
Radek Krejci76512572015-08-04 09:47:08 +02004538 grp->nodetype = LYS_GROUPING;
4539 grp->prev = (struct lys_node *)grp;
4540 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004541
Michal Vasko71e1aa82015-08-12 12:17:51 +02004542 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 goto error;
4544 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004545
Radek Krejcia9544502015-08-14 08:24:29 +02004546 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4547
Radek Krejciadb30652016-07-11 15:27:07 +02004548 /* insert the node into the schema tree */
4549 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4550 goto error;
4551 }
4552
Radek Krejci1d82ef62015-08-07 14:44:40 +02004553 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004554 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4555 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004556 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004557 continue;
4558 }
4559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 /* data statements */
4561 if (!strcmp(sub->name, "container") ||
4562 !strcmp(sub->name, "leaf-list") ||
4563 !strcmp(sub->name, "leaf") ||
4564 !strcmp(sub->name, "list") ||
4565 !strcmp(sub->name, "choice") ||
4566 !strcmp(sub->name, "uses") ||
4567 !strcmp(sub->name, "grouping") ||
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004568 !strcmp(sub->name, "anyxml") ||
4569 !strcmp(sub->name, "action")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004570 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004571 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 /* array counters */
4574 } else if (!strcmp(sub->name, "typedef")) {
4575 c_tpdf++;
4576 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004577 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 goto error;
4579 }
4580 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4583 if (c_tpdf) {
4584 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004585 if (!grp->tpdf) {
4586 LOGMEM;
4587 goto error;
4588 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004589 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004590 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004591 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4592 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004593 if (r) {
4594 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 /* last part - process data nodes */
Michal Vasko919dbbc2016-05-19 15:22:45 +02004599 if (!root.child) {
4600 LOGWRN("Grouping \"%s\" without children.", retval->name);
4601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004602 LY_TREE_FOR_SAFE(root.child, next, sub) {
4603 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004604 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004606 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004610 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004612 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004614 node = read_yin_uses(module, retval, sub, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004616 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004618 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4619 } else if (!strcmp(sub->name, "anydata")) {
4620 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004621 } else if (!strcmp(sub->name, "action")) {
4622 node = read_yin_rpc_action(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004624 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 goto error;
4626 }
Radek Krejci73adb602015-07-02 18:07:40 +02004627
Michal Vasko345da0a2015-12-02 10:35:55 +01004628 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004632
4633error:
4634
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004635 lys_node_free(retval, NULL, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004637 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004641}
4642
Michal Vasko0d343d12015-08-24 14:57:36 +02004643/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004644static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004645read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4646 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004647{
Radek Krejcie0674f82015-06-15 13:58:51 +02004648 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004649 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004650 struct lys_node *retval = NULL;
Michal Vasko44fb6382016-06-29 11:12:27 +02004651 struct lys_node_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004652 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004653 int c_tpdf = 0, c_must = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004654
Radek Krejcie0674f82015-06-15 13:58:51 +02004655 /* init */
4656 memset(&root, 0, sizeof root);
4657
Michal Vasko38d01f72015-06-15 09:41:06 +02004658 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004659 if (!inout) {
4660 LOGMEM;
4661 return NULL;
4662 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004663 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004664
4665 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004666 inout->nodetype = LYS_INPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004667 inout->name = lydict_insert(module->ctx, "input", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004668 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004669 inout->nodetype = LYS_OUTPUT;
Michal Vasko0a1aaa42016-04-19 09:48:25 +02004670 inout->name = lydict_insert(module->ctx, "output", 0);
Michal Vasko38d01f72015-06-15 09:41:06 +02004671 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004672 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004673 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004674 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004675 }
4676
Radek Krejci76512572015-08-04 09:47:08 +02004677 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004678
Radek Krejci6a113852015-07-03 16:04:20 +02004679 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004680 goto error;
4681 }
4682
Radek Krejcia9544502015-08-14 08:24:29 +02004683 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4684
Radek Krejciadb30652016-07-11 15:27:07 +02004685 /* insert the node into the schema tree */
4686 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4687 goto error;
4688 }
4689
Michal Vasko38d01f72015-06-15 09:41:06 +02004690 /* data statements */
4691 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004692 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4693 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004694 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004695 continue;
4696 }
4697
Michal Vasko38d01f72015-06-15 09:41:06 +02004698 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 !strcmp(sub->name, "leaf-list") ||
4700 !strcmp(sub->name, "leaf") ||
4701 !strcmp(sub->name, "list") ||
4702 !strcmp(sub->name, "choice") ||
4703 !strcmp(sub->name, "uses") ||
4704 !strcmp(sub->name, "grouping") ||
4705 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004706 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004707 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004710 } else if (!strcmp(sub->name, "typedef")) {
4711 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004712
Radek Krejci1a31efe2016-07-29 11:04:16 +02004713 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004714 c_must++;
4715
Michal Vasko38d01f72015-06-15 09:41:06 +02004716 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004717 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004718 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004719 }
4720 }
4721
4722 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4723 if (c_tpdf) {
4724 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004725 if (!inout->tpdf) {
4726 LOGMEM;
4727 goto error;
4728 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004729 }
Radek Krejci19332802016-07-29 10:39:46 +02004730 if (c_must) {
4731 inout->must = calloc(c_must, sizeof *inout->must);
4732 if (!inout->must) {
4733 LOGMEM;
4734 goto error;
4735 }
4736 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004737
Radek Krejci73adb602015-07-02 18:07:40 +02004738 LY_TREE_FOR(yin->child, sub) {
Radek Krejci19332802016-07-29 10:39:46 +02004739 if (!strcmp(sub->name, "must")) {
4740 r = fill_yin_must(module, sub, &inout->must[inout->must_size]);
4741 inout->must_size++;
4742 if (r) {
4743 goto error;
4744 }
4745 } else { /* typedef */
4746 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4747 inout->tpdf_size++;
4748 if (r) {
4749 goto error;
4750 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004751 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004752 }
4753
4754 /* last part - process data nodes */
4755 LY_TREE_FOR_SAFE(root.child, next, sub) {
4756 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004757 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004758 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004759 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004760 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004761 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004762 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004763 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004764 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004765 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004766 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004767 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004768 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004769 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004770 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004771 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4772 } else if (!strcmp(sub->name, "anydata")) {
4773 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004774 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004775 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004776 goto error;
4777 }
Radek Krejci73adb602015-07-02 18:07:40 +02004778
Michal Vasko345da0a2015-12-02 10:35:55 +01004779 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004780 }
4781
Michal Vasko508a50d2016-09-07 14:50:33 +02004782 /* check XPath dependencies */
4783 if (inout->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4784 goto error;
4785 }
4786
Michal Vasko38d01f72015-06-15 09:41:06 +02004787 return retval;
4788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004789error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004790
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004791 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004792 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004793 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004794 }
4795
4796 return NULL;
4797}
4798
Michal Vasko0d343d12015-08-24 14:57:36 +02004799/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004800static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004801read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4802 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004803{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004804 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004805 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004806 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004807 struct lys_node_notif *notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004808 int r;
Radek Krejci19332802016-07-29 10:39:46 +02004809 int c_tpdf = 0, c_ftrs = 0, c_must = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004810
Michal Vaskoc6551b32015-06-16 10:51:43 +02004811 memset(&root, 0, sizeof root);
4812
Michal Vasko0ea41032015-06-16 08:53:55 +02004813 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004814 if (!notif) {
4815 LOGMEM;
4816 return NULL;
4817 }
Radek Krejci76512572015-08-04 09:47:08 +02004818 notif->nodetype = LYS_NOTIF;
4819 notif->prev = (struct lys_node *)notif;
4820 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004821
Radek Krejci6a113852015-07-03 16:04:20 +02004822 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004823 goto error;
4824 }
4825
Radek Krejcia9544502015-08-14 08:24:29 +02004826 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4827
Radek Krejciadb30652016-07-11 15:27:07 +02004828 /* insert the node into the schema tree */
4829 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
4830 goto error;
4831 }
4832
Michal Vasko0ea41032015-06-16 08:53:55 +02004833 /* process rpc's specific children */
4834 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004835 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4836 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004837 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004838 continue;
4839 }
4840
Michal Vasko0ea41032015-06-16 08:53:55 +02004841 /* data statements */
4842 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 !strcmp(sub->name, "leaf-list") ||
4844 !strcmp(sub->name, "leaf") ||
4845 !strcmp(sub->name, "list") ||
4846 !strcmp(sub->name, "choice") ||
4847 !strcmp(sub->name, "uses") ||
4848 !strcmp(sub->name, "grouping") ||
4849 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004850 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004851 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004854 } else if (!strcmp(sub->name, "typedef")) {
4855 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004856 } else if (!strcmp(sub->name, "if-feature")) {
4857 c_ftrs++;
Radek Krejci1a31efe2016-07-29 11:04:16 +02004858 } else if ((module->version >= 2) && !strcmp(sub->name, "must")) {
Radek Krejci19332802016-07-29 10:39:46 +02004859 c_must++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004860 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01004861 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004862 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004863 }
4864 }
4865
4866 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4867 if (c_tpdf) {
4868 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004869 if (!notif->tpdf) {
4870 LOGMEM;
4871 goto error;
4872 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004873 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004874 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004875 notif->iffeature = calloc(c_ftrs, sizeof *notif->iffeature);
4876 if (!notif->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01004877 LOGMEM;
4878 goto error;
4879 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004880 }
Radek Krejci19332802016-07-29 10:39:46 +02004881 if (c_must) {
4882 notif->must = calloc(c_must, sizeof *notif->must);
4883 if (!notif->must) {
4884 LOGMEM;
4885 goto error;
4886 }
4887 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004888
Radek Krejci73adb602015-07-02 18:07:40 +02004889 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004890 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004891 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4892 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004893 if (r) {
4894 goto error;
4895 }
Radek Krejci96299152016-06-22 10:17:50 +02004896 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02004897 r = fill_yin_iffeature(retval, sub, &notif->iffeature[notif->iffeature_size], unres);
4898 notif->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01004899 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004900 goto error;
4901 }
Radek Krejci19332802016-07-29 10:39:46 +02004902 } else if (!strcmp(sub->name, "must")) {
4903 r = fill_yin_must(module, sub, &notif->must[notif->must_size]);
4904 notif->must_size++;
4905 if (r) {
4906 goto error;
4907 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004908 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004909 }
4910
4911 /* last part - process data nodes */
4912 LY_TREE_FOR_SAFE(root.child, next, sub) {
4913 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004914 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004915 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004916 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004917 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004918 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004919 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004920 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004921 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004922 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004923 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02004924 node = read_yin_uses(module, retval, sub, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004925 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004926 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004927 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02004928 node = read_yin_anydata(module, retval, sub, LYS_ANYXML, resolve, unres);
4929 } else if (!strcmp(sub->name, "anydata")) {
4930 node = read_yin_anydata(module, retval, sub, LYS_ANYDATA, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004931 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004932 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004933 goto error;
4934 }
Radek Krejci73adb602015-07-02 18:07:40 +02004935
Michal Vasko345da0a2015-12-02 10:35:55 +01004936 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004937 }
4938
Michal Vasko508a50d2016-09-07 14:50:33 +02004939 /* check XPath dependencies */
4940 if (notif->must_size && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
4941 goto error;
4942 }
4943
Michal Vasko0ea41032015-06-16 08:53:55 +02004944 return retval;
4945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004946error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004947
Michal Vaskod51d6ad2016-02-16 13:24:31 +01004948 lys_node_free(retval, NULL, 0);
Michal Vasko0ea41032015-06-16 08:53:55 +02004949 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004950 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004951 }
4952
4953 return NULL;
4954}
4955
Michal Vasko0d343d12015-08-24 14:57:36 +02004956/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004957static struct lys_node *
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004958read_yin_rpc_action(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4959 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004960{
Radek Krejcie0674f82015-06-15 13:58:51 +02004961 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004962 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004963 struct lys_node *retval;
Michal Vasko44fb6382016-06-29 11:12:27 +02004964 struct lys_node_rpc_action *rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004965 int r;
Pavol Vican3cb70c72016-09-05 11:32:52 +02004966 int c_tpdf = 0, c_ftrs = 0, c_input = 0, c_output = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004967
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004968 if (!strcmp(yin->name, "action")) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02004969 if (module->version < 2) {
Michal Vaskobb174852016-07-25 11:00:21 +02004970 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
4971 return NULL;
4972 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004973 for (node = parent; node; node = lys_parent(node)) {
4974 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
4975 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
4976 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
4977 return NULL;
4978 }
4979 }
4980 }
4981
Radek Krejcie0674f82015-06-15 13:58:51 +02004982 /* init */
4983 memset(&root, 0, sizeof root);
4984
Michal Vasko38d01f72015-06-15 09:41:06 +02004985 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004986 if (!rpc) {
4987 LOGMEM;
4988 return NULL;
4989 }
Michal Vaskoca7cbc42016-07-01 11:36:53 +02004990 rpc->nodetype = (!strcmp(yin->name, "rpc") ? LYS_RPC : LYS_ACTION);
Radek Krejci76512572015-08-04 09:47:08 +02004991 rpc->prev = (struct lys_node *)rpc;
4992 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004993
Radek Krejci6a113852015-07-03 16:04:20 +02004994 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004995 goto error;
4996 }
4997
Radek Krejcia9544502015-08-14 08:24:29 +02004998 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4999
Radek Krejciadb30652016-07-11 15:27:07 +02005000 /* insert the node into the schema tree */
5001 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5002 goto error;
5003 }
5004
Michal Vasko38d01f72015-06-15 09:41:06 +02005005 /* process rpc's specific children */
5006 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005007 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5008 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005009 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005010 continue;
5011 }
5012
Michal Vasko38d01f72015-06-15 09:41:06 +02005013 if (!strcmp(sub->name, "input")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005014 if (c_input) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005015 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005016 goto error;
5017 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005018 c_input++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005019 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005020 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005021 } else if (!strcmp(sub->name, "output")) {
Pavol Vican3cb70c72016-09-05 11:32:52 +02005022 if (c_output) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005023 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005024 goto error;
5025 }
Pavol Vican3cb70c72016-09-05 11:32:52 +02005026 c_output++;
Michal Vaskof3930de2015-10-22 12:03:59 +02005027 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005028 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005030 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02005031 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02005032 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02005033 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02005036 } else if (!strcmp(sub->name, "typedef")) {
5037 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005038 } else if (!strcmp(sub->name, "if-feature")) {
5039 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005040 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005041 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02005042 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02005043 }
5044 }
5045
5046 /* middle part - process nodes with cardinality of 0..n except the data nodes */
5047 if (c_tpdf) {
5048 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01005049 if (!rpc->tpdf) {
5050 LOGMEM;
5051 goto error;
5052 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005053 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005054 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005055 rpc->iffeature = calloc(c_ftrs, sizeof *rpc->iffeature);
5056 if (!rpc->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005057 LOGMEM;
5058 goto error;
5059 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005060 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005061
Radek Krejci73adb602015-07-02 18:07:40 +02005062 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005063 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005064 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
5065 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02005066 if (r) {
5067 goto error;
5068 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005069 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005070 r = fill_yin_iffeature(retval, sub, &rpc->iffeature[rpc->iffeature_size], unres);
5071 rpc->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005072 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005073 goto error;
5074 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005075 }
Michal Vasko38d01f72015-06-15 09:41:06 +02005076 }
5077
5078 /* last part - process data nodes */
5079 LY_TREE_FOR_SAFE(root.child, next, sub) {
5080 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005081 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005082 } else if (!strcmp(sub->name, "input") || !strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005083 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02005084 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005085 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02005086 goto error;
5087 }
Radek Krejci73adb602015-07-02 18:07:40 +02005088
Michal Vasko345da0a2015-12-02 10:35:55 +01005089 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02005090 }
5091
Michal Vasko38d01f72015-06-15 09:41:06 +02005092 return retval;
5093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005094error:
Michal Vasko38d01f72015-06-15 09:41:06 +02005095
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005096 lys_node_free(retval, NULL, 0);
Michal Vasko3a9abf82015-06-17 10:18:26 +02005097 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005098 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005099 }
5100
5101 return NULL;
5102}
5103
Michal Vasko0d343d12015-08-24 14:57:36 +02005104/* logs directly
5105 *
Radek Krejci74705112015-06-05 10:25:44 +02005106 * resolve - referenced grouping should be bounded to the namespace (resolved)
5107 * only when uses does not appear in grouping. In a case of grouping's uses,
5108 * we just get information but we do not apply augment or refine to it.
5109 */
Radek Krejci76512572015-08-04 09:47:08 +02005110static struct lys_node *
Radek Krejci3440cc52016-06-23 17:03:59 +02005111read_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 +02005112{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005113 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02005114 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02005115 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005116 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005117 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005118 int r;
Radek Krejci74705112015-06-05 10:25:44 +02005119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005120 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01005121 if (!uses) {
5122 LOGMEM;
5123 return NULL;
5124 }
Radek Krejci76512572015-08-04 09:47:08 +02005125 uses->nodetype = LYS_USES;
5126 uses->prev = (struct lys_node *)uses;
5127 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02005128
Radek Krejcia9544502015-08-14 08:24:29 +02005129 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005130 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02005131
Michal Vaskoe0c59842015-09-24 13:52:20 +02005132 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
Radek Krejci3440cc52016-06-23 17:03:59 +02005133 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 goto error;
5135 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005136
Radek Krejcia9544502015-08-14 08:24:29 +02005137 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
5138
Radek Krejciadb30652016-07-11 15:27:07 +02005139 /* insert the node into the schema tree */
5140 if (lys_node_addchild(parent, lys_main_module(module), retval)) {
5141 goto error;
5142 }
5143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005144 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02005145 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005146 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
5147 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005148 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02005149 continue;
5150 }
5151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005152 if (!strcmp(sub->name, "refine")) {
5153 c_ref++;
5154 } else if (!strcmp(sub->name, "augment")) {
5155 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005156 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02005157 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005158 } else if (!strcmp(sub->name, "when")) {
5159 if (uses->when) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005160 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005161 goto error;
5162 }
5163
5164 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005165 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005166 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02005167 goto error;
5168 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005169 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005170 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005171 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005172 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005173 }
5174 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005175
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005176 /* process properties with cardinality 0..n */
5177 if (c_ref) {
5178 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01005179 if (!uses->refine) {
5180 LOGMEM;
5181 goto error;
5182 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005183 }
5184 if (c_aug) {
5185 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01005186 if (!uses->augment) {
5187 LOGMEM;
5188 goto error;
5189 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005190 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005191 if (c_ftrs) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005192 uses->iffeature = calloc(c_ftrs, sizeof *uses->iffeature);
5193 if (!uses->iffeature) {
Michal Vasko253035f2015-12-17 16:58:13 +01005194 LOGMEM;
5195 goto error;
5196 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005197 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005198
Radek Krejcia9544502015-08-14 08:24:29 +02005199 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 if (!strcmp(sub->name, "refine")) {
Radek Krejci363bd4a2016-07-29 14:30:20 +02005201 r = fill_yin_refine(retval, sub, &uses->refine[uses->refine_size], unres);
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005202 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005203 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005204 goto error;
5205 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005206 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01005207 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
5208 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005209 if (r) {
5210 goto error;
5211 }
5212 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vaskoc5c26b02016-06-29 11:10:29 +02005213 r = fill_yin_iffeature(retval, sub, &uses->iffeature[uses->iffeature_size], unres);
5214 uses->iffeature_size++;
Michal Vasko1d337e12016-02-15 12:32:04 +01005215 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005216 goto error;
5217 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005218 }
5219 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02005220
Radek Krejci48464ed2016-03-17 15:44:09 +01005221 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02005222 goto error;
5223 }
Radek Krejci74705112015-06-05 10:25:44 +02005224
Michal Vasko508a50d2016-09-07 14:50:33 +02005225 /* check XPath dependencies */
5226 if (uses->when && (unres_schema_add_node(module, unres, retval, UNRES_XPATH, NULL) == -1)) {
5227 goto error;
5228 }
5229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005230 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005231
5232error:
5233
Michal Vaskod51d6ad2016-02-16 13:24:31 +01005234 lys_node_free(retval, NULL, 0);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005236 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02005237}
5238
Michal Vasko0d343d12015-08-24 14:57:36 +02005239/* logs directly
5240 *
5241 * common code for yin_read_module() and yin_read_submodule()
5242 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005243static int
Radek Krejcic071c542016-01-27 14:57:51 +01005244read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
5245 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02005246{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005247 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005248 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005249 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005250 struct lys_module *trg;
Pavol Vican974377b2016-03-23 00:38:53 +01005251 struct lys_include inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005252 const char *value;
Pavol Vican974377b2016-03-23 00:38:53 +01005253 int i, r;
Radek Krejci4dcd3392016-06-22 10:28:40 +02005254 size_t size;
Radek Krejcic071c542016-01-27 14:57:51 +01005255 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005256 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02005257 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 +02005258
Radek Krejcic071c542016-01-27 14:57:51 +01005259 /* to simplify code, store the module/submodule being processed as trg */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02005260 trg = submodule ? (struct lys_module *)submodule : module;
Radek Krejcic071c542016-01-27 14:57:51 +01005261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005262 /* init */
5263 memset(&root, 0, sizeof root);
5264 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005265 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02005266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005267 /*
5268 * in the first run, we process elements with cardinality of 1 or 0..1 and
5269 * count elements with cardinality 0..n. Data elements (choices, containers,
5270 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
5271 * need have all top-level and groupings already prepared at that time. In
5272 * the middle loop, we process other elements with carinality of 0..n since
5273 * we need to allocate arrays to store them.
5274 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005275 LY_TREE_FOR_SAFE(yin->child, next, child) {
5276 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02005277 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01005278 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005279 continue;
5280 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005281
Radek Krejcic071c542016-01-27 14:57:51 +01005282 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005283 if (module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005284 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005285 goto error;
5286 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005287 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005288 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005289 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005290 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005291 if (module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005292 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005293 goto error;
5294 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005295 GETVAL(value, child, "value");
Radek Krejci48464ed2016-03-17 15:44:09 +01005296 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005297 goto error;
5298 }
5299 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01005300 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005301 } else if (submodule && !strcmp(child->name, "belongs-to")) {
5302 if (submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005303 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005304 goto error;
5305 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005306 GETVAL(value, child, "module");
Radek Krejci749190d2016-02-18 16:26:25 +01005307 if (!ly_strequal(value, submodule->belongsto->name, 1)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 goto error;
5310 }
Radek Krejcif3886932015-06-04 17:36:06 +02005311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005312 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005313 if (!child->child) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005314 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005315 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005316 } else if (strcmp(child->child->name, "prefix")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005317 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005318 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005319 } else if (child->child->next) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005320 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 goto error;
5322 }
5323 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005324 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005325 /* check here differs from a generic prefix check, since this prefix
5326 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02005327 */
Radek Krejci48464ed2016-03-17 15:44:09 +01005328 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005329 goto error;
5330 }
Radek Krejcic071c542016-01-27 14:57:51 +01005331 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02005332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005333 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01005334 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02005335
5336 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005337 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005338 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005339 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005340 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005341 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005343 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005344 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005345 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005346 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005347 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005348 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005349 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01005350 lyxml_unlink_elem(ctx, child, 2);
5351 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02005352
Radek Krejci1d82ef62015-08-07 14:44:40 +02005353 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02005354 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005355 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02005356 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005358 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005359 } else if (!strcmp(child->name, "container") ||
5360 !strcmp(child->name, "leaf-list") ||
5361 !strcmp(child->name, "leaf") ||
5362 !strcmp(child->name, "list") ||
5363 !strcmp(child->name, "choice") ||
5364 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02005365 !strcmp(child->name, "anyxml") ||
5366 !strcmp(child->name, "rpc") ||
5367 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005368 lyxml_unlink_elem(ctx, child, 2);
5369 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005370
Radek Krejci1d82ef62015-08-07 14:44:40 +02005371 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005372 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01005373 lyxml_unlink_elem(ctx, child, 2);
5374 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005376 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005377 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005378 if (trg->dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005379 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 goto error;
5381 }
Radek Krejcic071c542016-01-27 14:57:51 +01005382 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005383 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005384 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005385 goto error;
5386 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005387 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005388 if (trg->ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005389 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005390 goto error;
5391 }
Radek Krejcic071c542016-01-27 14:57:51 +01005392 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005393 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005394 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005395 goto error;
5396 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005397 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005398 if (trg->org) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005399 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005400 goto error;
5401 }
Radek Krejcic071c542016-01-27 14:57:51 +01005402 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005403 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005404 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 goto error;
5406 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005407 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005408 if (trg->contact) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005409 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005410 goto error;
5411 }
Radek Krejcic071c542016-01-27 14:57:51 +01005412 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01005413 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01005414 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005415 goto error;
5416 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005417 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005418 if (version_flag) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005419 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005420 goto error;
5421 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005422 GETVAL(value, child, "value");
Michal Vasko88de3e42016-06-29 11:05:32 +02005423 if (strcmp(value, "1") && strcmp(value, "1.1")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005424 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005425 goto error;
5426 }
Radek Krejcic071c542016-01-27 14:57:51 +01005427 version_flag = 1;
Michal Vasko88de3e42016-06-29 11:05:32 +02005428 if (!strcmp(value, "1")) {
5429 if (submodule) {
5430 if (module->version > 1) {
5431 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5432 goto error;
5433 }
5434 } else {
5435 module->version = 1;
5436 }
5437 } else {
5438 if (submodule) {
Radek Krejci1a31efe2016-07-29 11:04:16 +02005439 if (module->version < 2) {
Michal Vasko88de3e42016-06-29 11:05:32 +02005440 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
5441 goto error;
5442 }
5443 } else {
5444 module->version = 2;
5445 }
5446 }
5447
Michal Vasko345da0a2015-12-02 10:35:55 +01005448 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005449
Radek Krejci1d82ef62015-08-07 14:44:40 +02005450 } else if (!strcmp(child->name, "extension")) {
5451 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02005452
Radek Krejci3d468122015-10-02 13:36:12 +02005453 /* we have the following supported (hardcoded) extensions: */
5454 /* ietf-netconf's get-filter-element-attributes */
5455 if (!strcmp(module->ns, LY_NSNC) &&
5456 !strcmp(value, "get-filter-element-attributes")) {
5457 LOGDBG("NETCONF filter extension found");
5458 /* NACM's default-deny-write and default-deny-all */
5459 } else if (!strcmp(module->ns, LY_NSNACM) &&
5460 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
5461 LOGDBG("NACM extension found");
5462 /* other extensions are not supported, so inform about such an extension */
5463 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02005464 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01005465 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02005466 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005467 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005468 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005469 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005470 }
5471 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005472
Radek Krejcic071c542016-01-27 14:57:51 +01005473 /* check for mandatory statements */
5474 if (submodule && !submodule->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005475 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
Michal Vaskobdf51ef2015-12-10 12:11:21 +01005476 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01005477 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005478 if (!module->ns) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005479 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005480 goto error;
5481 }
5482 if (!module->prefix) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005483 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005484 goto error;
5485 }
5486 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02005487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005488 /* allocate arrays for elements with cardinality of 0..n */
5489 if (c_imp) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005490 size = (c_imp * sizeof *trg->imp) + sizeof(void*);
5491 trg->imp = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005492 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01005493 LOGMEM;
5494 goto error;
5495 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005496 /* set stop block for possible realloc */
5497 trg->imp[c_imp].module = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005498 }
5499 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005500 trg->rev = calloc(c_rev, sizeof *trg->rev);
5501 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01005502 LOGMEM;
5503 goto error;
5504 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005505 }
5506 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01005507 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
5508 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01005509 LOGMEM;
5510 goto error;
5511 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005512 }
5513 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01005514 trg->ident = calloc(c_ident, sizeof *trg->ident);
5515 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01005516 LOGMEM;
5517 goto error;
5518 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005519 }
5520 if (c_inc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005521 size = (c_inc * sizeof *trg->inc) + sizeof(void*);
5522 trg->inc = calloc(1, size);
Radek Krejcic071c542016-01-27 14:57:51 +01005523 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01005524 LOGMEM;
5525 goto error;
5526 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005527 /* set stop block for possible realloc */
5528 trg->inc[c_inc].submodule = (void*)0x1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005529 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005530 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01005531 trg->augment = calloc(c_aug, sizeof *trg->augment);
5532 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01005533 LOGMEM;
5534 goto error;
5535 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005536 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005537 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01005538 trg->features = calloc(c_ftrs, sizeof *trg->features);
5539 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01005540 LOGMEM;
5541 goto error;
5542 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02005543 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005544 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01005545 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
5546 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01005547 LOGMEM;
5548 goto error;
5549 }
Radek Krejcieb00f512015-07-01 16:44:58 +02005550 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005551
Michal Vasko2f7925f2015-10-21 15:06:56 +02005552 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
5553 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005554 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005555 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
5556 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005557 if (r) {
5558 goto error;
5559 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005560
Radek Krejci1d82ef62015-08-07 14:44:40 +02005561 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005562 memset(&inc, 0, sizeof inc);
5563 /* 1) pass module, not trg, since we want to pass the main module
5564 * 2) we cannot pass directly the structure in the array since
5565 * submodule parser can realloc our array of includes */
Michal Vasko5ff78822016-02-12 09:33:31 +01005566 r = fill_yin_include(module, submodule, child, &inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005567 if (!r) {
5568 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02005569 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
5570 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02005571 } else if (r == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005572 goto error;
5573 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005574
Radek Krejci1d82ef62015-08-07 14:44:40 +02005575 } else if (!strcmp(child->name, "revision")) {
5576 GETVAL(value, child, "date");
Radek Krejci48464ed2016-03-17 15:44:09 +01005577 if (lyp_check_date(value)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005578 goto error;
5579 }
Radek Krejcic071c542016-01-27 14:57:51 +01005580 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005581 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01005582 for (i = 0; i < trg->rev_size; i++) {
5583 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005584 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
5585 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005586 }
5587 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005588
Radek Krejci1d82ef62015-08-07 14:44:40 +02005589 LY_TREE_FOR(child->child, child2) {
5590 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005591 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005592 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005593 goto error;
5594 }
Radek Krejcic071c542016-01-27 14:57:51 +01005595 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5596 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005597 goto error;
5598 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005599 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005600 if (trg->rev[trg->rev_size].ref) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005601 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005602 goto error;
5603 }
Radek Krejcic071c542016-01-27 14:57:51 +01005604 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5605 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005606 goto error;
5607 }
5608 } else {
Radek Krejci48464ed2016-03-17 15:44:09 +01005609 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005610 goto error;
5611 }
5612 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005614 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005615 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005616 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005617 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005618 if (!value) {
5619 LOGMEM;
5620 goto error;
5621 }
Radek Krejcic071c542016-01-27 14:57:51 +01005622 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5623 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005624 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005625
Radek Krejci749190d2016-02-18 16:26:25 +01005626 if (!ly_strequal(trg->rev[0].dsc, trg->rev[trg->rev_size].dsc, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005627 value = trg->rev[0].dsc;
5628 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5629 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005630 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005631
Radek Krejci749190d2016-02-18 16:26:25 +01005632 if (!ly_strequal(trg->rev[0].ref, trg->rev[trg->rev_size].ref, 1)) {
Radek Krejcic071c542016-01-27 14:57:51 +01005633 value = trg->rev[0].ref;
5634 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5635 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005636 }
5637 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005638
Radek Krejcic071c542016-01-27 14:57:51 +01005639 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005640
Radek Krejci1d82ef62015-08-07 14:44:40 +02005641 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005642 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5643 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005644 if (r) {
5645 goto error;
5646 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005647
Radek Krejci1d82ef62015-08-07 14:44:40 +02005648 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005649 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5650 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005651 if (r) {
5652 goto error;
5653 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005654
Radek Krejci1d82ef62015-08-07 14:44:40 +02005655 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005656 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5657 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005658 if (r) {
5659 goto error;
5660 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005661
Radek Krejci1d82ef62015-08-07 14:44:40 +02005662 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005663 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5664 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005665 if (r) {
5666 goto error;
5667 }
Michal Vasko53a42af2016-02-12 11:05:02 +01005668 /* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */
5669 module->implemented = 1;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005671 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005672 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005673
Radek Krejcib8f98c12016-06-24 10:30:46 +02005674 if (!submodule) {
5675 /* update the size of the arrays, they can be smaller due to possible duplicities
Radek Krejci4dcd3392016-06-22 10:28:40 +02005676 * found in submodules */
Radek Krejcib8f98c12016-06-24 10:30:46 +02005677 if (module->inc_size) {
5678 module->inc = ly_realloc(module->inc, module->inc_size * sizeof *module->inc);
5679 if (!module->inc) {
5680 LOGMEM;
5681 goto error;
5682 }
5683 }
5684 if (module->imp_size) {
5685 module->imp = ly_realloc(module->imp, module->imp_size * sizeof *module->imp);
5686 if (!module->imp) {
5687 LOGMEM;
5688 goto error;
5689 }
Radek Krejci4dcd3392016-06-22 10:28:40 +02005690 }
5691 }
Radek Krejcic071c542016-01-27 14:57:51 +01005692
Radek Krejcif5be10f2015-06-16 13:29:36 +02005693 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005694 * refer to them. Submodule's data nodes are stored in the
5695 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005696 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005697 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005698 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005699 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005700 goto error;
5701 }
Radek Krejci74705112015-06-05 10:25:44 +02005702
Michal Vasko345da0a2015-12-02 10:35:55 +01005703 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005704 }
Radek Krejci74705112015-06-05 10:25:44 +02005705
Radek Krejcif5be10f2015-06-16 13:29:36 +02005706 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005707 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005708
Radek Krejci1d82ef62015-08-07 14:44:40 +02005709 if (!strcmp(child->name, "container")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005710 node = read_yin_container(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005711 } else if (!strcmp(child->name, "leaf-list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005712 node = read_yin_leaflist(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005713 } else if (!strcmp(child->name, "leaf")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005714 node = read_yin_leaf(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005715 } else if (!strcmp(child->name, "list")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005716 node = read_yin_list(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005717 } else if (!strcmp(child->name, "choice")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005718 node = read_yin_choice(trg, NULL, child, 1, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005719 } else if (!strcmp(child->name, "uses")) {
Radek Krejci3440cc52016-06-23 17:03:59 +02005720 node = read_yin_uses(trg, NULL, child, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005721 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejcibf2abff2016-08-23 15:51:52 +02005722 node = read_yin_anydata(trg, NULL, child, LYS_ANYXML, 1, unres);
5723 } else if (!strcmp(child->name, "anydata")) {
5724 node = read_yin_anydata(trg, NULL, child, LYS_ANYDATA, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005725 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskoca7cbc42016-07-01 11:36:53 +02005726 node = read_yin_rpc_action(trg, NULL, child, 0, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005727 } else if (!strcmp(child->name, "notification")) {
Michal Vaskocd074222016-02-15 11:07:03 +01005728 node = read_yin_notif(trg, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005729 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005730 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005731 goto error;
5732 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005733
Michal Vasko345da0a2015-12-02 10:35:55 +01005734 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005735 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005736
Michal Vasko2f7925f2015-10-21 15:06:56 +02005737 /* ... and finally augments (last, so we can augment our data, for instance) */
5738 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005739 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5740 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005741
Michal Vasko2f7925f2015-10-21 15:06:56 +02005742 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005743 goto error;
5744 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005745 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005746 }
5747
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005748 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005749
5750error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005751 /* cleanup */
5752 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005753 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005754 }
5755 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005756 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005757 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005758 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005759 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005760 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005762 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005763}
5764
Michal Vasko0d343d12015-08-24 14:57:36 +02005765/* logs directly */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005766struct lys_submodule *
5767yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005768{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005769 struct lyxml_elem *yin;
Michal Vasko5a721fd2016-02-16 12:16:48 +01005770 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005771 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005772
Michal Vasko5a721fd2016-02-16 12:16:48 +01005773 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005774
Radek Krejci722b0072016-02-01 17:09:45 +01005775 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005776 if (!yin) {
Michal Vasko5a721fd2016-02-16 12:16:48 +01005777 return NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005778 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005780 /* check root element */
5781 if (!yin->name || strcmp(yin->name, "submodule")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005782 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005783 goto error;
5784 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005786 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005787 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005788 goto error;
5789 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005790
Michal Vasko5a721fd2016-02-16 12:16:48 +01005791 submodule = calloc(1, sizeof *submodule);
5792 if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005793 LOGMEM;
5794 goto error;
5795 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005796
Michal Vasko5a721fd2016-02-16 12:16:48 +01005797 submodule->ctx = module->ctx;
5798 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5799 submodule->type = 1;
5800 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005801
Michal Vasko5a721fd2016-02-16 12:16:48 +01005802 LOGVRB("Reading submodule \"%s\".", submodule->name);
5803 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005804 goto error;
5805 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005807 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005808 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005809
Michal Vasko5a721fd2016-02-16 12:16:48 +01005810 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005811 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005812
5813error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005814 /* cleanup */
Michal Vasko5a721fd2016-02-16 12:16:48 +01005815 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005816 lyxml_free(module->ctx, yin);
Michal Vasko9f258e42016-02-11 11:36:27 +01005817
Michal Vasko5a721fd2016-02-16 12:16:48 +01005818 if (!submodule) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005819 LOGERR(ly_errno, "Submodule parsing failed.");
Michal Vasko5a721fd2016-02-16 12:16:48 +01005820 return NULL;
Radek Krejcidaea8212016-02-15 08:28:20 +01005821 }
5822
Michal Vasko5a721fd2016-02-16 12:16:48 +01005823 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
Radek Krejcidaea8212016-02-15 08:28:20 +01005824
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005825 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
5826 lys_submodule_module_data_free(submodule);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005827 lys_submodule_free(submodule, NULL);
Michal Vasko5a721fd2016-02-16 12:16:48 +01005828 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005829}
5830
Michal Vasko0d343d12015-08-24 14:57:36 +02005831/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005832struct lys_module *
Radek Krejciff4874d2016-03-07 12:30:50 +01005833yin_read_module(struct ly_ctx *ctx, const char *data, const char *revision, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005834{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005835 struct lyxml_elem *yin;
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005836 struct lys_module *module = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005837 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005838 const char *value;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005839 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005840
Radek Krejcic071c542016-01-27 14:57:51 +01005841 unres = calloc(1, sizeof *unres);
5842 if (!unres) {
5843 LOGMEM;
5844 return NULL;
5845 }
5846
Radek Krejci722b0072016-02-01 17:09:45 +01005847 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005848 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005849 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005850 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005852 /* check root element */
5853 if (!yin->name || strcmp(yin->name, "module")) {
Radek Krejci48464ed2016-03-17 15:44:09 +01005854 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005855 goto error;
5856 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005858 GETVAL(value, yin, "name");
Radek Krejci48464ed2016-03-17 15:44:09 +01005859 if (lyp_check_identifier(value, LY_IDENT_NAME, NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005860 goto error;
5861 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005863 module = calloc(1, sizeof *module);
5864 if (!module) {
5865 LOGMEM;
5866 goto error;
5867 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005869 module->ctx = ctx;
5870 module->name = lydict_insert(ctx, value, strlen(value));
5871 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005872 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005873
Michal Vasko9f258e42016-02-11 11:36:27 +01005874 LOGVRB("Reading module \"%s\".", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005875 if (read_sub_module(module, NULL, yin, unres)) {
5876 goto error;
5877 }
5878
5879 /* resolve rest of unres items */
5880 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005881 goto error;
5882 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005883
Radek Krejciff4874d2016-03-07 12:30:50 +01005884 if (revision) {
5885 /* check revision of the parsed model */
5886 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
Michal Vaskob24e7882016-03-21 16:13:25 +01005887 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
5888 module->name, module->rev[0].date, revision);
Radek Krejciff4874d2016-03-07 12:30:50 +01005889 goto error;
5890 }
5891 }
5892
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005893 if (lyp_ctx_add_module(&module)) {
Pavol Vicanc99b59e2016-03-22 15:46:39 +01005894 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005895 }
Radek Krejci63a91a92015-07-29 13:31:04 +02005896
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005897 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02005898 if (!module->implemented) {
5899 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
5900 }
Michal Vasko26055752016-05-03 11:36:31 +02005901 if (lys_module_set_implement(module)) {
5902 goto error;
5903 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005904
Michal Vasko26055752016-05-03 11:36:31 +02005905 if (lys_sub_module_set_dev_aug_target_implement(module)) {
5906 goto error;
5907 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005908 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02005909 if (!module->inc[i].submodule) {
5910 continue;
5911 }
Michal Vasko26055752016-05-03 11:36:31 +02005912 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
5913 goto error;
5914 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005915 }
5916 }
5917
Michal Vasko345da0a2015-12-02 10:35:55 +01005918 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005919 unres_schema_free(NULL, &unres);
Michal Vasko9f258e42016-02-11 11:36:27 +01005920 LOGVRB("Module \"%s\" successfully parsed.", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005921 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005922
5923error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005924 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005925 lyxml_free(ctx, yin);
Radek Krejcib8c07b82016-02-12 11:11:55 +01005926 unres_schema_free(module, &unres);
5927
5928 if (!module) {
Radek Krejcidaea8212016-02-15 08:28:20 +01005929 LOGERR(ly_errno, "Module parsing failed.");
Radek Krejcib8c07b82016-02-12 11:11:55 +01005930 return NULL;
5931 }
5932
5933 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005934
Michal Vasko9eb6dd02016-05-02 14:52:40 +02005935 lys_sub_module_remove_devs_augs(module);
Michal Vasko9f258e42016-02-11 11:36:27 +01005936 lys_free(module, NULL, 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005937 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005938}