blob: c218175e4ad4ec7cf2329bfb98f7df77e2e2cba8 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020023#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020024#include <errno.h>
25#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020026#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027#include <stdlib.h>
28#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020029#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020030#include <sys/types.h>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020031#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
Radek Krejci998a0b82015-08-17 13:14:36 +020033#include "libyang.h"
34#include "common.h"
35#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020036#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020037#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020038#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020039#include "resolve.h"
40#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020041#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020042
Radek Krejcice7fb782015-05-29 16:52:34 +020043#define GETVAL(value, node, arg) \
Michal Vasko2d710f32016-02-05 12:29:21 +010044 value = lyxml_get_attr(node, arg, NULL); \
45 if (!value) { \
46 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
47 goto error; \
48 }
Radek Krejcice7fb782015-05-29 16:52:34 +020049
Radek Krejcic6556022016-01-27 15:16:45 +010050/* parser.c */
51int dup_prefix_check(const char *prefix, struct lys_module *module);
52
Radek Krejcib388c152015-06-04 17:03:03 +020053#define OPT_IDENT 0x01
54#define OPT_CONFIG 0x02
55#define OPT_MODULE 0x04
56#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020057#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020058static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020059
Radek Krejcib8048692015-08-05 13:36:34 +020060static 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 +020061 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020062static 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 +020063 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020064static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020065 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020066static 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 +020067 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020068static 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 +020069 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020070static 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 +020071 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020072static 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 +020073 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020074static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020075 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020076static 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 +020077 int resolve, struct unres_schema *unres);
78static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020079
Michal Vasko0d343d12015-08-24 14:57:36 +020080/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020081static const char *
82read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +020083{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020084 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +020085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020086 /* there should be <text> child */
87 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
88 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
89 } else if (node->child->content) {
90 len = strlen(node->child->content);
91 return lydict_insert(ctx, node->child->content, len);
92 }
Radek Krejcice7fb782015-05-29 16:52:34 +020093
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020094 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020095 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +020096}
97
Michal Vasko0d343d12015-08-24 14:57:36 +020098/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020099static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200100fill_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 +0200101{
Radek Krejci73adb602015-07-02 18:07:40 +0200102 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200103 const char *value;
Radek Krejciad73b6f2016-02-09 15:42:55 +0100104 int base_flag = 0;
Radek Krejci04581c62015-05-22 21:24:00 +0200105
Michal Vasko4cfcd252015-08-03 14:31:10 +0200106 GETVAL(value, yin, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100107 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200108
Radek Krejci76512572015-08-04 09:47:08 +0200109 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200110 return EXIT_FAILURE;
111 }
Radek Krejci04581c62015-05-22 21:24:00 +0200112
Radek Krejci73adb602015-07-02 18:07:40 +0200113 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200114 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
115 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200116 continue;
117 }
118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119 if (!strcmp(node->name, "base")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100120 if (base_flag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200121 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200122 return EXIT_FAILURE;
123 }
Radek Krejciad73b6f2016-02-09 15:42:55 +0100124 base_flag = 1;
125
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200126 GETVAL(value, node, "name");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100127 value = transform_schema2json(module, value, LOGLINE(node));
128 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200129 return EXIT_FAILURE;
130 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100131
132 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
133 lydict_remove(module->ctx, value);
134 return EXIT_FAILURE;
135 }
136 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200138 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200139 return EXIT_FAILURE;
140 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200141 }
Radek Krejci04581c62015-05-22 21:24:00 +0200142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200143 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200144
145error:
146 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200147}
148
Michal Vasko0d343d12015-08-24 14:57:36 +0200149/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200150static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200151read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200152{
Radek Krejci73adb602015-07-02 18:07:40 +0200153 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200154 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200155
Radek Krejci73adb602015-07-02 18:07:40 +0200156 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200157 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
158 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200159 continue;
160 }
161
Radek Krejci41726f92015-06-19 13:11:05 +0200162 if (!strcmp(child->name, "description")) {
163 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200164 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200165 return EXIT_FAILURE;
166 }
167 restr->dsc = read_yin_subnode(ctx, child, "text");
168 if (!restr->dsc) {
169 return EXIT_FAILURE;
170 }
171 } else if (!strcmp(child->name, "reference")) {
172 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200173 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200174 return EXIT_FAILURE;
175 }
176 restr->ref = read_yin_subnode(ctx, child, "text");
177 if (!restr->ref) {
178 return EXIT_FAILURE;
179 }
180 } else if (!strcmp(child->name, "error-app-tag")) {
181 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200182 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200183 return EXIT_FAILURE;
184 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200185 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200186 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200187 } else if (!strcmp(child->name, "error-message")) {
188 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200189 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200190 return EXIT_FAILURE;
191 }
192 restr->emsg = read_yin_subnode(ctx, child, "value");
193 if (!restr->emsg) {
194 return EXIT_FAILURE;
195 }
196 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200197 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200198 return EXIT_FAILURE;
199 }
Radek Krejci41726f92015-06-19 13:11:05 +0200200 }
201
202 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200203
204error:
205 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200206}
207
Michal Vasko88c29542015-11-27 14:57:53 +0100208/* logs directly, returns EXIT_SUCCESS, EXIT_FAILURE, -1 */
209int
Radek Krejcib8048692015-08-05 13:36:34 +0200210fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskof02e3742015-08-05 16:27:02 +0200211 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200212{
Michal Vasko1dca6882015-10-22 14:29:42 +0200213 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200214 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200215 struct lys_restr **restr;
216 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200217 pcre *precomp;
218 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200219 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200220 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200221
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200222 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200223 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200224 if (!value) {
225 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200226 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200227
228 i = parse_identifier(value);
229 if (i < 1) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200230 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[-i], &value[-i]);
Michal Vasko88c29542015-11-27 14:57:53 +0100231 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200232 goto error;
233 }
234 /* module name */
235 if (value[i]) {
236 type->module_name = lydict_insert(module->ctx, value, i);
237 value += i;
Michal Vasko534f8442015-10-21 13:25:49 +0200238 if ((value[0] != ':') || (parse_identifier(value + 1) < 1)) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200239 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[0], value);
Michal Vasko88c29542015-11-27 14:57:53 +0100240 lydict_remove(module->ctx, value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200241 goto error;
242 }
Michal Vasko534f8442015-10-21 13:25:49 +0200243 ++value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200244 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200245
Michal Vasko1dca6882015-10-22 14:29:42 +0200246 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vasko88c29542015-11-27 14:57:53 +0100247 lydict_remove(module->ctx, value);
Michal Vaskof7eee892015-08-24 15:03:11 +0200248 if (rc == -1) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200249 LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200250 goto error;
Michal Vasko88c29542015-11-27 14:57:53 +0100251
252 /* the type could not be resolved or it was resolved to an unresolved typedef */
Michal Vaskof7eee892015-08-24 15:03:11 +0200253 } else if (rc == EXIT_FAILURE) {
Michal Vasko88c29542015-11-27 14:57:53 +0100254 return EXIT_FAILURE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200255 }
256 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200257
Radek Krejcicf509982015-12-15 09:22:44 +0100258 /* check status */
Radek Krejcic6556022016-01-27 15:16:45 +0100259 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
Radek Krejcicf509982015-12-15 09:22:44 +0100260 type->der->flags, type->der->module, type->der->name, LOGLINE(yin))) {
261 return -1;
262 }
263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200264 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200265 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200266 /* RFC 6020 9.7.4 - bit */
267
268 /* get bit specifications, at least one must be present */
269 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200270 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
271 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100272 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200273 continue;
274 }
275
Radek Krejci994b6f62015-06-18 16:47:27 +0200276 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200277 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200278 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100279 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200280 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200281 }
282 }
Radek Krejciac781922015-07-09 15:35:14 +0200283 if (!type->der->type.der && !type->info.bits.count) {
284 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200285 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200286 goto error;
287 }
Radek Krejciac781922015-07-09 15:35:14 +0200288 if (type->der->type.der && type->info.bits.count) {
289 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200290 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200291 goto error;
292 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200293
294 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Michal Vasko253035f2015-12-17 16:58:13 +0100295 if (!type->info.bits.bit) {
296 LOGMEM;
297 goto error;
298 }
Radek Krejci73adb602015-07-02 18:07:40 +0200299 p = 0;
300 i = -1;
301 LY_TREE_FOR(yin->child, next) {
302 i++;
303
304 GETVAL(value, next, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100305 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Michal Vasko2d26a022015-12-07 09:27:21 +0100306 goto error;
307 }
308
Radek Krejci994b6f62015-06-18 16:47:27 +0200309 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200310 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200311 type->info.bits.count = i + 1;
312 goto error;
313 }
314
315 /* check the name uniqueness */
316 for (j = 0; j < i; j++) {
317 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200318 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200319 type->info.bits.count = i + 1;
320 goto error;
321 }
322 }
323
Radek Krejci0d70c372015-07-02 16:23:10 +0200324 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200325 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200326 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
327 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200328 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200329 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200330
Radek Krejci0d70c372015-07-02 16:23:10 +0200331 if (!strcmp(node->name, "position")) {
332 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200333 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200334
335 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200336 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200337 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200338 type->info.bits.count = i + 1;
339 goto error;
340 }
341 type->info.bits.bit[i].pos = (uint32_t)p_;
342
343 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200344 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200345 p = type->info.bits.bit[i].pos;
346 p++;
347 } else {
348 /* check that the value is unique */
349 for (j = 0; j < i; j++) {
350 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200351 LOGVAL(LYE_BITS_DUPVAL, LOGLINE(node), type->info.bits.bit[i].pos, type->info.bits.bit[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200352 type->info.bits.count = i + 1;
353 goto error;
354 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200355 }
356 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200357 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100358 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200359 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200360 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200361 }
362 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200363 /* assign value automatically */
364 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200365 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200366 type->info.bits.count = i + 1;
367 goto error;
368 }
369 type->info.bits.bit[i].pos = (uint32_t)p;
370 p++;
371 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200372
373 /* keep them ordered by position */
374 j = i;
375 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
376 /* switch them */
377 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
378 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
379 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
380 j--;
381 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200383 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200386 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200387 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200388 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
389 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200390 continue;
391 }
392
Radek Krejcif9401c32015-06-26 16:47:36 +0200393 if (!strcmp(node->name, "range")) {
394 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200395 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200396 goto error;
397 }
398
399 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200400 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200401 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200402 goto error;
403 }
404 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
Michal Vasko253035f2015-12-17 16:58:13 +0100405 if (!type->info.dec64.range) {
406 LOGMEM;
407 goto error;
408 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200409 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
410
411 /* get possible substatements */
412 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
413 goto error;
414 }
415 } else if (!strcmp(node->name, "fraction-digits")) {
416 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200417 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200418 goto error;
419 }
420 GETVAL(value, node, "value");
421 v = strtol(value, NULL, 10);
422
423 /* range check */
424 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200425 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200426 goto error;
427 }
428 type->info.dec64.dig = (uint8_t)v;
429 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200430 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200431 goto error;
432 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200433 }
434
435 /* mandatory sub-statement(s) check */
436 if (!type->info.dec64.dig && !type->der->type.der) {
437 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200438 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200439 goto error;
440 }
Radek Krejci7511f402015-07-10 09:56:30 +0200441 if (type->info.dec64.dig && type->der->type.der) {
442 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200443 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200444 goto error;
445 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200446 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200448 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200449 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200450
Radek Krejci994b6f62015-06-18 16:47:27 +0200451 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200452 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200453 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
454 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100455 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200456 continue;
457 }
458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200459 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200460 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200461 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100462 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200463 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200464 }
465 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200466 if (!type->der->type.der && !type->info.enums.count) {
467 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200468 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200469 goto error;
470 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200471 if (type->der->type.der && type->info.enums.count) {
472 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200473 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200474 goto error;
475 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200476
Radek Krejci1574a8d2015-08-03 14:16:52 +0200477 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Michal Vasko253035f2015-12-17 16:58:13 +0100478 if (!type->info.enums.enm) {
479 LOGMEM;
480 goto error;
481 }
Radek Krejci73adb602015-07-02 18:07:40 +0200482 v = 0;
483 i = -1;
484 LY_TREE_FOR(yin->child, next) {
485 i++;
486
487 GETVAL(value, next, "name");
Michal Vasko0fb58e92015-12-07 09:27:44 +0100488 if (!value[0]) {
489 LOGVAL(LYE_SPEC, LOGLINE(next), "Enum name must not be empty.");
490 goto error;
491 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200492 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200493 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200494 type->info.enums.count = i + 1;
495 goto error;
496 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200499 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200500 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200501 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200502 type->info.enums.count = i + 1;
503 goto error;
504 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200506 /* check the name uniqueness */
507 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200508 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200509 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200510 type->info.enums.count = i + 1;
511 goto error;
512 }
513 }
Radek Krejci04581c62015-05-22 21:24:00 +0200514
Radek Krejci0d70c372015-07-02 16:23:10 +0200515 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200516 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200517 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
518 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200519 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521
Radek Krejci0d70c372015-07-02 16:23:10 +0200522 if (!strcmp(node->name, "value")) {
523 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200524 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200525
526 /* range check */
527 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200528 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200529 type->info.enums.count = i + 1;
530 goto error;
531 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200532 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200533
534 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200535 if (type->info.enums.enm[i].value > v) {
536 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200537 v++;
538 } else {
539 /* check that the value is unique */
540 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200541 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200542 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200543 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200544 type->info.enums.count = i + 1;
545 goto error;
546 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200547 }
548 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200549 } else {
Michal Vaskoe29c6622015-11-27 15:02:31 +0100550 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200551 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200552 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200553 }
554 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200555 /* assign value automatically */
556 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200557 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200558 type->info.enums.count = i + 1;
559 goto error;
560 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200561 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200562 v++;
563 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200564 }
565 break;
566
567 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200568 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200569
570 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200571 LY_TREE_FOR_SAFE(yin->child, next, node) {
572 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
573 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100574 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200575 continue;
576 }
577
Michal Vaskoe29c6622015-11-27 15:02:31 +0100578 if (strcmp(node->name, "base")) {
579 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 goto error;
581 }
582 }
583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200584 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200585 if (type->der->type.der) {
586 /* this is just a derived type with no base specified/required */
587 break;
588 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200589 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200590 goto error;
591 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200592 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200593 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200594 goto error;
595 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200596 GETVAL(value, yin->child, "name");
Michal Vaskobdfb1e02016-02-05 13:15:11 +0100597 /* store in the JSON format */
598 value = transform_schema2json(module, value, LOGLINE(yin->child));
599 if (!value) {
600 goto error;
601 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200602 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200603 goto error;
604 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 break;
606
607 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200608 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200609 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200610 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
611 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200612 continue;
613 }
614
Radek Krejciaf351422015-06-19 14:49:38 +0200615 if (!strcmp(node->name, "require-instance")) {
616 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200617 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200618 goto error;
619 }
620 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200621 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200622 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200623 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200624 type->info.inst.req = -1;
625 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200626 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200627 goto error;
628 }
629 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200630 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200631 goto error;
632 }
Radek Krejciaf351422015-06-19 14:49:38 +0200633 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200635 break;
636
Radek Krejcif2860132015-06-20 12:37:20 +0200637 case LY_TYPE_BINARY:
638 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 case LY_TYPE_INT8:
640 case LY_TYPE_INT16:
641 case LY_TYPE_INT32:
642 case LY_TYPE_INT64:
643 case LY_TYPE_UINT8:
644 case LY_TYPE_UINT16:
645 case LY_TYPE_UINT32:
646 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200647 /* RFC 6020 9.2.4 - range */
648
649 /* length and range are actually the same restriction, so process
650 * them by this common code, we just need to differ the name and
651 * structure where the information will be stored
652 */
653 if (type->base == LY_TYPE_BINARY) {
654 restr = &type->info.binary.length;
655 name = "length";
656 } else {
657 restr = &type->info.num.range;
658 name = "range";
659 }
660
Radek Krejci73adb602015-07-02 18:07:40 +0200661 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200662 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
663 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200664 continue;
665 }
666
Radek Krejcif2860132015-06-20 12:37:20 +0200667 if (!strcmp(node->name, name)) {
668 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200669 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200670 goto error;
671 }
672
673 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200674 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200675 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200676 goto error;
677 }
678 *restr = calloc(1, sizeof **restr);
Michal Vasko253035f2015-12-17 16:58:13 +0100679 if (!(*restr)) {
680 LOGMEM;
681 goto error;
682 }
Radek Krejcif2860132015-06-20 12:37:20 +0200683 (*restr)->expr = lydict_insert(module->ctx, value, 0);
684
685 /* get possible substatements */
686 if (read_restr_substmt(module->ctx, *restr, node)) {
687 goto error;
688 }
689 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200690 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200691 goto error;
692 }
Radek Krejcif2860132015-06-20 12:37:20 +0200693 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200694 break;
695
696 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200697 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200698 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200699 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
700 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200701 continue;
702 }
703
Michal Vasko88c29542015-11-27 14:57:53 +0100704 if (!strcmp(node->name, "path") && !type->der->type.der) {
Radek Krejcidc4c1412015-06-19 15:39:54 +0200705 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200706 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200707 goto error;
708 }
709
710 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200711 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200712 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200713 if (!type->info.lref.path) {
714 goto error;
715 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200716 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200717 goto error;
718 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200719
Radek Krejcidc4c1412015-06-19 15:39:54 +0200720 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200721 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200722 goto error;
723 }
Radek Krejci73adb602015-07-02 18:07:40 +0200724 }
725
Michal Vasko88c29542015-11-27 14:57:53 +0100726 if (!type->info.lref.path && !type->der->type.der) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200727 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200728 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200730 break;
731
732 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200733 /* RFC 6020 9.4.4 - length */
734 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200735 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200736 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200737 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
738 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100739 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 continue;
741 }
742
Radek Krejci3733a802015-06-19 13:43:21 +0200743 if (!strcmp(node->name, "length")) {
744 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200745 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200746 goto error;
747 }
748
749 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200750 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200751 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200752 goto error;
753 }
754 type->info.str.length = calloc(1, sizeof *type->info.str.length);
Michal Vasko253035f2015-12-17 16:58:13 +0100755 if (!type->info.str.length) {
756 LOGMEM;
757 goto error;
758 }
Radek Krejci3733a802015-06-19 13:43:21 +0200759 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
760
Radek Krejci5fbc9162015-06-19 14:11:11 +0200761 /* get possible sub-statements */
762 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200763 goto error;
764 }
Michal Vasko345da0a2015-12-02 10:35:55 +0100765 lyxml_free(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200766 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200767 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200768 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200769 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200770 goto error;
771 }
772 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200773 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200774 if (i) {
775 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
Michal Vasko253035f2015-12-17 16:58:13 +0100776 if (!type->info.str.patterns) {
777 LOGMEM;
778 goto error;
779 }
Radek Krejci73adb602015-07-02 18:07:40 +0200780 LY_TREE_FOR(yin->child, node) {
Michal Vasko5b64da22015-11-23 15:22:30 +0100781 GETVAL(value, node, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200782
783 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200784 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
785 if (!precomp) {
786 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200787 free(type->info.str.patterns);
788 goto error;
789 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200790 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +0200791
Radek Krejci73adb602015-07-02 18:07:40 +0200792 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200793
794 /* get possible sub-statements */
Michal Vasko5b64da22015-11-23 15:22:30 +0100795 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
Michal Vasko69068852015-07-13 14:34:31 +0200796 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200797 goto error;
798 }
Radek Krejci73adb602015-07-02 18:07:40 +0200799 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200800 }
801 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 break;
803
804 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200805 /* RFC 6020 7.4 - type */
806 /* count number of types in union */
807 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200808 LY_TREE_FOR_SAFE(yin->child, next, node) {
809 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
810 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100811 lyxml_free(module->ctx, node);
Radek Krejci0d70c372015-07-02 16:23:10 +0200812 continue;
813 }
814
Radek Krejcie4c366b2015-07-02 10:11:31 +0200815 if (!strcmp(node->name, "type")) {
816 i++;
817 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200818 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200819 goto error;
820 }
821 }
822
823 if (!i) {
824 if (type->der->type.der) {
Michal Vasko88c29542015-11-27 14:57:53 +0100825 /* this is just a derived type with no additional type specified/required */
Radek Krejcie4c366b2015-07-02 10:11:31 +0200826 break;
827 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200828 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +0200829 goto error;
830 }
831
832 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200833 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Michal Vasko253035f2015-12-17 16:58:13 +0100834 if (!type->info.uni.types) {
835 LOGMEM;
836 goto error;
837 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200838 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +0200839 LY_TREE_FOR(yin->child, node) {
Radek Krejcicf509982015-12-15 09:22:44 +0100840 type->info.uni.types[type->info.uni.count].parent = type->parent;
Michal Vasko88c29542015-11-27 14:57:53 +0100841 rc = fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres);
842 if (!rc) {
843 type->info.uni.count++;
844
845 /* union's type cannot be empty or leafref */
846 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
847 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
848 rc = -1;
849 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
850 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
851 rc = -1;
852 }
853 }
854 if (rc) {
855 /* even if we got EXIT_FAILURE, throw it all away, too much trouble doing something else */
856 for (i = 0; i < type->info.uni.count; ++i) {
857 lys_type_free(module->ctx, &type->info.uni.types[i]);
858 }
859 free(type->info.uni.types);
860 type->info.uni.types = NULL;
861 type->info.uni.count = 0;
862
863 if (rc == EXIT_FAILURE) {
864 return EXIT_FAILURE;
865 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200866 goto error;
867 }
Michal Vasko88c29542015-11-27 14:57:53 +0100868 }
869 break;
Radek Krejcie4c366b2015-07-02 10:11:31 +0200870
Michal Vasko88c29542015-11-27 14:57:53 +0100871 case LY_TYPE_BOOL:
872 case LY_TYPE_EMPTY:
873 /* no sub-statement allowed */
874 LY_TREE_FOR(yin->child, node) {
875 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
876 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +0200877 goto error;
878 }
Radek Krejcie4c366b2015-07-02 10:11:31 +0200879 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200880 break;
881
882 default:
Michal Vasko88c29542015-11-27 14:57:53 +0100883 LOGINT;
884 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200885 }
886
887 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +0200888
889error:
Michal Vasko88c29542015-11-27 14:57:53 +0100890 return -1;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200891}
892
Michal Vasko0d343d12015-08-24 14:57:36 +0200893/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200894static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200895fill_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 +0200896{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200897 const char *value;
Michal Vasko88c29542015-11-27 14:57:53 +0100898 struct lyxml_elem *node, *next;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200899 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200901 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100902 if (lyp_check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200903 goto error;
904 }
905 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +0200906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200907 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +0200908 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 goto error;
910 }
Radek Krejcieac35532015-05-31 19:09:15 +0200911
Michal Vasko88c29542015-11-27 14:57:53 +0100912 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200913 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
914 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200915 continue;
916 }
917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200918 if (!strcmp(node->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +0100919 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200920 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200921 goto error;
922 }
Michal Vasko88c29542015-11-27 14:57:53 +0100923 /* HACK for unres */
924 tpdf->type.der = (struct lys_tpdf *)node;
Radek Krejcicf509982015-12-15 09:22:44 +0100925 tpdf->type.parent = tpdf;
Michal Vasko88c29542015-11-27 14:57:53 +0100926 if (unres_schema_add_node(module, unres, &tpdf->type, UNRES_TYPE_DER, parent, LOGLINE(node))) {
Radek Krejci73adb602015-07-02 18:07:40 +0200927 goto error;
928 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200929 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200930 } else if (!strcmp(node->name, "default")) {
931 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200932 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200933 goto error;
934 }
935 GETVAL(value, node, "value");
936 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200937 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 } else if (!strcmp(node->name, "units")) {
939 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200940 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 goto error;
942 }
943 GETVAL(value, node, "name");
944 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
945 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200946 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 goto error;
948 }
949 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200951 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200952 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200953 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200954 goto error;
955 }
Radek Krejcieac35532015-05-31 19:09:15 +0200956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200957 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200958 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +0200959 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200960 goto error;
961 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200962 }
Radek Krejcida04f4a2015-05-21 12:54:09 +0200963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200964 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200965
966error:
967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200968 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200969}
970
Michal Vasko0d343d12015-08-24 14:57:36 +0200971/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +0200972static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200973fill_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 +0200974{
975 const char *value;
976 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +0200977 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +0200978
Radek Krejcib05774c2015-06-18 13:52:59 +0200979 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +0100980 if (lyp_check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
Radek Krejcib05774c2015-06-18 13:52:59 +0200981 goto error;
982 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200983 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +0200984 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +0200985
Radek Krejci76512572015-08-04 09:47:08 +0200986 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +0200987 goto error;
988 }
989
990 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200991 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
992 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +0100993 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +0200994 continue;
995 }
996
Radek Krejci3cf9e222015-06-18 11:37:50 +0200997 if (!strcmp(child->name, "if-feature")) {
998 c++;
999 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001000 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001001 goto error;
1002 }
1003 }
1004
1005 if (c) {
1006 f->features = calloc(c, sizeof *f->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001007 if (!f->features) {
1008 LOGMEM;
1009 goto error;
1010 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001011 }
Radek Krejci73adb602015-07-02 18:07:40 +02001012 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001013 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001014 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001015 goto error;
1016 }
Radek Krejcicf509982015-12-15 09:22:44 +01001017 /* hack - store pointer to the parent node for later status check */
1018 f->features[f->features_size] = f;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001019 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001020 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001021 f->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001022 lydict_remove(module->ctx, value);
1023 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001024 goto error;
1025 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001026 }
1027
Radek Krejci3cf9e222015-06-18 11:37:50 +02001028 return EXIT_SUCCESS;
1029
1030error:
1031
1032 return EXIT_FAILURE;
1033}
1034
Michal Vasko0d343d12015-08-24 14:57:36 +02001035/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036static int
Radek Krejcib8048692015-08-05 13:36:34 +02001037fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001038{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001039 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001041 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001042 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001043 if (!must->expr) {
1044 goto error;
1045 }
Radek Krejci800af702015-06-02 13:46:01 +02001046
Radek Krejci41726f92015-06-19 13:11:05 +02001047 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001048
Radek Krejci41726f92015-06-19 13:11:05 +02001049error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001052}
1053
Radek Krejci581ce772015-11-10 17:22:40 +01001054static int
Michal Vasko88c29542015-11-27 14:57:53 +01001055fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
1056 struct unres_schema *unres)
Radek Krejci581ce772015-11-10 17:22:40 +01001057{
1058 int i, j;
1059 const char *value, *vaux;
1060
1061 /* get unique value (list of leafs supposed to be unique */
1062 GETVAL(value, yin, "tag");
1063
1064 /* count the number of unique leafs in the value */
1065 vaux = value;
1066 while ((vaux = strpbrk(vaux, " \t\n"))) {
1067 unique->expr_size++;
1068 while (isspace(*vaux)) {
1069 vaux++;
1070 }
1071 }
1072 unique->expr_size++;
1073 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
Michal Vasko253035f2015-12-17 16:58:13 +01001074 if (!unique->expr) {
1075 LOGMEM;
1076 goto error;
1077 }
Radek Krejci581ce772015-11-10 17:22:40 +01001078
1079 for (i = 0; i < unique->expr_size; i++) {
1080 vaux = strpbrk(value, " \t\n");
1081 if (!vaux) {
1082 /* the last token, lydict_insert() will count its size on its own */
1083 vaux = value;
1084 }
1085
1086 /* store token into unique structure */
1087 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1088
1089 /* check that the expression does not repeat */
1090 for (j = 0; j < i; j++) {
1091 if (unique->expr[j] == unique->expr[i]) {
1092 LOGVAL(LYE_INARG, LOGLINE(yin), unique->expr[i], "unique");
1093 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
1094 goto error;
1095 }
1096 }
1097
1098 /* try to resolve leaf */
1099 if (unres) {
1100 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1101 } else {
1102 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1103 goto error;
1104 }
1105 }
1106
1107 /* move to next token */
1108 value = vaux;
1109 while(isspace(*value)) {
1110 value++;
1111 }
1112 }
1113
1114 return EXIT_SUCCESS;
1115
1116error:
1117 return EXIT_FAILURE;
1118}
1119
Michal Vasko0d343d12015-08-24 14:57:36 +02001120/* logs directly
1121 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001122 * type: 0 - min, 1 - max
1123 */
1124static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001125deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001126{
1127 const char *value;
1128 char *endptr;
1129 unsigned long val;
1130 uint32_t *ui32val;
1131
1132 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001133 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001134 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001135 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001136 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001137 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001138 }
Radek Krejci76512572015-08-04 09:47:08 +02001139 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001140 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001141 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001142 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001143 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001144 }
1145 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001146 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1147 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001148 goto error;
1149 }
1150
1151 GETVAL(value, node, "value");
1152 while (isspace(value[0])) {
1153 value++;
1154 }
1155
1156 /* convert it to uint32_t */
1157 errno = 0;
1158 endptr = NULL;
1159 val = strtoul(value, &endptr, 10);
1160 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001161 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001162 goto error;
1163 }
1164 if (type) {
1165 d->max = (uint32_t)val;
1166 } else {
1167 d->min = (uint32_t)val;
1168 }
1169
1170 if (d->mod == LY_DEVIATE_ADD) {
1171 /* check that there is no current value */
1172 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001173 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1174 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001175 goto error;
1176 }
1177 }
1178
1179 if (d->mod == LY_DEVIATE_DEL) {
1180 /* check values */
1181 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001182 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1183 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001184 goto error;
1185 }
1186 /* remove current min-elements value of the target */
1187 *ui32val = 0;
1188 } else { /* add (already checked) and replace */
1189 /* set new value specified in deviation */
1190 *ui32val = (uint32_t)val;
1191 }
1192
1193 return EXIT_SUCCESS;
1194
1195error:
1196
1197 return EXIT_FAILURE;
1198}
1199
Michal Vasko0d343d12015-08-24 14:57:36 +02001200/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001201static int
Michal Vasko88c29542015-11-27 14:57:53 +01001202fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev,
1203 struct unres_schema *unres)
Radek Krejcieb00f512015-07-01 16:44:58 +02001204{
1205 const char *value, **stritem;
1206 struct lyxml_elem *next, *child, *develem;
1207 int c_dev = 0, c_must, c_uniq;
1208 int f_min = 0; /* flags */
Radek Krejci581ce772015-11-10 17:22:40 +01001209 int i, j, k, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001210 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001211 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001212 struct lys_node_choice *choice = NULL;
1213 struct lys_node_leaf *leaf = NULL;
1214 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001215 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001216 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001217 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001218
1219 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001220 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001221 if (!dev->target_name) {
1222 goto error;
1223 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001224
1225 /* resolve target node */
Michal Vasko1e62a092015-12-01 12:27:20 +01001226 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, (const struct lys_node **)&dev->target);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001227 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001228 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001229 goto error;
1230 }
1231 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001232 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001233 goto error;
1234 }
1235 /* mark the target module as deviated */
1236 dev->target->module->deviated = 1;
1237
1238 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001239 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1240 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001241 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001242 continue;
1243 }
1244
Radek Krejcieb00f512015-07-01 16:44:58 +02001245 if (!strcmp(child->name, "description")) {
1246 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001247 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001248 goto error;
1249 }
1250 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1251 if (!dev->dsc) {
1252 goto error;
1253 }
1254 } else if (!strcmp(child->name, "reference")) {
1255 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001256 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001257 goto error;
1258 }
1259 dev->ref = read_yin_subnode(module->ctx, child, "text");
1260 if (!dev->ref) {
1261 goto error;
1262 }
1263 } else if (!strcmp(child->name, "deviate")) {
1264 c_dev++;
1265
Michal Vasko345da0a2015-12-02 10:35:55 +01001266 /* skip lyxml_free() at the end of the loop, node will be
Radek Krejcieb00f512015-07-01 16:44:58 +02001267 * further processed later
1268 */
1269 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001270
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001272 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001273 goto error;
1274 }
1275
Michal Vasko345da0a2015-12-02 10:35:55 +01001276 lyxml_free(module->ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02001277 }
1278
1279 if (c_dev) {
1280 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
Michal Vasko253035f2015-12-17 16:58:13 +01001281 if (!dev->deviate) {
1282 LOGMEM;
1283 goto error;
1284 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001285 }
1286
1287 LY_TREE_FOR(yin->child, develem) {
1288 /* init */
1289 f_min = 0;
1290 c_must = 0;
1291 c_uniq = 0;
1292
1293 /* get deviation type */
1294 GETVAL(value, develem, "value");
1295 if (!strcmp(value, "not-supported")) {
1296 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1297 /* no property expected in this case */
1298 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001299 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001300 goto error;
1301 }
1302
Radek Krejci5b917642015-07-02 09:03:13 +02001303 /* and neither any other deviate statement is expected,
1304 * not-supported deviation must be the only deviation of the target
1305 */
1306 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001307 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1308 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001309 goto error;
1310 }
1311
1312
Radek Krejcieb00f512015-07-01 16:44:58 +02001313 /* remove target node */
Radek Krejcifa0b5e02016-02-04 13:57:03 +01001314 lys_node_free(dev->target, NULL);
Radek Krejci5b917642015-07-02 09:03:13 +02001315 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001316
Radek Krejci5b917642015-07-02 09:03:13 +02001317 dev->deviate_size = 1;
1318 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001319 } else if (!strcmp(value, "add")) {
1320 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1321 } else if (!strcmp(value, "replace")) {
1322 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1323 } else if (!strcmp(value, "delete")) {
1324 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1325 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001326 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001327 goto error;
1328 }
1329 d = &dev->deviate[dev->deviate_size];
1330
1331 /* process deviation properties */
1332 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001333 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1334 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001335 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001336 continue;
1337 }
1338
Radek Krejcieb00f512015-07-01 16:44:58 +02001339 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001340 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001341 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001342 goto error;
1343 }
1344
1345 /* for we deviate from RFC 6020 and allow config property even it is/is not
1346 * specified in the target explicitly since config property inherits. So we expect
1347 * that config is specified in every node. But for delete, we check that the value
1348 * is the same as here in deviation
1349 */
1350 GETVAL(value, child, "value");
1351 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001352 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001353 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001354 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001355 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001356 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 goto error;
1358 }
1359
1360 if (d->mod == LY_DEVIATE_DEL) {
1361 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001362 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001363 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1364 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 goto error;
1366 }
1367 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001368 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001369
1370 /* ... and inherit config value from the target's parent */
1371 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001372 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 } else {
1374 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001375 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001376 }
1377 } else { /* add and replace are the same in this case */
1378 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001379 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001380
1381 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001382 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001383 }
1384 } else if (!strcmp(child->name, "default")) {
1385 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001386 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001387 goto error;
1388 }
1389 GETVAL(value, child, "value");
1390 d->dflt = lydict_insert(module->ctx, value, 0);
1391
Radek Krejci76512572015-08-04 09:47:08 +02001392 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001393 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001394
1395 if (d->mod == LY_DEVIATE_ADD) {
1396 /* check that there is no current value */
1397 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001398 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1399 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001400 goto error;
1401 }
1402 }
1403
Michal Vasko1e62a092015-12-01 12:27:20 +01001404 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE,
1405 (const struct lys_node **)&node);
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001406 if (rc) {
1407 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1408 goto error;
1409 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001410 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001411 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001412 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1413 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001414 goto error;
1415 }
1416 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001417 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 if (!choice->dflt) {
1419 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001420 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001421 goto error;
1422 }
1423 }
Radek Krejci76512572015-08-04 09:47:08 +02001424 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001425 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001426
1427 if (d->mod == LY_DEVIATE_ADD) {
1428 /* check that there is no current value */
1429 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001430 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1431 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001432 goto error;
1433 }
1434 }
1435
1436 if (d->mod == LY_DEVIATE_DEL) {
1437 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001438 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1439 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001440 goto error;
1441 }
1442 /* remove value */
1443 lydict_remove(leaf->module->ctx, leaf->dflt);
1444 leaf->dflt = NULL;
1445 } else { /* add (already checked) and replace */
1446 /* remove value */
1447 lydict_remove(leaf->module->ctx, leaf->dflt);
1448
1449 /* set new value */
1450 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1451 }
1452 } else {
1453 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001454 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1455 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001456 goto error;
1457 }
1458 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001459 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001460 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001461 goto error;
1462 }
1463
1464 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001465 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001466 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1467 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001468 goto error;
1469 }
1470
1471 GETVAL(value, child, "value");
1472 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001473 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001474 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001475 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001476 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001477 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 goto error;
1479 }
1480
1481 if (d->mod == LY_DEVIATE_ADD) {
1482 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001483 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001484 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1485 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 goto error;
1487 }
1488 }
1489
1490 if (d->mod == LY_DEVIATE_DEL) {
1491 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001492 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001493 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1494 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001495 goto error;
1496 }
1497 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001498 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001499 } else { /* add (already checked) and replace */
1500 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001501 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001502
1503 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001504 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 }
1506 } else if (!strcmp(child->name, "min-elements")) {
1507 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001508 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001509 goto error;
1510 }
1511 f_min = 1;
1512
1513 if (deviate_minmax(dev->target, child, d, 0)) {
1514 goto error;
1515 }
1516 } else if (!strcmp(child->name, "max-elements")) {
1517 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001518 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 goto error;
1520 }
1521
1522 if (deviate_minmax(dev->target, child, d, 1)) {
1523 goto error;
1524 }
1525 } else if (!strcmp(child->name, "must")) {
1526 c_must++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001527 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001528 continue;
1529 } else if (!strcmp(child->name, "type")) {
1530 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001531 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 goto error;
1533 }
1534
1535 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001536 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001537 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001538 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001539 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001540 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001541 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1542 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001543 goto error;
1544 }
1545
1546 if (d->mod == LY_DEVIATE_ADD) {
1547 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001548 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1549 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 goto error;
1551 } else if (d->mod == LY_DEVIATE_DEL) {
1552 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001553 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1554 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 goto error;
1556 }
1557
1558 /* replace */
1559 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001560 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001561
1562 /* ... and replace it with the value specified in deviation */
Michal Vasko88c29542015-11-27 14:57:53 +01001563 /* HACK for unres */
1564 t->der = (struct lys_tpdf *)child;
1565 if (unres_schema_add_node(module, unres, t, UNRES_TYPE_DER, dev->target, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 goto error;
1567 }
1568 d->type = t;
1569 } else if (!strcmp(child->name, "unique")) {
1570 c_uniq++;
Michal Vasko345da0a2015-12-02 10:35:55 +01001571 /* skip lyxml_free() at the end of the loop, this node will be processed later */
Radek Krejcieb00f512015-07-01 16:44:58 +02001572 continue;
1573 } else if (!strcmp(child->name, "units")) {
1574 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001575 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 goto error;
1577 }
1578
1579 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001580 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001581 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001582 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001583 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001584 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001585 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1586 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
1589
1590 /* get units value */
1591 GETVAL(value, child, "name");
1592 d->units = lydict_insert(module->ctx, value, 0);
1593
1594 /* apply to target */
1595 if (d->mod == LY_DEVIATE_ADD) {
1596 /* check that there is no current value */
1597 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001598 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1599 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001600 goto error;
1601 }
1602 }
1603
1604 if (d->mod == LY_DEVIATE_DEL) {
1605 /* check values */
1606 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001607 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1608 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 goto error;
1610 }
1611 /* remove current units value of the target */
1612 lydict_remove(dev->target->module->ctx, *stritem);
1613 } else { /* add (already checked) and replace */
1614 /* remove current units value of the target ... */
1615 lydict_remove(dev->target->module->ctx, *stritem);
1616
1617 /* ... and replace it with the value specified in deviation */
1618 *stritem = lydict_insert(module->ctx, value, 0);
1619 }
1620 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001621 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 goto error;
1623 }
1624
Michal Vasko88c29542015-11-27 14:57:53 +01001625 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 }
1627
1628 if (c_must) {
1629 /* check target node type */
1630 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001631 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001632 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1633 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001634 break;
Radek Krejci76512572015-08-04 09:47:08 +02001635 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001636 trg_must = &((struct lys_node_container *)dev->target)->must;
1637 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 break;
Radek Krejci76512572015-08-04 09:47:08 +02001639 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001640 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1641 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001642 break;
Radek Krejci76512572015-08-04 09:47:08 +02001643 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001644 trg_must = &((struct lys_node_list *)dev->target)->must;
1645 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001646 break;
Radek Krejci76512572015-08-04 09:47:08 +02001647 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001648 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1649 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 break;
1651 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001652 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1653 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001654 goto error;
1655 }
1656
1657 if (d->mod == LY_DEVIATE_RPL) {
1658 /* remove target's musts and allocate new array for it */
1659 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001660 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1661 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001662 goto error;
1663 }
1664
1665 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001666 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 }
1668 free(*trg_must);
1669 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1670 d->must_size = c_must;
1671 *trg_must_size = 0;
1672 } else if (d->mod == LY_DEVIATE_ADD) {
1673 /* reallocate the must array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001674 d->must = ly_realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
Radek Krejcieb00f512015-07-01 16:44:58 +02001675 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001676 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001677 d->must_size = c_must;
1678 } else { /* LY_DEVIATE_DEL */
1679 d->must = calloc(c_must, sizeof *d->must);
1680 }
Michal Vasko253035f2015-12-17 16:58:13 +01001681 if (!d->must) {
1682 LOGMEM;
1683 goto error;
1684 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001685 }
1686 if (c_uniq) {
1687 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001688 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001689 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1690 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001691 goto error;
1692 }
1693
Radek Krejcib8048692015-08-05 13:36:34 +02001694 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001695 if (d->mod == LY_DEVIATE_RPL) {
1696 /* remove target's unique and allocate new array for it */
1697 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001698 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1699 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 goto error;
1701 }
1702
1703 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001704 for (j = 0; j < list->unique[i].expr_size; j++) {
1705 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1706 }
1707 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001708 }
1709 free(list->unique);
1710 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1711 d->unique_size = c_uniq;
1712 list->unique_size = 0;
1713 } else if (d->mod == LY_DEVIATE_ADD) {
1714 /* reallocate the unique array of the target */
Michal Vasko253035f2015-12-17 16:58:13 +01001715 d->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 list->unique = d->unique;
1717 d->unique = &list->unique[list->unique_size];
1718 d->unique_size = c_uniq;
1719 } else { /* LY_DEVIATE_DEL */
1720 d->unique = calloc(c_uniq, sizeof *d->unique);
1721 }
Michal Vasko253035f2015-12-17 16:58:13 +01001722 if (!d->unique) {
1723 LOGMEM;
1724 goto error;
1725 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001726 }
1727
1728 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001729 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001730 if (!strcmp(child->name, "must")) {
1731 if (d->mod == LY_DEVIATE_DEL) {
1732 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1733 goto error;
1734 }
1735
1736 /* find must to delete, we are ok with just matching conditions */
1737 for (i = 0; i < *trg_must_size; i++) {
1738 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1739 /* we have a match, free the must structure ... */
Michal Vasko5e7d9ca2015-10-23 10:37:28 +02001740 lys_restr_free(dev->target->module->ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 /* ... and maintain the array */
1742 (*trg_must_size)--;
1743 if (i != *trg_must_size) {
1744 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1745 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1746 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1747 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1748 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1749 }
1750 if (!(*trg_must_size)) {
1751 free(*trg_must);
1752 *trg_must = NULL;
1753 } else {
1754 (*trg_must)[*trg_must_size].expr = NULL;
1755 (*trg_must)[*trg_must_size].dsc = NULL;
1756 (*trg_must)[*trg_must_size].ref = NULL;
1757 (*trg_must)[*trg_must_size].eapptag = NULL;
1758 (*trg_must)[*trg_must_size].emsg = NULL;
1759 }
1760
1761 i = -1; /* set match flag */
1762 break;
1763 }
1764 }
1765 d->must_size++;
1766 if (i != -1) {
1767 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001768 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1769 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 goto error;
1771 }
1772 } else { /* replace or add */
1773 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1774 goto error;
1775 }
1776 (*trg_must_size)++;
1777 }
1778 } else if (!strcmp(child->name, "unique")) {
1779 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci581ce772015-11-10 17:22:40 +01001780 if (fill_yin_unique(module, dev->target, child, &d->unique[d->unique_size], NULL)) {
1781 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 goto error;
1783 }
1784
1785 /* find unique structures to delete */
1786 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001787 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 continue;
1789 }
1790
Radek Krejci581ce772015-11-10 17:22:40 +01001791 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1792 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001793 break;
1794 }
1795 }
1796
Radek Krejci581ce772015-11-10 17:22:40 +01001797 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001799 for (j = 0; j < list->unique[i].expr_size; j++) {
1800 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1801 }
1802 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001803 /* ... and maintain the array */
1804 list->unique_size--;
1805 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001806 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1807 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001808 }
1809
1810 if (!list->unique_size) {
1811 free(list->unique);
1812 list->unique = NULL;
1813 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001814 list->unique[list->unique_size].expr_size = 0;
1815 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 }
1817
1818 i = -1; /* set match flag */
1819 break;
1820 }
1821 }
1822
1823 d->unique_size++;
1824 if (i != -1) {
1825 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001826 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1827 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 goto error;
1829 }
1830 } else { /* replace or add */
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001831 i = fill_yin_unique(module, dev->target, child, &list->unique[list->unique_size], NULL);
1832 list->unique_size++;
1833 if (i) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001834 goto error;
1835 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 }
1837 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001838 }
Radek Krejci5b917642015-07-02 09:03:13 +02001839
1840 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001841 }
1842
Radek Krejcieb00f512015-07-01 16:44:58 +02001843 return EXIT_SUCCESS;
1844
1845error:
1846
1847 if (dev->deviate) {
1848 for (i = 0; i < dev->deviate_size; i++) {
1849 lydict_remove(module->ctx, dev->deviate[i].dflt);
1850 lydict_remove(module->ctx, dev->deviate[i].units);
1851
1852 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1853 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001854 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 }
1856 free(dev->deviate[i].must);
1857
1858 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001859 for (k = 0; k < dev->deviate[i].unique[i].expr_size; k++) {
1860 lydict_remove(module->ctx, dev->deviate[i].unique[j].expr[k]);
1861 }
1862 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001863 }
1864 free(dev->deviate[i].unique);
1865 }
1866 }
1867 free(dev->deviate);
1868 }
1869
1870 return EXIT_FAILURE;
1871}
1872
Michal Vasko0d343d12015-08-24 14:57:36 +02001873/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001874static int
Radek Krejcib8048692015-08-05 13:36:34 +02001875fill_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 +02001876 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001877{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001878 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001879 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001880 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001881 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001882
Michal Vasko591e0b22015-08-13 13:53:43 +02001883 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001884 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001885 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001886 if (!aug->target_name) {
1887 goto error;
1888 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001889 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001890
Michal Vasko1d87a922015-08-21 12:57:16 +02001891 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001892 goto error;
1893 }
1894
1895 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001896 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1897 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01001898 lyxml_free(module->ctx, child);
Radek Krejci0d70c372015-07-02 16:23:10 +02001899 continue;
1900 }
1901
Radek Krejci3cf9e222015-06-18 11:37:50 +02001902 if (!strcmp(child->name, "if-feature")) {
1903 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001904 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001905 } else if (!strcmp(child->name, "when")) {
1906 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001907 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001908 goto error;
1909 }
1910
1911 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001912 if (!aug->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01001913 lyxml_free(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001914 goto error;
1915 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001916 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001917 goto error;
1918 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001919 lyxml_free(module->ctx, child);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001920 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001921
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001922 /* check allowed data sub-statements */
1923 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001924 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001925 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001926 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001927 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001928 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001929 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001930 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001931 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001933 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001934 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001935 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001936 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001937 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001938 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001939 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001940 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001941 goto error;
1942 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001943
Radek Krejci1d82ef62015-08-07 14:44:40 +02001944 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001945 goto error;
1946 }
1947
1948 /* check for mandatory nodes - if the target node is in another module
1949 * the added nodes cannot be mandatory
1950 */
Radek Krejcic6556022016-01-27 15:16:45 +01001951 if ((!parent || (parent->nodetype != LYS_USES)) && lyp_check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001952 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001953 goto error;
1954 }
1955
Radek Krejci1d82ef62015-08-07 14:44:40 +02001956 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01001957 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001958 }
1959
1960 if (c) {
1961 aug->features = calloc(c, sizeof *aug->features);
Michal Vasko253035f2015-12-17 16:58:13 +01001962 if (!aug->features) {
1963 LOGMEM;
1964 goto error;
1965 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001966 }
1967
1968 LY_TREE_FOR_SAFE(yin->child, next, child) {
1969 if (!strcmp(child->name, "if-feature")) {
1970 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001971 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001972 goto error;
1973 }
Radek Krejcicf509982015-12-15 09:22:44 +01001974 /* hack - store pointer to the parent node for later status check */
1975 aug->features[aug->features_size] = (struct lys_feature *)aug;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001976 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02001977 LOGLINE(child));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01001978 aug->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02001979 lydict_remove(module->ctx, value);
1980 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001981 goto error;
1982 }
Michal Vasko345da0a2015-12-02 10:35:55 +01001983 lyxml_free(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001984 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001985 }
1986
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001987 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02001988 * connected to the tree and adjusted (if possible right now).
1989 * However, if this is augment in a uses, it gets resolved
1990 * when the uses does and cannot be resolved now for sure
1991 * (the grouping was not yet copied into uses).
1992 */
1993 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02001994 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02001995 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
1996 goto error;
1997 }
Michal Vasko49291b32015-08-06 09:49:41 +02001998 }
Radek Krejci106efc02015-06-10 14:36:27 +02001999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002000 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002001
2002error:
2003
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002004 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002005}
2006
Michal Vasko0d343d12015-08-24 14:57:36 +02002007/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002008static int
Michal Vasko0d204592015-10-07 09:50:04 +02002009fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002010{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002011 struct lyxml_elem *sub, *next;
2012 const char *value;
2013 char *endptr;
2014 int f_mand = 0, f_min = 0, f_max = 0;
2015 int c_must = 0;
2016 int r;
2017 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002018
Radek Krejci76512572015-08-04 09:47:08 +02002019 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002020 goto error;
2021 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002022
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002023 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002024 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002025 if (!rfn->target_name) {
2026 goto error;
2027 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002030 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2031 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002032 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002033 continue;
2034 }
2035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002036 /* limited applicability */
2037 if (!strcmp(sub->name, "default")) {
2038 /* leaf or choice */
2039 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002040 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002041 goto error;
2042 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 /* check possibility of statements combination */
2045 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002046 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002047 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002048 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 goto error;
2050 }
2051 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002052 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002053 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 GETVAL(value, sub, "value");
2056 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2057 } else if (!strcmp(sub->name, "mandatory")) {
2058 /* leaf, choice or anyxml */
2059 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002060 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002061 goto error;
2062 }
2063 /* just checking the flags in leaf is not sufficient, we would allow
2064 * multiple mandatory statements with the "false" value
2065 */
2066 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 /* check possibility of statements combination */
2069 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002070 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002072 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002073 goto error;
2074 }
2075 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002076 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002077 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002079 GETVAL(value, sub, "value");
2080 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002081 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002082 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002083 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002084 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002085 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 goto error;
2087 }
2088 } else if (!strcmp(sub->name, "min-elements")) {
2089 /* list or leaf-list */
2090 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002091 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 goto error;
2093 }
2094 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 /* check possibility of statements combination */
2097 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002098 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002100 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 goto error;
2102 }
2103 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002104 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 GETVAL(value, sub, "value");
2108 while (isspace(value[0])) {
2109 value++;
2110 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 /* convert it to uint32_t */
2113 errno = 0;
2114 endptr = NULL;
2115 val = strtoul(value, &endptr, 10);
2116 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002117 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 goto error;
2119 }
2120 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 /* magic - bit 3 in flags means min set */
2123 rfn->flags |= 0x04;
2124 } else if (!strcmp(sub->name, "max-elements")) {
2125 /* list or leaf-list */
2126 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002127 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 goto error;
2129 }
2130 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002132 /* check possibility of statements combination */
2133 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002134 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002136 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 goto error;
2138 }
2139 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002140 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 GETVAL(value, sub, "value");
2144 while (isspace(value[0])) {
2145 value++;
2146 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002148 /* convert it to uint32_t */
2149 errno = 0;
2150 endptr = NULL;
2151 val = strtoul(value, &endptr, 10);
2152 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002153 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 goto error;
2155 }
2156 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 /* magic - bit 4 in flags means min set */
2159 rfn->flags |= 0x08;
2160 } else if (!strcmp(sub->name, "presence")) {
2161 /* container */
2162 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002163 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 goto error;
2165 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 /* check possibility of statements combination */
2168 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002169 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002171 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 goto error;
2173 }
2174 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002175 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 GETVAL(value, sub, "value");
2179 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2180 } else if (!strcmp(sub->name, "must")) {
2181 /* leaf-list, list, container or anyxml */
2182 /* check possibility of statements combination */
2183 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002184 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002186 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 goto error;
2188 }
2189 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002190 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002194 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002197 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 goto error;
2199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002200
Michal Vasko345da0a2015-12-02 10:35:55 +01002201 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 /* process nodes with cardinality of 0..n */
2205 if (c_must) {
2206 rfn->must = calloc(c_must, sizeof *rfn->must);
Michal Vasko253035f2015-12-17 16:58:13 +01002207 if (!rfn->must) {
2208 LOGMEM;
2209 goto error;
2210 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 }
Radek Krejci73adb602015-07-02 18:07:40 +02002212 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002213 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size]);
2214 rfn->must_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02002215 if (r) {
2216 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 }
Michal Vasko0d204592015-10-07 09:50:04 +02002218 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002219 goto error;
2220 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002224
2225error:
2226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002228}
2229
Michal Vasko0d343d12015-08-24 14:57:36 +02002230/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231static int
Radek Krejcib8048692015-08-05 13:36:34 +02002232fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002233{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 struct lyxml_elem *child;
2235 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002236 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002239 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2240 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002241 continue;
2242 }
2243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 if (!strcmp(child->name, "prefix")) {
2245 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01002246 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 goto error;
2248 }
2249 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2250 } else if (!strcmp(child->name, "revision-date")) {
2251 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002252 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 goto error;
2254 }
2255 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002256 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 goto error;
2258 }
2259 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2260 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002261 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 goto error;
2263 }
2264 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 /* check mandatory information */
2267 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002268 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 goto error;
2270 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002273
2274 /* check for circular import, store it if passed */
2275 if (!module->ctx->models.parsing) {
2276 count = 0;
2277 } else {
2278 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2279 if (value == module->ctx->models.parsing[count]) {
2280 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2281 goto error;
2282 }
2283 }
2284 }
2285 ++count;
2286 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002287 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2288 if (!module->ctx->models.parsing) {
2289 LOGMEM;
2290 goto error;
2291 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002292 module->ctx->models.parsing[count - 1] = value;
2293 module->ctx->models.parsing[count] = NULL;
2294
2295 /* try to load the module */
Michal Vasko1e62a092015-12-01 12:27:20 +01002296 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 if (!imp->module) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002298 /* whether to use a user callback is decided in the function */
2299 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002300 }
2301
2302 /* remove the new module name now that its parsing is finished (even if failed) */
2303 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2304 LOGINT;
2305 }
2306 --count;
2307 if (count) {
2308 module->ctx->models.parsing[count] = NULL;
2309 } else {
2310 free(module->ctx->models.parsing);
2311 module->ctx->models.parsing = NULL;
2312 }
2313
2314 /* check the result */
2315 if (!imp->module) {
2316 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2317 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2318 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002322
2323error:
2324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002326}
2327
Michal Vasko0d343d12015-08-24 14:57:36 +02002328/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329static int
Radek Krejcic071c542016-01-27 14:57:51 +01002330fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02002331{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002332 struct lyxml_elem *child;
2333 const char *value;
Michal Vasko99b0aad2015-12-01 12:28:51 +01002334 char *module_data;
2335 void (*module_data_free)(char *module_data) = NULL;
2336 LYS_INFORMAT format = LYS_IN_UNKNOWN;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002337 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002339 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002340 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2341 /* garbage */
2342 continue;
2343 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 if (!strcmp(child->name, "revision-date")) {
2345 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002346 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 goto error;
2348 }
2349 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01002350 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 goto error;
2352 }
2353 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2354 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002355 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 goto error;
2357 }
2358 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002361
2362 /* check for circular include, store it if passed */
2363 if (!module->ctx->models.parsing) {
2364 count = 0;
2365 } else {
2366 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2367 if (value == module->ctx->models.parsing[count]) {
2368 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2369 goto error;
2370 }
2371 }
2372 }
2373 ++count;
2374 module->ctx->models.parsing =
Michal Vasko253035f2015-12-17 16:58:13 +01002375 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2376 if (!module->ctx->models.parsing) {
2377 LOGMEM;
2378 goto error;
2379 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002380 module->ctx->models.parsing[count - 1] = value;
2381 module->ctx->models.parsing[count] = NULL;
2382
2383 /* try to load the submodule */
Michal Vasko1e62a092015-12-01 12:27:20 +01002384 inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 if (!inc->submodule) {
Michal Vasko99b0aad2015-12-01 12:28:51 +01002386 if (module->ctx->module_clb) {
2387 module_data = module->ctx->module_clb(value, inc->rev[0] ? inc->rev : NULL, module->ctx->module_clb_data,
2388 &format, &module_data_free);
2389 if (module_data) {
Radek Krejcic071c542016-01-27 14:57:51 +01002390 inc->submodule = lys_submodule_parse(module, module_data, format, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002391 if (module_data_free) {
2392 module_data_free(module_data);
2393 } else {
2394 free(module_data);
2395 }
2396 } else {
2397 LOGERR(LY_EVALID, "User module retrieval callback failed!");
2398 }
2399 } else {
2400 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value,
Radek Krejcic071c542016-01-27 14:57:51 +01002401 inc->rev[0] ? inc->rev : NULL, unres);
Michal Vasko99b0aad2015-12-01 12:28:51 +01002402 }
Michal Vasko1b882eb2015-10-22 11:43:14 +02002403 }
2404
2405 /* remove the new submodule name now that its parsing is finished (even if failed) */
2406 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2407 LOGINT;
2408 }
2409 --count;
2410 if (count) {
2411 module->ctx->models.parsing[count] = NULL;
2412 } else {
2413 free(module->ctx->models.parsing);
2414 module->ctx->models.parsing = NULL;
2415 }
2416
2417 /* check the result */
2418 if (!inc->submodule) {
2419 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2420 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2421 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002422 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002425
2426error:
2427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002428 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002429}
2430
Michal Vasko0d343d12015-08-24 14:57:36 +02002431/* logs directly
2432 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002433 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002434 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002435 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002436 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437static int
Radek Krejcib8048692015-08-05 13:36:34 +02002438read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002439 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002440{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 const char *value;
2442 struct lyxml_elem *sub, *next;
2443 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002445 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002447 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002449 if (opt & OPT_IDENT) {
2450 GETVAL(value, xmlnode, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01002451 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 goto error;
2453 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002454 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002456
Radek Krejci6764bb32015-07-03 15:16:04 +02002457 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002458 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002460 }
2461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 /* process local parameters */
2463 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002464 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002465 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002466 lyxml_free(ctx, sub);
Radek Krejci6764bb32015-07-03 15:16:04 +02002467 continue;
2468 }
2469 if (strcmp(sub->ns->value, LY_NSYIN)) {
2470 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002471 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002472 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002473 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002474 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002475 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002476 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002477 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002478 goto error;
2479 }
2480 }
2481
2482 /* else garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002483 lyxml_free(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002484 continue;
2485 }
2486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002488 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002489 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 goto error;
2491 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002492 node->dsc = read_yin_subnode(ctx, sub, "text");
2493 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002494 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 }
2496 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002497 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002498 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 goto error;
2500 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002501 node->ref = read_yin_subnode(ctx, sub, "text");
2502 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002503 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 }
2505 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002506 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002507 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002508 goto error;
2509 }
2510 GETVAL(value, sub, "value");
2511 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002512 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002514 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002516 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002518 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002519 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 }
2521 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002522 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002523 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002524 goto error;
2525 }
2526 GETVAL(value, sub, "value");
2527 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002528 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002530 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002532 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002533 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534 }
2535 } else {
Michal Vasko345da0a2015-12-02 10:35:55 +01002536 /* skip the lyxml_free */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 continue;
2538 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002539 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002541
Radek Krejci1d82ef62015-08-07 14:44:40 +02002542 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002543 /* get config flag from parent */
2544 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002545 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 } else {
2547 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002548 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 }
2550 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002552 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002553
2554error:
2555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002556 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002557}
2558
Michal Vasko0d343d12015-08-24 14:57:36 +02002559/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002560static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002561read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002562{
Radek Krejci76512572015-08-04 09:47:08 +02002563 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002564 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002565 const char *value;
2566
2567 retval = calloc(1, sizeof *retval);
Michal Vasko253035f2015-12-17 16:58:13 +01002568 if (!retval) {
2569 LOGMEM;
2570 return NULL;
2571 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002572
2573 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002574 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002575 if (!retval->cond) {
2576 goto error;
2577 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002578
Radek Krejci73adb602015-07-02 18:07:40 +02002579 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002580 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2581 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002582 continue;
2583 }
2584
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002585 if (!strcmp(child->name, "description")) {
2586 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002587 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002588 goto error;
2589 }
2590 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2591 if (!retval->dsc) {
2592 goto error;
2593 }
2594 } else if (!strcmp(child->name, "reference")) {
2595 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002596 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002597 goto error;
2598 }
2599 retval->ref = read_yin_subnode(module->ctx, child, "text");
2600 if (!retval->ref) {
2601 goto error;
2602 }
2603 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002604 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002605 goto error;
2606 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002607 }
2608
2609 return retval;
2610
2611error:
2612
Michal Vasko0308dd62015-10-07 09:14:40 +02002613 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002614 return NULL;
2615}
2616
Michal Vasko0d343d12015-08-24 14:57:36 +02002617/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002618static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002619read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2620 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002621{
Michal Vasko29fc0182015-08-24 15:02:39 +02002622 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 struct lys_node_case *cs;
2624 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002625 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002626 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002627
Radek Krejcie867c852015-08-27 09:52:34 +02002628 /* init */
2629 memset(&root, 0, sizeof root);
2630
Radek Krejci1d82ef62015-08-07 14:44:40 +02002631 cs = calloc(1, sizeof *cs);
Michal Vasko253035f2015-12-17 16:58:13 +01002632 if (!cs) {
2633 LOGMEM;
2634 return NULL;
2635 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002636 cs->nodetype = LYS_CASE;
2637 cs->prev = (struct lys_node *)cs;
2638 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002639
Radek Krejci6a113852015-07-03 16:04:20 +02002640 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002641 goto error;
2642 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002643
Radek Krejcia9544502015-08-14 08:24:29 +02002644 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2645
Michal Vasko3a0043f2015-08-12 12:11:30 +02002646 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002647 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002648 goto error;
2649 }
2650
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 /* process choice's specific children */
2652 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002653 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2654 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002655 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002656 continue;
2657 }
2658
Michal Vasko29fc0182015-08-24 15:02:39 +02002659 if (!strcmp(sub->name, "container") ||
2660 !strcmp(sub->name, "leaf-list") ||
2661 !strcmp(sub->name, "leaf") ||
2662 !strcmp(sub->name, "list") ||
2663 !strcmp(sub->name, "uses") ||
2664 !strcmp(sub->name, "choice") ||
2665 !strcmp(sub->name, "anyxml")) {
2666
Michal Vaskof3930de2015-10-22 12:03:59 +02002667 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002668 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002669 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002670 c_ftrs++;
Michal Vasko345da0a2015-12-02 10:35:55 +01002671 /* skip lyxml_free() at the end of the loop, sub is processed later */
Michal Vasko29fc0182015-08-24 15:02:39 +02002672 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002673 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002674 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002675 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002676 goto error;
2677 }
2678
Radek Krejci1d82ef62015-08-07 14:44:40 +02002679 cs->when = read_yin_when(module, sub);
2680 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002681 goto error;
2682 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002683 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002684 goto error;
2685 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002686
Michal Vasko345da0a2015-12-02 10:35:55 +01002687 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002689 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002693
Radek Krejci3cf9e222015-06-18 11:37:50 +02002694 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002695 cs->features = calloc(c_ftrs, sizeof *cs->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002696 if (!cs->features) {
2697 LOGMEM;
2698 goto error;
2699 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002700 }
Radek Krejci73adb602015-07-02 18:07:40 +02002701 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002702 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002703 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002704 goto error;
2705 }
Radek Krejcicf509982015-12-15 09:22:44 +01002706 /* hack - store pointer to the parent node for later status check */
2707 cs->features[cs->features_size] = (struct lys_feature *)cs;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002708 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002709 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002710 cs->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002711 lydict_remove(module->ctx, value);
2712 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002713 goto error;
2714 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 }
Radek Krejcib388c152015-06-04 17:03:03 +02002716
Michal Vasko29fc0182015-08-24 15:02:39 +02002717 /* last part - process data nodes */
2718 LY_TREE_FOR_SAFE(root.child, next, sub) {
2719 if (!strcmp(sub->name, "container")) {
2720 node = read_yin_container(module, retval, sub, resolve, unres);
2721 } else if (!strcmp(sub->name, "leaf-list")) {
2722 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2723 } else if (!strcmp(sub->name, "leaf")) {
2724 node = read_yin_leaf(module, retval, sub, resolve, unres);
2725 } else if (!strcmp(sub->name, "list")) {
2726 node = read_yin_list(module, retval, sub, resolve, unres);
2727 } else if (!strcmp(sub->name, "choice")) {
2728 node = read_yin_choice(module, retval, sub, resolve, unres);
2729 } else if (!strcmp(sub->name, "uses")) {
2730 node = read_yin_uses(module, retval, sub, resolve, unres);
2731 } else if (!strcmp(sub->name, "anyxml")) {
2732 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2733 }
2734 if (!node) {
2735 goto error;
2736 }
2737
Michal Vasko345da0a2015-12-02 10:35:55 +01002738 lyxml_free(module->ctx, sub);
Michal Vasko29fc0182015-08-24 15:02:39 +02002739 }
2740
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002742
2743error:
2744
Michal Vasko29fc0182015-08-24 15:02:39 +02002745 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002746 lyxml_free(module->ctx, root.child);
Michal Vasko29fc0182015-08-24 15:02:39 +02002747 }
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002748 lys_node_free(retval, NULL);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002750 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002751}
2752
Michal Vasko0d343d12015-08-24 14:57:36 +02002753/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002754static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002755read_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 +02002756{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 struct lyxml_elem *sub, *next;
2758 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002759 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002760 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002761 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002762 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 choice = calloc(1, sizeof *choice);
Michal Vasko253035f2015-12-17 16:58:13 +01002765 if (!choice) {
2766 LOGMEM;
2767 return NULL;
2768 }
Radek Krejci76512572015-08-04 09:47:08 +02002769 choice->nodetype = LYS_CHOICE;
2770 choice->prev = (struct lys_node *)choice;
2771 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002772
Michal Vaskoe0c59842015-09-24 13:52:20 +02002773 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2774 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 goto error;
2776 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002777
Radek Krejcia9544502015-08-14 08:24:29 +02002778 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2779
Michal Vasko3a0043f2015-08-12 12:11:30 +02002780 /* insert the node into the schema tree */
Radek Krejcic071c542016-01-27 14:57:51 +01002781 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002782 goto error;
2783 }
2784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002785 /* process choice's specific children */
2786 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002787 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2788 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002789 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002790 continue;
2791 }
2792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002794 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 goto error;
2796 }
2797 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002798 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 goto error;
2800 }
2801 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002802 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 goto error;
2804 }
2805 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002806 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 goto error;
2808 }
2809 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002810 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002811 goto error;
2812 }
2813 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002814 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002815 goto error;
2816 }
2817 } else if (!strcmp(sub->name, "default")) {
2818 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002819 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820 goto error;
2821 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002822 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002823 } else if (!strcmp(sub->name, "mandatory")) {
2824 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002825 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 goto error;
2827 }
2828 /* just checking the flags in leaf is not sufficient, we would allow
2829 * multiple mandatory statements with the "false" value
2830 */
2831 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 GETVAL(value, sub, "value");
2834 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002835 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002836 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002837 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002838 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002839 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 goto error;
2841 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002842 } else if (!strcmp(sub->name, "when")) {
2843 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002844 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002845 goto error;
2846 }
2847
2848 choice->when = read_yin_when(module, sub);
2849 if (!choice->when) {
2850 goto error;
2851 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002852 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002853 goto error;
2854 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002855 } else if (!strcmp(sub->name, "if-feature")) {
2856 c_ftrs++;
2857
Michal Vasko345da0a2015-12-02 10:35:55 +01002858 /* skip lyxml_free() at the end of the loop, the sub node is processed later */
Radek Krejci3cf9e222015-06-18 11:37:50 +02002859 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002861 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002863 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002864
Radek Krejci1d82ef62015-08-07 14:44:40 +02002865 node = NULL;
Michal Vasko345da0a2015-12-02 10:35:55 +01002866 lyxml_free(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002868
Radek Krejci3cf9e222015-06-18 11:37:50 +02002869 if (c_ftrs) {
2870 choice->features = calloc(c_ftrs, sizeof *choice->features);
Michal Vasko253035f2015-12-17 16:58:13 +01002871 if (!choice->features) {
2872 LOGMEM;
2873 goto error;
2874 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002875 }
2876
Radek Krejci73adb602015-07-02 18:07:40 +02002877 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002878 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002879 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002880 goto error;
2881 }
Radek Krejcicf509982015-12-15 09:22:44 +01002882 /* hack - store pointer to the parent node for later status check */
2883 choice->features[choice->features_size] = (struct lys_feature *)choice;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002884 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02002885 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01002886 choice->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02002887 lydict_remove(module->ctx, value);
2888 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002889 goto error;
2890 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002891 }
2892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002894 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002895 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2897 goto error;
2898 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002900 /* link default with the case */
2901 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002902 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002903 goto error;
2904 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002905 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002908
2909error:
2910
Radek Krejcifa0b5e02016-02-04 13:57:03 +01002911 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002914}
2915
Michal Vasko0d343d12015-08-24 14:57:36 +02002916/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002917static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002918read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002919 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002920{
Radek Krejci76512572015-08-04 09:47:08 +02002921 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002922 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 struct lyxml_elem *sub, *next;
2924 const char *value;
2925 int r;
2926 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002927 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 anyxml = calloc(1, sizeof *anyxml);
Michal Vasko253035f2015-12-17 16:58:13 +01002930 if (!anyxml) {
2931 LOGMEM;
2932 return NULL;
2933 }
Radek Krejci76512572015-08-04 09:47:08 +02002934 anyxml->nodetype = LYS_ANYXML;
2935 anyxml->prev = (struct lys_node *)anyxml;
2936 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002937
Michal Vaskoe0c59842015-09-24 13:52:20 +02002938 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2939 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002940 goto error;
2941 }
Radek Krejci863c2852015-06-03 15:47:11 +02002942
Radek Krejcia9544502015-08-14 08:24:29 +02002943 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002944
Radek Krejcic071c542016-01-27 14:57:51 +01002945 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002946 goto error;
2947 }
2948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002950 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2951 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01002952 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002953 continue;
2954 }
2955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 if (!strcmp(sub->name, "mandatory")) {
2957 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002958 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 goto error;
2960 }
2961 /* just checking the flags in leaf is not sufficient, we would allow
2962 * multiple mandatory statements with the "false" value
2963 */
2964 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 GETVAL(value, sub, "value");
2967 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002968 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002969 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002970 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002971 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002972 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 goto error;
2974 }
2975 /* else false is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01002976 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002977 } else if (!strcmp(sub->name, "when")) {
2978 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002979 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002980 goto error;
2981 }
2982
2983 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002984 if (!anyxml->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01002985 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002986 goto error;
2987 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002988 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002989 goto error;
2990 }
Michal Vasko345da0a2015-12-02 10:35:55 +01002991 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 } else if (!strcmp(sub->name, "must")) {
2993 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002994 } else if (!strcmp(sub->name, "if-feature")) {
2995 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002998 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 }
3001 }
Radek Krejci863c2852015-06-03 15:47:11 +02003002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003003 /* middle part - process nodes with cardinality of 0..n */
3004 if (c_must) {
3005 anyxml->must = calloc(c_must, sizeof *anyxml->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003006 if (!anyxml->must) {
3007 LOGMEM;
3008 goto error;
3009 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003011 if (c_ftrs) {
3012 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003013 if (!anyxml->features) {
3014 LOGMEM;
3015 goto error;
3016 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003017 }
Radek Krejci863c2852015-06-03 15:47:11 +02003018
Radek Krejci73adb602015-07-02 18:07:40 +02003019 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003021 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size]);
3022 anyxml->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 if (r) {
3024 goto error;
3025 }
Michal Vasko0d204592015-10-07 09:50:04 +02003026 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003027 goto error;
3028 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003029 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003030 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003031 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003032 goto error;
3033 }
Radek Krejcicf509982015-12-15 09:22:44 +01003034 /* hack - store pointer to the parent node for later status check */
3035 anyxml->features[anyxml->features_size] = (struct lys_feature *)anyxml;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003036 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003037 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003038 anyxml->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003039 lydict_remove(module->ctx, value);
3040 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003041 goto error;
3042 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 }
Radek Krejci863c2852015-06-03 15:47:11 +02003045
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003047
3048error:
3049
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003050 lys_node_free(retval, NULL);
Radek Krejci863c2852015-06-03 15:47:11 +02003051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003053}
3054
Michal Vasko0d343d12015-08-24 14:57:36 +02003055/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003056static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003057read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003058 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003059{
Radek Krejci76512572015-08-04 09:47:08 +02003060 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003061 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 struct lyxml_elem *sub, *next;
3063 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003064 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003065 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 leaf = calloc(1, sizeof *leaf);
Michal Vasko253035f2015-12-17 16:58:13 +01003068 if (!leaf) {
3069 LOGMEM;
3070 return NULL;
3071 }
Radek Krejci76512572015-08-04 09:47:08 +02003072 leaf->nodetype = LYS_LEAF;
3073 leaf->prev = (struct lys_node *)leaf;
3074 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003075
Michal Vaskoe0c59842015-09-24 13:52:20 +02003076 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3077 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 goto error;
3079 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003080
Radek Krejcia9544502015-08-14 08:24:29 +02003081 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003082
Radek Krejcic071c542016-01-27 14:57:51 +01003083 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003084 goto error;
3085 }
3086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003088 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3089 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003090 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003091 continue;
3092 }
3093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003095 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003096 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003097 goto error;
3098 }
Michal Vasko88c29542015-11-27 14:57:53 +01003099 /* HACK for unres */
3100 leaf->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003101 leaf->type.parent = (struct lys_tpdf *)leaf;
Michal Vasko88c29542015-11-27 14:57:53 +01003102 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3103 leaf->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 goto error;
3105 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003106 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 } else if (!strcmp(sub->name, "default")) {
3108 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003109 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003110 goto error;
3111 }
3112 GETVAL(value, sub, "value");
3113 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003114 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 } else if (!strcmp(sub->name, "units")) {
3116 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003117 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 goto error;
3119 }
3120 GETVAL(value, sub, "name");
3121 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3122 } else if (!strcmp(sub->name, "mandatory")) {
3123 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003124 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
3127 /* just checking the flags in leaf is not sufficient, we would allow
3128 * multiple mandatory statements with the "false" value
3129 */
3130 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 GETVAL(value, sub, "value");
3133 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003134 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003135 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003136 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003137 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003138 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 goto error;
3140 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003141 } else if (!strcmp(sub->name, "when")) {
3142 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003143 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003144 goto error;
3145 }
3146
3147 leaf->when = read_yin_when(module, sub);
3148 if (!leaf->when) {
3149 goto error;
3150 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003151 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003152 goto error;
3153 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003156 c_must++;
3157 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003158 } else if (!strcmp(sub->name, "if-feature")) {
3159 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003163 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003166
Michal Vasko88c29542015-11-27 14:57:53 +01003167 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003171 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003172 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 goto error;
3174 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003175 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003176 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003177 goto error;
3178 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003181 /* middle part - process nodes with cardinality of 0..n */
3182 if (c_must) {
3183 leaf->must = calloc(c_must, sizeof *leaf->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003184 if (!leaf->must) {
3185 LOGMEM;
3186 goto error;
3187 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003189 if (c_ftrs) {
3190 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003191 if (!leaf->features) {
3192 LOGMEM;
3193 goto error;
3194 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003195 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003196
Radek Krejci73adb602015-07-02 18:07:40 +02003197 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003199 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size]);
3200 leaf->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 if (r) {
3202 goto error;
3203 }
Michal Vasko0d204592015-10-07 09:50:04 +02003204 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003205 goto error;
3206 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003207 } else if (!strcmp(sub->name, "if-feature")) {
3208 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003209 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003210 goto error;
3211 }
Radek Krejcicf509982015-12-15 09:22:44 +01003212 /* hack - store pointer to the parent node for later status check */
3213 leaf->features[leaf->features_size] = (struct lys_feature *)leaf;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003214 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003215 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003216 leaf->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003217 lydict_remove(module->ctx, value);
3218 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003219 goto error;
3220 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003225
3226error:
3227
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003228 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003231}
3232
Michal Vasko0d343d12015-08-24 14:57:36 +02003233/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003234static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003235read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003236 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003237{
Radek Krejci76512572015-08-04 09:47:08 +02003238 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003239 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 struct lyxml_elem *sub, *next;
3241 const char *value;
3242 char *endptr;
3243 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003244 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003245 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003246 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003248 llist = calloc(1, sizeof *llist);
Michal Vasko253035f2015-12-17 16:58:13 +01003249 if (!llist) {
3250 LOGMEM;
3251 return NULL;
3252 }
Radek Krejci76512572015-08-04 09:47:08 +02003253 llist->nodetype = LYS_LEAFLIST;
3254 llist->prev = (struct lys_node *)llist;
3255 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003256
Michal Vaskoe0c59842015-09-24 13:52:20 +02003257 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3258 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 goto error;
3260 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003261
Radek Krejcia9544502015-08-14 08:24:29 +02003262 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003263
Radek Krejcic071c542016-01-27 14:57:51 +01003264 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003265 goto error;
3266 }
3267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003269 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3270 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003271 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003272 continue;
3273 }
3274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 if (!strcmp(sub->name, "type")) {
Radek Krejciad73b6f2016-02-09 15:42:55 +01003276 if (has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003277 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 goto error;
3279 }
Michal Vasko88c29542015-11-27 14:57:53 +01003280 /* HACK for unres */
3281 llist->type.der = (struct lys_tpdf *)sub;
Radek Krejcicf509982015-12-15 09:22:44 +01003282 llist->type.parent = (struct lys_tpdf *)llist;
Michal Vasko88c29542015-11-27 14:57:53 +01003283 if (unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DER, parent, LOGLINE(sub))) {
3284 llist->type.der = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 goto error;
3286 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003287 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 } else if (!strcmp(sub->name, "units")) {
3289 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003290 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 goto error;
3292 }
3293 GETVAL(value, sub, "name");
3294 llist->units = lydict_insert(module->ctx, value, strlen(value));
3295 } else if (!strcmp(sub->name, "ordered-by")) {
3296 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003297 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 goto error;
3299 }
3300 /* just checking the flags in llist is not sufficient, we would
3301 * allow multiple ordered-by statements with the "system" value
3302 */
3303 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003304
Radek Krejci1574a8d2015-08-03 14:16:52 +02003305 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3307 * state data
3308 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003309 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 continue;
3311 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 GETVAL(value, sub, "value");
3314 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003315 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003317 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003319 } /* else system is the default value, so we can ignore it */
3320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 } else if (!strcmp(sub->name, "must")) {
3322 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003323 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003324 } else if (!strcmp(sub->name, "if-feature")) {
3325 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 } else if (!strcmp(sub->name, "min-elements")) {
3329 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003330 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 goto error;
3332 }
3333 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 GETVAL(value, sub, "value");
3336 while (isspace(value[0])) {
3337 value++;
3338 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 /* convert it to uint32_t */
3341 errno = 0;
3342 endptr = NULL;
3343 val = strtoul(value, &endptr, 10);
3344 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003345 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003346 goto error;
3347 }
3348 llist->min = (uint32_t) val;
3349 } else if (!strcmp(sub->name, "max-elements")) {
3350 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003351 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 goto error;
3353 }
3354 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 GETVAL(value, sub, "value");
3357 while (isspace(value[0])) {
3358 value++;
3359 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 /* convert it to uint32_t */
3362 errno = 0;
3363 endptr = NULL;
3364 val = strtoul(value, &endptr, 10);
3365 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003366 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003367 goto error;
3368 }
3369 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003370 } else if (!strcmp(sub->name, "when")) {
3371 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003372 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003373 goto error;
3374 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003375
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003376 llist->when = read_yin_when(module, sub);
3377 if (!llist->when) {
3378 goto error;
3379 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003380 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003381 goto error;
3382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003383 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003384 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003387
Michal Vasko88c29542015-11-27 14:57:53 +01003388 /* do not free sub, it could have been unlinked and stored in unres */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003392 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003393 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003394 goto error;
3395 }
3396 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003397 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
3399 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 /* middle part - process nodes with cardinality of 0..n */
3402 if (c_must) {
3403 llist->must = calloc(c_must, sizeof *llist->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003404 if (!llist->must) {
3405 LOGMEM;
3406 goto error;
3407 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003409 if (c_ftrs) {
3410 llist->features = calloc(c_ftrs, sizeof *llist->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003411 if (!llist->features) {
3412 LOGMEM;
3413 goto error;
3414 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003415 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003416
Radek Krejci73adb602015-07-02 18:07:40 +02003417 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003419 r = fill_yin_must(module, sub, &llist->must[llist->must_size]);
3420 llist->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 if (r) {
3422 goto error;
3423 }
Michal Vasko0d204592015-10-07 09:50:04 +02003424 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003425 goto error;
3426 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003427 } else if (!strcmp(sub->name, "if-feature")) {
3428 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003429 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003430 goto error;
3431 }
Radek Krejcicf509982015-12-15 09:22:44 +01003432 /* hack - store pointer to the parent node for later status check */
3433 llist->features[llist->features_size] = (struct lys_feature *)llist;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003434 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02003435 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003436 llist->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003437 lydict_remove(module->ctx, value);
3438 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003439 goto error;
3440 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003445
3446error:
3447
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003448 lys_node_free(retval, NULL);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003451}
3452
Michal Vasko0d343d12015-08-24 14:57:36 +02003453/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003454static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003455read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3456 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003457{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003458 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003459 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003461 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003462 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003464 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 char *auxs;
3466 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 /* init */
3469 memset(&root, 0, sizeof root);
3470 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 list = calloc(1, sizeof *list);
Michal Vasko253035f2015-12-17 16:58:13 +01003473 if (!list) {
3474 LOGMEM;
3475 return NULL;
3476 }
Radek Krejci76512572015-08-04 09:47:08 +02003477 list->nodetype = LYS_LIST;
3478 list->prev = (struct lys_node *)list;
3479 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003480
Michal Vaskoe0c59842015-09-24 13:52:20 +02003481 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3482 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 goto error;
3484 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003485
Radek Krejcia9544502015-08-14 08:24:29 +02003486 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 /* process list's specific children */
3489 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003490 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3491 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003492 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003493 continue;
3494 }
3495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 /* data statements */
3497 if (!strcmp(sub->name, "container") ||
3498 !strcmp(sub->name, "leaf-list") ||
3499 !strcmp(sub->name, "leaf") ||
3500 !strcmp(sub->name, "list") ||
3501 !strcmp(sub->name, "choice") ||
3502 !strcmp(sub->name, "uses") ||
3503 !strcmp(sub->name, "grouping") ||
3504 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003505 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003506 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 /* array counters */
3509 } else if (!strcmp(sub->name, "key")) {
3510 /* check cardinality 0..1 */
3511 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003512 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 goto error;
3514 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003515
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003516 /* count the number of keys */
3517 GETVAL(value, sub, "value");
3518 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003519 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 while ((value = strpbrk(value, " \t\n"))) {
3521 list->keys_size++;
3522 while (isspace(*value)) {
3523 value++;
3524 }
3525 }
3526 list->keys_size++;
3527 list->keys = calloc(list->keys_size, sizeof *list->keys);
Michal Vasko253035f2015-12-17 16:58:13 +01003528 if (!list->keys) {
3529 LOGMEM;
3530 goto error;
3531 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 } else if (!strcmp(sub->name, "unique")) {
3533 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003534 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003535 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 } else if (!strcmp(sub->name, "typedef")) {
3537 c_tpdf++;
3538 } else if (!strcmp(sub->name, "must")) {
3539 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003540 } else if (!strcmp(sub->name, "if-feature")) {
3541 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 /* optional stetments */
3544 } else if (!strcmp(sub->name, "ordered-by")) {
3545 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003546 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 goto error;
3548 }
3549 /* just checking the flags in llist is not sufficient, we would
3550 * allow multiple ordered-by statements with the "system" value
3551 */
3552 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003553
Radek Krejci1574a8d2015-08-03 14:16:52 +02003554 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3556 * state data
3557 */
Michal Vasko345da0a2015-12-02 10:35:55 +01003558 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 continue;
3560 }
Radek Krejci345ad742015-06-03 11:04:18 +02003561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 GETVAL(value, sub, "value");
3563 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003564 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003566 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 goto error;
3568 }
3569 /* else system is the default value, so we can ignore it */
Michal Vasko345da0a2015-12-02 10:35:55 +01003570 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003571 } else if (!strcmp(sub->name, "min-elements")) {
3572 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003573 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 goto error;
3575 }
3576 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 GETVAL(value, sub, "value");
3579 while (isspace(value[0])) {
3580 value++;
3581 }
Radek Krejci345ad742015-06-03 11:04:18 +02003582
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003583 /* convert it to uint32_t */
3584 errno = 0;
3585 auxs = NULL;
3586 val = strtoul(value, &auxs, 10);
3587 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003588 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003589 goto error;
3590 }
3591 list->min = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003592 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 } else if (!strcmp(sub->name, "max-elements")) {
3594 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003595 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 goto error;
3597 }
3598 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 GETVAL(value, sub, "value");
3601 while (isspace(value[0])) {
3602 value++;
3603 }
Radek Krejci345ad742015-06-03 11:04:18 +02003604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 /* convert it to uint32_t */
3606 errno = 0;
3607 auxs = NULL;
3608 val = strtoul(value, &auxs, 10);
3609 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003610 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003611 goto error;
3612 }
3613 list->max = (uint32_t) val;
Michal Vasko345da0a2015-12-02 10:35:55 +01003614 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003615 } else if (!strcmp(sub->name, "when")) {
3616 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003617 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003618 goto error;
3619 }
3620
3621 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003622 if (!list->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003623 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003624 goto error;
3625 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003626 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003627 goto error;
3628 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003629 lyxml_free(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003630 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003631 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003632 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 }
3634 }
Radek Krejci345ad742015-06-03 11:04:18 +02003635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003637 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003638 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 goto error;
3640 }
3641 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003642 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 goto error;
3644 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003645
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003646 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3647 if (c_tpdf) {
3648 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003649 if (!list->tpdf) {
3650 LOGMEM;
3651 goto error;
3652 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003654 if (c_must) {
3655 list->must = calloc(c_must, sizeof *list->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003656 if (!list->must) {
3657 LOGMEM;
3658 goto error;
3659 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003660 }
3661 if (c_ftrs) {
3662 list->features = calloc(c_ftrs, sizeof *list->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003663 if (!list->features) {
3664 LOGMEM;
3665 goto error;
3666 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003667 }
Radek Krejci73adb602015-07-02 18:07:40 +02003668 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003670 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size], unres);
3671 list->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 if (r) {
3673 goto error;
3674 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003675 } else if (!strcmp(sub->name, "if-feature")) {
3676 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003677 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003678 goto error;
3679 }
Radek Krejcicf509982015-12-15 09:22:44 +01003680 /* hack - store pointer to the parent node for later status check */
3681 list->features[list->features_size] = (struct lys_feature *)list;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003682 r = unres_schema_add_str(module, unres, &list->features[list->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003683 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003684 list->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003685 lydict_remove(module->ctx, value);
3686 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003687 goto error;
3688 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003690 r = fill_yin_must(module, sub, &list->must[list->must_size]);
3691 list->must_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003692 if (r) {
3693 goto error;
3694 }
Michal Vasko0d204592015-10-07 09:50:04 +02003695 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003696 goto error;
3697 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003698 }
3699 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003700
Radek Krejcic071c542016-01-27 14:57:51 +01003701 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003702 goto error;
3703 }
3704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003705 /* last part - process data nodes */
3706 LY_TREE_FOR_SAFE(root.child, next, sub) {
3707 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003708 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003709 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003710 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003712 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003714 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003716 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003718 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003719 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003720 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003722 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003723 } else {
3724 LOGINT;
3725 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003727 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 goto error;
3729 }
Radek Krejci73adb602015-07-02 18:07:40 +02003730
Michal Vasko345da0a2015-12-02 10:35:55 +01003731 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 if (!key_str) {
3735 /* config false list without a key */
3736 return retval;
3737 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003738 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003739 goto error;
3740 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 /* process unique statements */
3743 if (c_uniq) {
3744 list->unique = calloc(c_uniq, sizeof *list->unique);
Michal Vasko253035f2015-12-17 16:58:13 +01003745 if (!list->unique) {
3746 LOGMEM;
3747 goto error;
3748 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 }
3750 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003751 r = fill_yin_unique(module, retval, sub, &list->unique[list->unique_size], unres);
3752 list->unique_size++;
3753 if (r) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003754 goto error;
3755 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003756
Michal Vasko345da0a2015-12-02 10:35:55 +01003757 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003759
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003760 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761
3762error:
3763
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003764 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003766 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 }
3768 while (uniq.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003769 lyxml_free(module->ctx, uniq.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003773}
3774
Michal Vasko0d343d12015-08-24 14:57:36 +02003775/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003776static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003777read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3778 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003779{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003781 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003782 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003783 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003784 const char *value;
3785 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003786 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003787
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 /* init */
3789 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003791 cont = calloc(1, sizeof *cont);
Michal Vasko253035f2015-12-17 16:58:13 +01003792 if (!cont) {
3793 LOGMEM;
3794 return NULL;
3795 }
Radek Krejci76512572015-08-04 09:47:08 +02003796 cont->nodetype = LYS_CONTAINER;
3797 cont->prev = (struct lys_node *)cont;
3798 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003799
Michal Vaskoe0c59842015-09-24 13:52:20 +02003800 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3801 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 goto error;
3803 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003804
Radek Krejcia9544502015-08-14 08:24:29 +02003805 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 /* process container's specific children */
3808 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003809 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003810 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003811 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003812 continue;
3813 }
3814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 if (!strcmp(sub->name, "presence")) {
3816 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003817 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
3820 GETVAL(value, sub, "value");
3821 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003822
Michal Vasko345da0a2015-12-02 10:35:55 +01003823 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003824 } else if (!strcmp(sub->name, "when")) {
3825 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003826 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003827 goto error;
3828 }
3829
3830 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003831 if (!cont->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003832 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003833 goto error;
3834 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003835 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003836 goto error;
3837 }
Michal Vasko345da0a2015-12-02 10:35:55 +01003838 lyxml_free(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 /* data statements */
3841 } else if (!strcmp(sub->name, "container") ||
3842 !strcmp(sub->name, "leaf-list") ||
3843 !strcmp(sub->name, "leaf") ||
3844 !strcmp(sub->name, "list") ||
3845 !strcmp(sub->name, "choice") ||
3846 !strcmp(sub->name, "uses") ||
3847 !strcmp(sub->name, "grouping") ||
3848 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003849 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003850 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 /* array counters */
3853 } else if (!strcmp(sub->name, "typedef")) {
3854 c_tpdf++;
3855 } else if (!strcmp(sub->name, "must")) {
3856 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003857 } else if (!strcmp(sub->name, "if-feature")) {
3858 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003860 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003862 }
3863 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3866 if (c_tpdf) {
3867 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01003868 if (!cont->tpdf) {
3869 LOGMEM;
3870 goto error;
3871 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
3873 if (c_must) {
3874 cont->must = calloc(c_must, sizeof *cont->must);
Michal Vasko253035f2015-12-17 16:58:13 +01003875 if (!cont->must) {
3876 LOGMEM;
3877 goto error;
3878 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003880 if (c_ftrs) {
3881 cont->features = calloc(c_ftrs, sizeof *cont->features);
Michal Vasko253035f2015-12-17 16:58:13 +01003882 if (!cont->features) {
3883 LOGMEM;
3884 goto error;
3885 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003886 }
Radek Krejci800af702015-06-02 13:46:01 +02003887
Radek Krejci73adb602015-07-02 18:07:40 +02003888 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003889 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003890 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size], unres);
3891 cont->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 if (r) {
3893 goto error;
3894 }
3895 } else if (!strcmp(sub->name, "must")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003896 r = fill_yin_must(module, sub, &cont->must[cont->must_size]);
3897 cont->must_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 if (r) {
3899 goto error;
3900 }
Michal Vasko0d204592015-10-07 09:50:04 +02003901 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003902 goto error;
3903 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003904 } else if (!strcmp(sub->name, "if-feature")) {
3905 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003906 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003907 goto error;
3908 }
Radek Krejcicf509982015-12-15 09:22:44 +01003909 /* hack - store pointer to the parent node for later status check */
3910 cont->features[cont->features_size] = (struct lys_feature *)cont;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003911 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01003912 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01003913 cont->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02003914 lydict_remove(module->ctx, value);
3915 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003916 goto error;
3917 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003919 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003920
Radek Krejcic071c542016-01-27 14:57:51 +01003921 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003922 goto error;
3923 }
3924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 /* last part - process data nodes */
3926 LY_TREE_FOR_SAFE(root.child, next, sub) {
3927 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003928 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003929 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003930 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003932 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003933 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003934 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003936 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003938 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003939 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003940 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003941 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003942 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003944 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003945 goto error;
3946 }
Radek Krejci73adb602015-07-02 18:07:40 +02003947
Michal Vasko345da0a2015-12-02 10:35:55 +01003948 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003951 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003952
3953error:
3954
Radek Krejcifa0b5e02016-02-04 13:57:03 +01003955 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01003957 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003959
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003961}
3962
Michal Vasko0d343d12015-08-24 14:57:36 +02003963/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003964static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003966 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003967{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003969 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003970 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003971 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003972 int r;
3973 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 /* init */
3976 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003978 grp = calloc(1, sizeof *grp);
Michal Vasko253035f2015-12-17 16:58:13 +01003979 if (!grp) {
3980 LOGMEM;
3981 return NULL;
3982 }
Radek Krejci76512572015-08-04 09:47:08 +02003983 grp->nodetype = LYS_GROUPING;
3984 grp->prev = (struct lys_node *)grp;
3985 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003986
Michal Vasko71e1aa82015-08-12 12:17:51 +02003987 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003988 goto error;
3989 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003990
Radek Krejcia9544502015-08-14 08:24:29 +02003991 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3992
Radek Krejci1d82ef62015-08-07 14:44:40 +02003993 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003994 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3995 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01003996 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02003997 continue;
3998 }
3999
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 /* data statements */
4001 if (!strcmp(sub->name, "container") ||
4002 !strcmp(sub->name, "leaf-list") ||
4003 !strcmp(sub->name, "leaf") ||
4004 !strcmp(sub->name, "list") ||
4005 !strcmp(sub->name, "choice") ||
4006 !strcmp(sub->name, "uses") ||
4007 !strcmp(sub->name, "grouping") ||
4008 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004009 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004010 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 /* array counters */
4013 } else if (!strcmp(sub->name, "typedef")) {
4014 c_tpdf++;
4015 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004016 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 goto error;
4018 }
4019 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4022 if (c_tpdf) {
4023 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004024 if (!grp->tpdf) {
4025 LOGMEM;
4026 goto error;
4027 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004029 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004030 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size], unres);
4031 grp->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004032 if (r) {
4033 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004034 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004035 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004036
Radek Krejcic071c542016-01-27 14:57:51 +01004037 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004038 goto error;
4039 }
4040
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004041 /* last part - process data nodes */
4042 LY_TREE_FOR_SAFE(root.child, next, sub) {
4043 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004044 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004045 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004046 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004047 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004048 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004049 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004050 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004052 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004053 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004054 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004055 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004056 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004058 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004059 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004060 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 goto error;
4062 }
Radek Krejci73adb602015-07-02 18:07:40 +02004063
Michal Vasko345da0a2015-12-02 10:35:55 +01004064 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004065 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004067 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004068
4069error:
4070
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004071 lys_node_free(retval, NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004072 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004073 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004076 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004077}
4078
Michal Vasko0d343d12015-08-24 14:57:36 +02004079/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004080static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004081read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4082 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004083{
Radek Krejcie0674f82015-06-15 13:58:51 +02004084 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004086 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004087 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 int r;
4089 int c_tpdf = 0;
4090
Radek Krejcie0674f82015-06-15 13:58:51 +02004091 /* init */
4092 memset(&root, 0, sizeof root);
4093
Michal Vasko38d01f72015-06-15 09:41:06 +02004094 inout = calloc(1, sizeof *inout);
Michal Vasko253035f2015-12-17 16:58:13 +01004095 if (!inout) {
4096 LOGMEM;
4097 return NULL;
4098 }
Radek Krejci6acc8012015-08-13 09:07:04 +02004099 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004100
4101 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004102 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004103 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004104 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004105 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004106 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004107 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004108 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004109 }
4110
Radek Krejci76512572015-08-04 09:47:08 +02004111 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004112
Radek Krejci6a113852015-07-03 16:04:20 +02004113 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004114 goto error;
4115 }
4116
Radek Krejcia9544502015-08-14 08:24:29 +02004117 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4118
Michal Vasko38d01f72015-06-15 09:41:06 +02004119 /* data statements */
4120 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004121 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4122 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004123 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004124 continue;
4125 }
4126
Michal Vasko38d01f72015-06-15 09:41:06 +02004127 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 !strcmp(sub->name, "leaf-list") ||
4129 !strcmp(sub->name, "leaf") ||
4130 !strcmp(sub->name, "list") ||
4131 !strcmp(sub->name, "choice") ||
4132 !strcmp(sub->name, "uses") ||
4133 !strcmp(sub->name, "grouping") ||
4134 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004135 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004136 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004139 } else if (!strcmp(sub->name, "typedef")) {
4140 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004141
Michal Vasko38d01f72015-06-15 09:41:06 +02004142 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004143 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004144 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004145 }
4146 }
4147
4148 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4149 if (c_tpdf) {
4150 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004151 if (!inout->tpdf) {
4152 LOGMEM;
4153 goto error;
4154 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 }
4156
Radek Krejci73adb602015-07-02 18:07:40 +02004157 LY_TREE_FOR(yin->child, sub) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004158 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size], unres);
4159 inout->tpdf_size++;
Radek Krejci73adb602015-07-02 18:07:40 +02004160 if (r) {
4161 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004162 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 }
4164
Radek Krejcic071c542016-01-27 14:57:51 +01004165 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004166 goto error;
4167 }
4168
Michal Vasko38d01f72015-06-15 09:41:06 +02004169 /* last part - process data nodes */
4170 LY_TREE_FOR_SAFE(root.child, next, sub) {
4171 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004172 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004174 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004175 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004176 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004177 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004178 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004179 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004180 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004181 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004182 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004183 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004184 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004185 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004186 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004187 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004188 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004189 goto error;
4190 }
Radek Krejci73adb602015-07-02 18:07:40 +02004191
Michal Vasko345da0a2015-12-02 10:35:55 +01004192 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004193 }
4194
Michal Vasko38d01f72015-06-15 09:41:06 +02004195 return retval;
4196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004197error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004198
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004199 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004200 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004201 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004202 }
4203
4204 return NULL;
4205}
4206
Michal Vasko0d343d12015-08-24 14:57:36 +02004207/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004208static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004209read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4210 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004211{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004212 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004213 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004214 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004215 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004216 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004217 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004218 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004219
Michal Vaskoc6551b32015-06-16 10:51:43 +02004220 memset(&root, 0, sizeof root);
4221
Michal Vasko0ea41032015-06-16 08:53:55 +02004222 notif = calloc(1, sizeof *notif);
Michal Vasko253035f2015-12-17 16:58:13 +01004223 if (!notif) {
4224 LOGMEM;
4225 return NULL;
4226 }
Radek Krejci76512572015-08-04 09:47:08 +02004227 notif->nodetype = LYS_NOTIF;
4228 notif->prev = (struct lys_node *)notif;
4229 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004230
Radek Krejci6a113852015-07-03 16:04:20 +02004231 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004232 goto error;
4233 }
4234
Radek Krejcia9544502015-08-14 08:24:29 +02004235 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4236
Michal Vasko0ea41032015-06-16 08:53:55 +02004237 /* process rpc's specific children */
4238 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004239 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4240 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004241 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004242 continue;
4243 }
4244
Michal Vasko0ea41032015-06-16 08:53:55 +02004245 /* data statements */
4246 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004247 !strcmp(sub->name, "leaf-list") ||
4248 !strcmp(sub->name, "leaf") ||
4249 !strcmp(sub->name, "list") ||
4250 !strcmp(sub->name, "choice") ||
4251 !strcmp(sub->name, "uses") ||
4252 !strcmp(sub->name, "grouping") ||
4253 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004254 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004255 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004257 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004258 } else if (!strcmp(sub->name, "typedef")) {
4259 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004260 } else if (!strcmp(sub->name, "if-feature")) {
4261 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004262 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004263 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004264 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 }
4266 }
4267
4268 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4269 if (c_tpdf) {
4270 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004271 if (!notif->tpdf) {
4272 LOGMEM;
4273 goto error;
4274 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004275 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004276 if (c_ftrs) {
4277 notif->features = calloc(c_ftrs, sizeof *notif->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004278 if (!notif->features) {
4279 LOGMEM;
4280 goto error;
4281 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004282 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004283
Radek Krejci73adb602015-07-02 18:07:40 +02004284 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004285 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004286 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size], unres);
4287 notif->tpdf_size++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004288 if (r) {
4289 goto error;
4290 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004291 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004292 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004293 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004294 goto error;
4295 }
Radek Krejcicf509982015-12-15 09:22:44 +01004296 /* hack - store pointer to the parent node for later status check */
4297 notif->features[notif->features_size] = (struct lys_feature *)notif;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004298 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004299 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004300 notif->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004301 lydict_remove(module->ctx, value);
4302 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004303 goto error;
4304 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004305 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004306 }
4307
Radek Krejcic071c542016-01-27 14:57:51 +01004308 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004309 goto error;
4310 }
4311
Michal Vasko0ea41032015-06-16 08:53:55 +02004312 /* last part - process data nodes */
4313 LY_TREE_FOR_SAFE(root.child, next, sub) {
4314 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004315 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004317 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004318 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004319 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004320 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004321 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004322 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004323 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004324 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004325 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004326 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004327 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004328 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004329 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004330 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004331 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004332 goto error;
4333 }
Radek Krejci73adb602015-07-02 18:07:40 +02004334
Michal Vasko345da0a2015-12-02 10:35:55 +01004335 lyxml_free(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004336 }
4337
Michal Vasko0ea41032015-06-16 08:53:55 +02004338 return retval;
4339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004340error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004341
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004342 lys_node_free(retval, NULL);
Michal Vasko0ea41032015-06-16 08:53:55 +02004343 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004344 lyxml_free(module->ctx, root.child);
Michal Vasko0ea41032015-06-16 08:53:55 +02004345 }
4346
4347 return NULL;
4348}
4349
Michal Vasko0d343d12015-08-24 14:57:36 +02004350/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004351static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004352read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4353 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004354{
Radek Krejcie0674f82015-06-15 13:58:51 +02004355 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004356 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004357 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004358 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004359 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004360 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004361 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004362
Radek Krejcie0674f82015-06-15 13:58:51 +02004363 /* init */
4364 memset(&root, 0, sizeof root);
4365
Michal Vasko38d01f72015-06-15 09:41:06 +02004366 rpc = calloc(1, sizeof *rpc);
Michal Vasko253035f2015-12-17 16:58:13 +01004367 if (!rpc) {
4368 LOGMEM;
4369 return NULL;
4370 }
Radek Krejci76512572015-08-04 09:47:08 +02004371 rpc->nodetype = LYS_RPC;
4372 rpc->prev = (struct lys_node *)rpc;
4373 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004374
Radek Krejci6a113852015-07-03 16:04:20 +02004375 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004376 goto error;
4377 }
4378
Radek Krejcia9544502015-08-14 08:24:29 +02004379 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4380
Michal Vasko38d01f72015-06-15 09:41:06 +02004381 /* process rpc's specific children */
4382 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004383 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4384 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004385 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004386 continue;
4387 }
4388
Michal Vasko38d01f72015-06-15 09:41:06 +02004389 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004391 && (rpc->child->nodetype == LYS_INPUT
4392 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004393 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004394 goto error;
4395 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004396 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004397 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004398 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004400 && (rpc->child->nodetype == LYS_INPUT
4401 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004402 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004403 goto error;
4404 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004405 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004406 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004409 } else if (!strcmp(sub->name, "grouping")) {
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);
Michal Vasko38d01f72015-06-15 09:41:06 +02004412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004414 } else if (!strcmp(sub->name, "typedef")) {
4415 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004416 } else if (!strcmp(sub->name, "if-feature")) {
4417 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004418 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004419 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004420 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004421 }
4422 }
4423
4424 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4425 if (c_tpdf) {
4426 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
Michal Vasko253035f2015-12-17 16:58:13 +01004427 if (!rpc->tpdf) {
4428 LOGMEM;
4429 goto error;
4430 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004431 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004432 if (c_ftrs) {
4433 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004434 if (!rpc->features) {
4435 LOGMEM;
4436 goto error;
4437 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004438 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004439
Radek Krejci73adb602015-07-02 18:07:40 +02004440 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004441 if (!strcmp(sub->name, "typedef")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004442 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size], unres);
4443 rpc->tpdf_size++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004444 if (r) {
4445 goto error;
4446 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004447 } else if (!strcmp(sub->name, "if-feature")) {
4448 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004449 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004450 goto error;
4451 }
Radek Krejcicf509982015-12-15 09:22:44 +01004452 /* hack - store pointer to the parent node for later status check */
4453 rpc->features[rpc->features_size] = (struct lys_feature *)rpc;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004454 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size], UNRES_IFFEAT, value,
Radek Krejcife8582c2015-12-15 15:39:02 +01004455 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004456 rpc->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004457 lydict_remove(module->ctx, value);
4458 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004459 goto error;
4460 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004461 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004462 }
4463
Radek Krejcic071c542016-01-27 14:57:51 +01004464 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004465 goto error;
4466 }
4467
Michal Vasko38d01f72015-06-15 09:41:06 +02004468 /* last part - process data nodes */
4469 LY_TREE_FOR_SAFE(root.child, next, sub) {
4470 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004471 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004472 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004473 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004474 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004475 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004476 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004477 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004478 goto error;
4479 }
Radek Krejci73adb602015-07-02 18:07:40 +02004480
Michal Vasko345da0a2015-12-02 10:35:55 +01004481 lyxml_free(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004482 }
4483
Michal Vasko38d01f72015-06-15 09:41:06 +02004484 return retval;
4485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004487
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004488 lys_node_free(retval, NULL);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004489 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004490 lyxml_free(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004491 }
4492
4493 return NULL;
4494}
4495
Michal Vasko0d343d12015-08-24 14:57:36 +02004496/* logs directly
4497 *
Radek Krejci74705112015-06-05 10:25:44 +02004498 * resolve - referenced grouping should be bounded to the namespace (resolved)
4499 * only when uses does not appear in grouping. In a case of grouping's uses,
4500 * we just get information but we do not apply augment or refine to it.
4501 */
Radek Krejci76512572015-08-04 09:47:08 +02004502static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004503read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004504 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004505{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004507 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004508 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004510 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 uses = calloc(1, sizeof *uses);
Michal Vasko253035f2015-12-17 16:58:13 +01004514 if (!uses) {
4515 LOGMEM;
4516 return NULL;
4517 }
Radek Krejci76512572015-08-04 09:47:08 +02004518 uses->nodetype = LYS_USES;
4519 uses->prev = (struct lys_node *)uses;
4520 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004521
Radek Krejcia9544502015-08-14 08:24:29 +02004522 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004524
Michal Vaskoe0c59842015-09-24 13:52:20 +02004525 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4526 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 goto error;
4528 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004529
Radek Krejcia9544502015-08-14 08:24:29 +02004530 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004533 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004534 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4535 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004536 lyxml_free(module->ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02004537 continue;
4538 }
4539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 if (!strcmp(sub->name, "refine")) {
4541 c_ref++;
4542 } else if (!strcmp(sub->name, "augment")) {
4543 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004544 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004545 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004546 } else if (!strcmp(sub->name, "when")) {
4547 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004548 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004549 goto error;
4550 }
4551
4552 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004553 if (!uses->when) {
Michal Vasko345da0a2015-12-02 10:35:55 +01004554 lyxml_free(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004555 goto error;
4556 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004557 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004558 goto error;
4559 }
Michal Vasko345da0a2015-12-02 10:35:55 +01004560 lyxml_free(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004561 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004562 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 }
4565 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 /* process properties with cardinality 0..n */
4568 if (c_ref) {
4569 uses->refine = calloc(c_ref, sizeof *uses->refine);
Michal Vasko253035f2015-12-17 16:58:13 +01004570 if (!uses->refine) {
4571 LOGMEM;
4572 goto error;
4573 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004574 }
4575 if (c_aug) {
4576 uses->augment = calloc(c_aug, sizeof *uses->augment);
Michal Vasko253035f2015-12-17 16:58:13 +01004577 if (!uses->augment) {
4578 LOGMEM;
4579 goto error;
4580 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004582 if (c_ftrs) {
4583 uses->features = calloc(c_ftrs, sizeof *uses->features);
Michal Vasko253035f2015-12-17 16:58:13 +01004584 if (!uses->features) {
4585 LOGMEM;
4586 goto error;
4587 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004588 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004589
Radek Krejcic071c542016-01-27 14:57:51 +01004590 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004591 goto error;
4592 }
4593
Radek Krejcia9544502015-08-14 08:24:29 +02004594 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004595 if (!strcmp(sub->name, "refine")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004596 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size]);
4597 uses->refine_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004598 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004599 goto error;
4600 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004601 } else if (!strcmp(sub->name, "augment")) {
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004602 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size], unres);
4603 uses->augment_size++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004604 if (r) {
4605 goto error;
4606 }
4607 } else if (!strcmp(sub->name, "if-feature")) {
4608 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004609 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004610 goto error;
4611 }
Radek Krejcicf509982015-12-15 09:22:44 +01004612 /* hack - store pointer to the parent node for later status check */
4613 uses->features[uses->features_size] = (struct lys_feature *)uses;
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004614 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size], UNRES_IFFEAT, value,
Michal Vasko2d851a92015-10-20 16:16:36 +02004615 LOGLINE(sub));
Radek Krejci7d74ebc2015-12-10 16:05:02 +01004616 uses->features_size++;
Michal Vasko2d851a92015-10-20 16:16:36 +02004617 lydict_remove(module->ctx, value);
4618 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004619 goto error;
4620 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 }
4622 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004623
Michal Vasko0bd29d12015-08-19 11:45:49 +02004624 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004625 goto error;
4626 }
Radek Krejci74705112015-06-05 10:25:44 +02004627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 if (resolve) {
4629 /* inherit config flag */
4630 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004631 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 } else {
4633 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004634 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 }
4636 }
Radek Krejcib388c152015-06-04 17:03:03 +02004637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004639
4640error:
4641
Radek Krejcifa0b5e02016-02-04 13:57:03 +01004642 lys_node_free(retval, NULL);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004643
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004645}
4646
Michal Vasko0d343d12015-08-24 14:57:36 +02004647/* logs directly
4648 *
4649 * common code for yin_read_module() and yin_read_submodule()
4650 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004651static int
Radek Krejcic071c542016-01-27 14:57:51 +01004652read_sub_module(struct lys_module *module, struct lys_submodule *submodule, struct lyxml_elem *yin,
4653 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004654{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 struct ly_ctx *ctx = module->ctx;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004656 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004657 struct lys_node *node = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01004658 struct lys_module *trg;
4659 struct lys_import *aux_imp;
4660 struct lys_include *aux_inc, inc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004661 const char *value;
Radek Krejcic071c542016-01-27 14:57:51 +01004662 int i, j, r;
4663 int inc_size_aux = 0;
4664 int version_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004665 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004666 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 +02004667
Radek Krejcic071c542016-01-27 14:57:51 +01004668 /* to simplify code, store the module/submodule being processed as trg */
4669 trg = submodule ? (struct lys_module*)submodule : module;
4670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 /* init */
4672 memset(&root, 0, sizeof root);
4673 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004674 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 /*
4677 * in the first run, we process elements with cardinality of 1 or 0..1 and
4678 * count elements with cardinality 0..n. Data elements (choices, containers,
4679 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4680 * need have all top-level and groupings already prepared at that time. In
4681 * the middle loop, we process other elements with carinality of 0..n since
4682 * we need to allocate arrays to store them.
4683 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004684 LY_TREE_FOR_SAFE(yin->child, next, child) {
4685 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004686 /* garbage */
Michal Vasko345da0a2015-12-02 10:35:55 +01004687 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 continue;
4689 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004690
Radek Krejcic071c542016-01-27 14:57:51 +01004691 if (!submodule && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004693 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 goto error;
4695 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 module->ns = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004698 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004699 } else if (!submodule && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 goto error;
4703 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004704 GETVAL(value, child, "value");
Radek Krejcic6556022016-01-27 15:16:45 +01004705 if (lyp_check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 goto error;
4707 }
4708 module->prefix = lydict_insert(ctx, value, strlen(value));
Michal Vasko345da0a2015-12-02 10:35:55 +01004709 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004710 } else if (submodule && !strcmp(child->name, "belongs-to")) {
4711 if (submodule->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 goto error;
4714 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004715 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004717 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
4719 }
Radek Krejcif3886932015-06-04 17:36:06 +02004720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004722 if (!child->child) {
4723 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004725 } else if (strcmp(child->child->name, "prefix")) {
4726 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004728 } else if (child->child->next) {
4729 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 goto error;
4731 }
4732 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004733 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 /* check here differs from a generic prefix check, since this prefix
4735 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004736 */
Radek Krejcic6556022016-01-27 15:16:45 +01004737 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 goto error;
4739 }
Radek Krejcic071c542016-01-27 14:57:51 +01004740 submodule->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 /* we are done with belongs-to */
Michal Vasko345da0a2015-12-02 10:35:55 +01004743 lyxml_free(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004744
4745 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004746 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004750 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004752 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004756 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004757 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004758 /* keep augments separated, processed last */
Radek Krejcic071c542016-01-27 14:57:51 +01004759 lyxml_unlink_elem(ctx, child, 2);
4760 lyxml_add_child(ctx, &augs, child);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004761
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004763 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004764 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004765 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004767 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004768 } else if (!strcmp(child->name, "container") ||
4769 !strcmp(child->name, "leaf-list") ||
4770 !strcmp(child->name, "leaf") ||
4771 !strcmp(child->name, "list") ||
4772 !strcmp(child->name, "choice") ||
4773 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004774 !strcmp(child->name, "anyxml") ||
4775 !strcmp(child->name, "rpc") ||
4776 !strcmp(child->name, "notification")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004777 lyxml_unlink_elem(ctx, child, 2);
4778 lyxml_add_child(ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004779
Radek Krejci1d82ef62015-08-07 14:44:40 +02004780 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004781 /* keep groupings separated and process them before other data statements */
Radek Krejcic071c542016-01-27 14:57:51 +01004782 lyxml_unlink_elem(ctx, child, 2);
4783 lyxml_add_child(ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004786 } else if (!strcmp(child->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004787 if (trg->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004788 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004789 goto error;
4790 }
Radek Krejcic071c542016-01-27 14:57:51 +01004791 trg->dsc = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004792 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004793 if (!trg->dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004794 goto error;
4795 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004796 } else if (!strcmp(child->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004797 if (trg->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004798 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 goto error;
4800 }
Radek Krejcic071c542016-01-27 14:57:51 +01004801 trg->ref = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004802 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004803 if (!trg->ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 goto error;
4805 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004806 } else if (!strcmp(child->name, "organization")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004807 if (trg->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004808 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004809 goto error;
4810 }
Radek Krejcic071c542016-01-27 14:57:51 +01004811 trg->org = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004812 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004813 if (!trg->org) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 goto error;
4815 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004816 } else if (!strcmp(child->name, "contact")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004817 if (trg->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004818 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004819 goto error;
4820 }
Radek Krejcic071c542016-01-27 14:57:51 +01004821 trg->contact = read_yin_subnode(ctx, child, "text");
Michal Vasko345da0a2015-12-02 10:35:55 +01004822 lyxml_free(ctx, child);
Radek Krejcic071c542016-01-27 14:57:51 +01004823 if (!trg->contact) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 goto error;
4825 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004826 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004827 /* TODO: support YANG 1.1 ? */
Radek Krejcic071c542016-01-27 14:57:51 +01004828 if (version_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004829 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 goto error;
4831 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004832 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004834 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 goto error;
4836 }
Radek Krejcic071c542016-01-27 14:57:51 +01004837 version_flag = 1;
4838 if (!submodule) {
4839 module->version = 1;
4840 } /* TODO else check for the submodule's same version as in main module, waits for YANG 1.1 support */
Michal Vasko345da0a2015-12-02 10:35:55 +01004841 lyxml_free(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004842
Radek Krejci1d82ef62015-08-07 14:44:40 +02004843 } else if (!strcmp(child->name, "extension")) {
4844 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004845
Radek Krejci3d468122015-10-02 13:36:12 +02004846 /* we have the following supported (hardcoded) extensions: */
4847 /* ietf-netconf's get-filter-element-attributes */
4848 if (!strcmp(module->ns, LY_NSNC) &&
4849 !strcmp(value, "get-filter-element-attributes")) {
4850 LOGDBG("NETCONF filter extension found");
4851 /* NACM's default-deny-write and default-deny-all */
4852 } else if (!strcmp(module->ns, LY_NSNACM) &&
4853 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4854 LOGDBG("NACM extension found");
4855 /* other extensions are not supported, so inform about such an extension */
4856 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004857 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Michal Vasko345da0a2015-12-02 10:35:55 +01004858 lyxml_free(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004859 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004861 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004862 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 }
4864 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004865
Radek Krejcic071c542016-01-27 14:57:51 +01004866 /* check for mandatory statements */
4867 if (submodule && !submodule->prefix) {
Michal Vaskobdf51ef2015-12-10 12:11:21 +01004868 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "belongs-to", "submodule");
4869 goto error;
Radek Krejcic071c542016-01-27 14:57:51 +01004870 } else if (!submodule) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004872 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 goto error;
4874 }
4875 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004876 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 goto error;
4878 }
4879 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 /* allocate arrays for elements with cardinality of 0..n */
4882 if (c_imp) {
Radek Krejcic071c542016-01-27 14:57:51 +01004883 trg->imp = calloc(c_imp, sizeof *trg->imp);
4884 if (!trg->imp) {
Michal Vasko253035f2015-12-17 16:58:13 +01004885 LOGMEM;
4886 goto error;
4887 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 }
4889 if (c_rev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004890 trg->rev = calloc(c_rev, sizeof *trg->rev);
4891 if (!trg->rev) {
Michal Vasko253035f2015-12-17 16:58:13 +01004892 LOGMEM;
4893 goto error;
4894 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004895 }
4896 if (c_tpdf) {
Radek Krejcic071c542016-01-27 14:57:51 +01004897 trg->tpdf = calloc(c_tpdf, sizeof *trg->tpdf);
4898 if (!trg->tpdf) {
Michal Vasko253035f2015-12-17 16:58:13 +01004899 LOGMEM;
4900 goto error;
4901 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 }
4903 if (c_ident) {
Radek Krejcic071c542016-01-27 14:57:51 +01004904 trg->ident = calloc(c_ident, sizeof *trg->ident);
4905 if (!trg->ident) {
Michal Vasko253035f2015-12-17 16:58:13 +01004906 LOGMEM;
4907 goto error;
4908 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 }
4910 if (c_inc) {
Radek Krejcic071c542016-01-27 14:57:51 +01004911 trg->inc = calloc(c_inc, sizeof *trg->inc);
4912 if (!trg->inc) {
Michal Vasko253035f2015-12-17 16:58:13 +01004913 LOGMEM;
4914 goto error;
4915 }
Radek Krejcic071c542016-01-27 14:57:51 +01004916 trg->inc_size = c_inc;
4917 /* trg->inc_size can be updated by the included submodules,
4918 * so we will use inc_size_aux here, trg->inc_size stores the
4919 * target size of the array
4920 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004922 if (c_aug) {
Radek Krejcic071c542016-01-27 14:57:51 +01004923 trg->augment = calloc(c_aug, sizeof *trg->augment);
4924 if (!trg->augment) {
Michal Vasko253035f2015-12-17 16:58:13 +01004925 LOGMEM;
4926 goto error;
4927 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004928 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004929 if (c_ftrs) {
Radek Krejcic071c542016-01-27 14:57:51 +01004930 trg->features = calloc(c_ftrs, sizeof *trg->features);
4931 if (!trg->features) {
Michal Vasko253035f2015-12-17 16:58:13 +01004932 LOGMEM;
4933 goto error;
4934 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004935 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004936 if (c_dev) {
Radek Krejcic071c542016-01-27 14:57:51 +01004937 trg->deviation = calloc(c_dev, sizeof *trg->deviation);
4938 if (!trg->deviation) {
Michal Vasko253035f2015-12-17 16:58:13 +01004939 LOGMEM;
4940 goto error;
4941 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004942 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004943
Michal Vasko2f7925f2015-10-21 15:06:56 +02004944 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4945 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004946 if (!strcmp(child->name, "import")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004947 r = fill_yin_import(trg, child, &trg->imp[trg->imp_size]);
4948 trg->imp_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 if (r) {
4950 goto error;
4951 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 /* check duplicities in imported modules */
Radek Krejcic071c542016-01-27 14:57:51 +01004954 for (i = 0; i < trg->imp_size - 1; i++) {
4955 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
4956 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 goto error;
4958 }
4959 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004960
Radek Krejci1d82ef62015-08-07 14:44:40 +02004961 } else if (!strcmp(child->name, "include")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004962 memset(&inc, 0, sizeof inc);
4963 /* 1) pass module, not trg, since we want to pass the main module
4964 * 2) we cannot pass directly the structure in the array since
4965 * submodule parser can realloc our array of includes */
4966 r = fill_yin_include(module, child, &inc, unres);
4967 memcpy(&trg->inc[inc_size_aux], &inc, sizeof inc);
4968 inc_size_aux++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004969 if (r) {
4970 goto error;
4971 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 /* check duplications in include submodules */
Radek Krejcic071c542016-01-27 14:57:51 +01004974 for (i = 0; i < inc_size_aux - 1; i++) {
4975 if (!strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
4976 LOGVAL(LYE_SPEC, LOGLINE(child), "Including submodule \"%s\" repeatedly.",
4977 trg->inc[i].submodule->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004978 goto error;
4979 }
4980 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004981
Radek Krejci1d82ef62015-08-07 14:44:40 +02004982 } else if (!strcmp(child->name, "revision")) {
4983 GETVAL(value, child, "date");
Radek Krejcic6556022016-01-27 15:16:45 +01004984 if (lyp_check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004985 goto error;
4986 }
Radek Krejcic071c542016-01-27 14:57:51 +01004987 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 /* check uniqueness of the revision date - not required by RFC */
Radek Krejcic071c542016-01-27 14:57:51 +01004989 for (i = 0; i < trg->rev_size; i++) {
4990 if (!strcmp(value, trg->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004991 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004992 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 }
4994 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004995
Radek Krejci1d82ef62015-08-07 14:44:40 +02004996 LY_TREE_FOR(child->child, child2) {
4997 if (!strcmp(child2->name, "description")) {
Radek Krejcic071c542016-01-27 14:57:51 +01004998 if (trg->rev[trg->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004999 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005000 goto error;
5001 }
Radek Krejcic071c542016-01-27 14:57:51 +01005002 trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
5003 if (!trg->rev[trg->rev_size].dsc) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005004 goto error;
5005 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005006 } else if (!strcmp(child2->name, "reference")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005007 if (trg->rev[trg->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005008 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005009 goto error;
5010 }
Radek Krejcic071c542016-01-27 14:57:51 +01005011 trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
5012 if (!trg->rev[trg->rev_size].ref) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 goto error;
5014 }
5015 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02005016 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 goto error;
5018 }
5019 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 /* keep the latest revision at position 0 */
Radek Krejcic071c542016-01-27 14:57:51 +01005022 if (trg->rev_size && strcmp(trg->rev[trg->rev_size].date, trg->rev[0].date) > 0) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005023 /* switch their position */
Radek Krejcic071c542016-01-27 14:57:51 +01005024 value = strdup(trg->rev[0].date);
Michal Vasko253035f2015-12-17 16:58:13 +01005025 if (!value) {
5026 LOGMEM;
5027 goto error;
5028 }
Radek Krejcic071c542016-01-27 14:57:51 +01005029 memcpy(trg->rev[0].date, trg->rev[trg->rev_size].date, LY_REV_SIZE - 1);
5030 memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005031 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02005032
Radek Krejcic071c542016-01-27 14:57:51 +01005033 if (trg->rev[0].dsc != trg->rev[trg->rev_size].dsc) {
5034 value = trg->rev[0].dsc;
5035 trg->rev[0].dsc = trg->rev[trg->rev_size].dsc;
5036 trg->rev[trg->rev_size].dsc = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005037 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005038
Radek Krejcic071c542016-01-27 14:57:51 +01005039 if (trg->rev[0].ref != trg->rev[trg->rev_size].ref) {
5040 value = trg->rev[0].ref;
5041 trg->rev[0].ref = trg->rev[trg->rev_size].ref;
5042 trg->rev[trg->rev_size].ref = value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005043 }
5044 }
Radek Krejcice7fb782015-05-29 16:52:34 +02005045
Radek Krejcic071c542016-01-27 14:57:51 +01005046 trg->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02005047
Radek Krejci1d82ef62015-08-07 14:44:40 +02005048 } else if (!strcmp(child->name, "typedef")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005049 r = fill_yin_typedef(trg, NULL, child, &trg->tpdf[trg->tpdf_size], unres);
5050 trg->tpdf_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005051 if (r) {
5052 goto error;
5053 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005054
Radek Krejci1d82ef62015-08-07 14:44:40 +02005055 } else if (!strcmp(child->name, "identity")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005056 r = fill_yin_identity(trg, child, &trg->ident[trg->ident_size], unres);
5057 trg->ident_size++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005058 if (r) {
5059 goto error;
5060 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005061
Radek Krejci1d82ef62015-08-07 14:44:40 +02005062 } else if (!strcmp(child->name, "feature")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005063 r = fill_yin_feature(trg, child, &trg->features[trg->features_size], unres);
5064 trg->features_size++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02005065 if (r) {
5066 goto error;
5067 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005068
Radek Krejci1d82ef62015-08-07 14:44:40 +02005069 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcic071c542016-01-27 14:57:51 +01005070 r = fill_yin_deviation(trg, child, &trg->deviation[trg->deviation_size], unres);
5071 trg->deviation_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02005072 if (r) {
5073 goto error;
5074 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005076 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005077 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02005078
Radek Krejcic071c542016-01-27 14:57:51 +01005079 if (submodule) {
5080 /* propagate imports into the main module */
5081 for (i = r = 0; i < submodule->imp_size; i++) {
5082 for (j = 0; j < module->imp_size; j++) {
5083 if (submodule->imp[i].module == module->imp[j].module &&
5084 !strcmp(submodule->imp[i].rev, module->imp[j].rev)) {
5085 /* check prefix match */
5086 if (submodule->imp[i].prefix != module->imp[j].prefix) {
5087 LOGVAL(LYE_INID, LOGLINE(yin), submodule->imp[i].prefix,
5088 "non-matching prefixes of imported module in main module and submodule");
5089 goto error;
5090 }
5091 break;
5092 }
5093 }
5094 if (j == module->imp_size) {
5095 /* new import */
5096 r++;
5097 }
5098 }
5099 if (r) {
5100 aux_imp = realloc(module->imp, (module->imp_size + r) * sizeof *module->imp);
5101 if (!aux_imp) {
5102 LOGMEM;
5103 goto error;
5104 }
5105 module->imp = aux_imp;
5106 for (i = r = 0; i < submodule->imp_size; i++) {
5107 for (j = 0; j < module->imp_size; j++) {
5108 if (submodule->imp[i].module == module->imp[j].module) {
5109 break;
5110 }
5111 }
5112 if (j == module->imp_size) {
5113 /* new import */
5114 /* check prefix uniqueness */
5115 if (dup_prefix_check(submodule->imp[i].prefix, module)) {
5116 LOGVAL(LYE_DUPID, LOGLINE(yin), "prefix", submodule->imp[i].prefix);
5117 goto error;
5118 }
5119 memcpy(&module->imp[module->imp_size + r], &submodule->imp[i], sizeof *submodule->imp);
5120 module->imp[module->imp_size + r].external = 1;
5121 r++;
5122 }
5123 }
5124 module->imp_size += r;
5125 }
5126
5127 /* propagate imports into the main module */
5128 for (i = r = 0; i < submodule->inc_size; i++) {
5129 for (j = 0; j < module->inc_size; j++) {
5130 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5131 break;
5132 }
5133 }
5134 if (j == module->inc_size) {
5135 /* new include */
5136 r++;
5137 }
5138 }
5139
5140 if (r) {
5141 aux_inc = realloc(module->inc, (module->inc_size + r) * sizeof *module->inc);
5142 if (!aux_inc) {
5143 LOGMEM;
5144 goto error;
5145 }
5146 module->inc = aux_inc;
5147 for (i = r = 0; i < submodule->inc_size; i++) {
5148 for (j = 0; j < module->inc_size; j++) {
5149 if (submodule->inc[i].submodule == module->inc[j].submodule) {
5150 break;
5151 }
5152 }
5153 if (j == module->inc_size) {
5154 /* new include */
5155 memcpy(&module->inc[module->inc_size + r], &submodule->inc[i], sizeof *submodule->inc);
5156 module->inc[module->inc_size + r].external = 1;
5157 r++;
5158 }
5159 }
5160 module->inc_size += r;
5161 }
5162 }
5163
Radek Krejcif5be10f2015-06-16 13:29:36 +02005164 /* process data nodes. Start with groupings to allow uses
Radek Krejcic071c542016-01-27 14:57:51 +01005165 * refer to them. Submodule's data nodes are stored in the
5166 * main module data tree.
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005167 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005168 LY_TREE_FOR_SAFE(grps.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005169 node = read_yin_grouping(trg, NULL, child, 0, unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +02005170 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005171 goto error;
5172 }
Radek Krejci74705112015-06-05 10:25:44 +02005173
Michal Vasko345da0a2015-12-02 10:35:55 +01005174 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005175 }
Radek Krejci74705112015-06-05 10:25:44 +02005176
Radek Krejcif5be10f2015-06-16 13:29:36 +02005177 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02005178 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02005179
Radek Krejci1d82ef62015-08-07 14:44:40 +02005180 if (!strcmp(child->name, "container")) {
5181 node = read_yin_container(module, NULL, child, 1, unres);
5182 } else if (!strcmp(child->name, "leaf-list")) {
5183 node = read_yin_leaflist(module, NULL, child, 1, unres);
5184 } else if (!strcmp(child->name, "leaf")) {
5185 node = read_yin_leaf(module, NULL, child, 1, unres);
5186 } else if (!strcmp(child->name, "list")) {
5187 node = read_yin_list(module, NULL, child, 1, unres);
5188 } else if (!strcmp(child->name, "choice")) {
5189 node = read_yin_choice(module, NULL, child, 1, unres);
5190 } else if (!strcmp(child->name, "uses")) {
5191 node = read_yin_uses(module, NULL, child, 1, unres);
5192 } else if (!strcmp(child->name, "anyxml")) {
5193 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005194 } else if (!strcmp(child->name, "rpc")) {
5195 node = read_yin_rpc(module, NULL, child, 0, unres);
5196 } else if (!strcmp(child->name, "notification")) {
5197 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005198 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005199 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005200 goto error;
5201 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005202
Michal Vasko345da0a2015-12-02 10:35:55 +01005203 lyxml_free(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005205
Michal Vasko2f7925f2015-10-21 15:06:56 +02005206 /* ... and finally augments (last, so we can augment our data, for instance) */
5207 LY_TREE_FOR_SAFE(augs.child, next, child) {
Radek Krejcic071c542016-01-27 14:57:51 +01005208 r = fill_yin_augment(trg, NULL, child, &trg->augment[trg->augment_size], unres);
5209 trg->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005210
Michal Vasko2f7925f2015-10-21 15:06:56 +02005211 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005212 goto error;
5213 }
Michal Vasko345da0a2015-12-02 10:35:55 +01005214 lyxml_free(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005215 }
5216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005217 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005218
5219error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005220 /* cleanup */
5221 while (root.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005222 lyxml_free(module->ctx, root.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005223 }
5224 while (grps.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005225 lyxml_free(module->ctx, grps.child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005226 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005227 while (augs.child) {
Michal Vasko345da0a2015-12-02 10:35:55 +01005228 lyxml_free(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005229 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005231 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005232}
5233
Michal Vasko0d343d12015-08-24 14:57:36 +02005234/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005235struct lys_submodule *
Radek Krejcic071c542016-01-27 14:57:51 +01005236yin_read_submodule(struct lys_module *module, const char *data, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005237{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005238 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005239 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005240 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005242 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005243
Radek Krejci722b0072016-02-01 17:09:45 +01005244 yin = lyxml_parse_mem(module->ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005245 if (!yin) {
5246 return NULL;
5247 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005249 /* check root element */
5250 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005251 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005252 goto error;
5253 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005255 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005256 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005257 goto error;
5258 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005260 submodule = calloc(1, sizeof *submodule);
5261 if (!submodule) {
5262 LOGMEM;
5263 goto error;
5264 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005266 submodule->ctx = module->ctx;
5267 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5268 submodule->type = 1;
5269 submodule->belongsto = module;
Radek Krejciefaeba32015-05-27 14:30:57 +02005270
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005271 LOGVRB("Reading submodule %s", submodule->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005272 if (read_sub_module(module, submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005273 goto error;
5274 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005276 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005277 lyxml_free(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005278
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005279 LOGVRB("Submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005281 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005282
5283error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005284 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005285 unres_schema_free((struct lys_module *)submodule, &unres);
Michal Vasko345da0a2015-12-02 10:35:55 +01005286 lyxml_free(module->ctx, yin);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005287 lys_submodule_free(submodule, 0, NULL);
Radek Krejciefaeba32015-05-27 14:30:57 +02005288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005289 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005290}
5291
Michal Vasko0d343d12015-08-24 14:57:36 +02005292/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005293struct lys_module *
Radek Krejcic071c542016-01-27 14:57:51 +01005294yin_read_module(struct ly_ctx *ctx, const char *data, int implement)
Radek Krejciefaeba32015-05-27 14:30:57 +02005295{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005296 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005297 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejcic071c542016-01-27 14:57:51 +01005298 struct unres_schema *unres;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005299 const char *value;
5300 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005301
Radek Krejcic071c542016-01-27 14:57:51 +01005302 unres = calloc(1, sizeof *unres);
5303 if (!unres) {
5304 LOGMEM;
5305 return NULL;
5306 }
5307
Radek Krejci722b0072016-02-01 17:09:45 +01005308 yin = lyxml_parse_mem(ctx, data, 0);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005309 if (!yin) {
Radek Krejcic071c542016-01-27 14:57:51 +01005310 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005311 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005313 /* check root element */
5314 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005315 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005316 goto error;
5317 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005319 GETVAL(value, yin, "name");
Radek Krejcic6556022016-01-27 15:16:45 +01005320 if (lyp_check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005321 goto error;
5322 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005324 module = calloc(1, sizeof *module);
5325 if (!module) {
5326 LOGMEM;
5327 goto error;
5328 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005330 module->ctx = ctx;
5331 module->name = lydict_insert(ctx, value, strlen(value));
5332 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005333 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005334
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005335 LOGVRB("Reading module %s", module->name);
Radek Krejcic071c542016-01-27 14:57:51 +01005336 if (read_sub_module(module, NULL, yin, unres)) {
5337 goto error;
5338 }
5339
5340 /* resolve rest of unres items */
5341 if (unres->count && resolve_unres_schema(module, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005342 goto error;
5343 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005345 /* add to the context's list of modules */
5346 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005347 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005348 if (!newlist) {
5349 LOGMEM;
5350 goto error;
5351 }
5352 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5353 newlist[i] = NULL;
5354 }
5355 ctx->models.size *= 2;
5356 ctx->models.list = newlist;
5357 }
5358 for (i = 0; ctx->models.list[i]; i++) {
5359 /* check name (name/revision) and namespace uniqueness */
5360 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005361 if (ctx->models.list[i]->rev_size == module->rev_size) {
5362 /* both have the same number of revisions */
5363 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5364 /* both have the same revision -> we already have the same module */
5365 /* so free the new one and update the old one's implement flag if needed */
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005366 LOGVRB("Module %s already in context", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005367
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005368 lys_free(module, 0, NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01005369 module = ctx->models.list[i];
5370 if (implement && !module->implemented) {
5371 lyp_set_implemented(module);
Radek Krejci63a91a92015-07-29 13:31:04 +02005372 }
Radek Krejcic071c542016-01-27 14:57:51 +01005373
5374 goto success;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005375 }
5376 }
Radek Krejcif647e612015-07-30 11:36:07 +02005377 /* else (both elses) keep searching, for now the caller is just adding
5378 * another revision of an already present schema
5379 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005380 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
5381 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
5382 ctx->models.list[i]->name, module->name, module->ns);
5383 goto error;
5384 }
5385 }
5386 ctx->models.list[i] = module;
5387 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005388 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005389
Radek Krejcic071c542016-01-27 14:57:51 +01005390success:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005391 /* cleanup */
Michal Vasko345da0a2015-12-02 10:35:55 +01005392 lyxml_free(ctx, yin);
Radek Krejcic071c542016-01-27 14:57:51 +01005393 unres_schema_free(NULL, &unres);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005394
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005395 LOGVRB("Module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005397 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005398
5399error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005400 /* cleanup */
Radek Krejcic071c542016-01-27 14:57:51 +01005401 unres_schema_free(module, &unres);
Radek Krejcifa0b5e02016-02-04 13:57:03 +01005402 lys_free(module, 0, NULL);
Radek Krejcic071c542016-01-27 14:57:51 +01005403 lyxml_free(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005404
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005405 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005406}