blob: a266a795e691658712aff772409a59b0cb70991b [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"
Michal Vaskofcdac172015-10-07 09:35:05 +020036#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020037#include "dict.h"
38#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020039#include "resolve.h"
40#include "tree_internal.h"
Radek Krejcic6704c82015-10-06 11:12:45 +020041#include "xml_private.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020042
Radek Krejcice7fb782015-05-29 16:52:34 +020043enum LY_IDENT {
Radek Krejci994b6f62015-06-18 16:47:27 +020044 LY_IDENT_SIMPLE, /* only syntax rules */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020045 LY_IDENT_FEATURE,
46 LY_IDENT_IDENTITY,
47 LY_IDENT_TYPE,
48 LY_IDENT_NODE,
Radek Krejci994b6f62015-06-18 16:47:27 +020049 LY_IDENT_NAME, /* uniqueness across the siblings */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020050 LY_IDENT_PREFIX
Radek Krejcice7fb782015-05-29 16:52:34 +020051};
52
Radek Krejcice7fb782015-05-29 16:52:34 +020053#define GETVAL(value, node, arg) \
54 value = lyxml_get_attr(node, arg, NULL); \
55 if (!value) { \
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020056 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
Radek Krejcice7fb782015-05-29 16:52:34 +020057 goto error; \
58 }
59
Radek Krejcib388c152015-06-04 17:03:03 +020060#define OPT_IDENT 0x01
61#define OPT_CONFIG 0x02
62#define OPT_MODULE 0x04
63#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020064#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020065static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020066
Radek Krejcib8048692015-08-05 13:36:34 +020067static 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 +020068 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020069static 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 +020070 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020071static 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 +020072 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020073static 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 +020074 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020075static 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 +020076 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020077static 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 +020078 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020079static 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 +020080 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020081static 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 +020082 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020083static 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 +020084 int resolve, struct unres_schema *unres);
85static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020086
Michal Vasko0d343d12015-08-24 14:57:36 +020087/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020088static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020089dup_typedef_check(const char *type, struct lys_tpdf *tpdf, int size)
Radek Krejcieac35532015-05-31 19:09:15 +020090{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020091 int i;
Radek Krejcieac35532015-05-31 19:09:15 +020092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093 for (i = 0; i < size; i++) {
94 if (!strcmp(type, tpdf[i].name)) {
95 /* name collision */
96 return EXIT_FAILURE;
97 }
98 }
Radek Krejcieac35532015-05-31 19:09:15 +020099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200100 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200101}
102
Michal Vasko0d343d12015-08-24 14:57:36 +0200103/* does not log */
Radek Krejcib05774c2015-06-18 13:52:59 +0200104static int
Radek Krejcib8048692015-08-05 13:36:34 +0200105dup_feature_check(const char *id, struct lys_module *module)
Radek Krejcib05774c2015-06-18 13:52:59 +0200106{
107 int i;
108
109 for (i = 0; i < module->features_size; i++) {
110 if (!strcmp(id, module->features[i].name)) {
111 return EXIT_FAILURE;
112 }
113 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200114
115 return EXIT_SUCCESS;
Radek Krejcib05774c2015-06-18 13:52:59 +0200116}
117
Michal Vasko0d343d12015-08-24 14:57:36 +0200118/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119static int
Radek Krejcib8048692015-08-05 13:36:34 +0200120dup_prefix_check(const char *prefix, struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200121{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200122 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200124 if (!module->type && module->prefix && !strcmp(module->prefix, prefix)) {
125 return EXIT_FAILURE;
126 }
127 for (i = 0; i < module->imp_size; i++) {
128 if (!strcmp(module->imp[i].prefix, prefix)) {
129 return EXIT_FAILURE;
130 }
131 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200133 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200134}
135
Michal Vasko0d343d12015-08-24 14:57:36 +0200136/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200137static int
138check_identifier(const char *id, enum LY_IDENT type, unsigned int line,
Radek Krejcib8048692015-08-05 13:36:34 +0200139 struct lys_module *module, struct lys_node *parent)
Radek Krejcice7fb782015-05-29 16:52:34 +0200140{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200141 int i;
142 int size;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200143 struct lys_tpdf *tpdf;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200144 struct lys_node *node;
Radek Krejcice7fb782015-05-29 16:52:34 +0200145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200146 assert(id);
Radek Krejcice7fb782015-05-29 16:52:34 +0200147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 /* check id syntax */
149 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200150 LOGVAL(LYE_INID, line, id, "invalid start character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200151 return EXIT_FAILURE;
152 }
153 for (i = 1; id[i]; i++) {
154 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
155 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200156 LOGVAL(LYE_INID, line, id, "invalid character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200157 return EXIT_FAILURE;
158 }
159 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200161 if (i > 64) {
162 LOGWRN("Identifier \"%s\" is long, you should use something shorter.", id);
163 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200165 switch (type) {
166 case LY_IDENT_NAME:
167 /* check uniqueness of the node within its siblings */
168 if (!parent) {
169 break;
170 }
Radek Krejcib4cf2022015-06-03 14:40:05 +0200171
Radek Krejci1d82ef62015-08-07 14:44:40 +0200172 LY_TREE_FOR(parent->child, node) {
173 if (node->name == id) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200174 LOGVAL(LYE_INID, line, id, "name duplication");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200175 return EXIT_FAILURE;
176 }
177 }
178 break;
179 case LY_IDENT_TYPE:
180 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200182 /* check collision with the built-in types */
183 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
184 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
185 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
186 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
187 !strcmp(id, "int8") || !strcmp(id, "int16") ||
188 !strcmp(id, "int32") || !strcmp(id, "int64") ||
189 !strcmp(id, "leafref") || !strcmp(id, "string") ||
190 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
191 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200192 LOGVAL(LYE_SPEC, line, "Typedef name duplicates built-in type.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200193 return EXIT_FAILURE;
194 }
Radek Krejcieac35532015-05-31 19:09:15 +0200195
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200196 /* check locally scoped typedefs (avoid name shadowing) */
197 for (; parent; parent = parent->parent) {
198 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200199 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +0200200 size = ((struct lys_node_container *)parent)->tpdf_size;
201 tpdf = ((struct lys_node_container *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200202 break;
Radek Krejci76512572015-08-04 09:47:08 +0200203 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +0200204 size = ((struct lys_node_list *)parent)->tpdf_size;
205 tpdf = ((struct lys_node_list *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200206 break;
Radek Krejci76512572015-08-04 09:47:08 +0200207 case LYS_GROUPING:
Radek Krejcib8048692015-08-05 13:36:34 +0200208 size = ((struct lys_node_grp *)parent)->tpdf_size;
209 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200210 break;
211 default:
212 continue;
213 }
Radek Krejcieac35532015-05-31 19:09:15 +0200214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200215 if (dup_typedef_check(id, tpdf, size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200216 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200217 return EXIT_FAILURE;
218 }
219 }
Radek Krejcieac35532015-05-31 19:09:15 +0200220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200221 /* check top-level names */
222 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200223 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200224 return EXIT_FAILURE;
225 }
Radek Krejcieac35532015-05-31 19:09:15 +0200226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200227 /* check submodule's top-level names */
228 for (i = 0; i < module->inc_size; i++) {
229 if (dup_typedef_check(id, module->inc[i].submodule->tpdf, module->inc[i].submodule->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200230 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200231 return EXIT_FAILURE;
232 }
233 }
Radek Krejcieac35532015-05-31 19:09:15 +0200234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200235 /* check top-level names in the main module */
236 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +0200237 if (dup_typedef_check(id, ((struct lys_submodule *)module)->belongsto->tpdf,
238 ((struct lys_submodule *)module)->belongsto->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200239 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200240 return EXIT_FAILURE;
241 }
242 }
Radek Krejcieac35532015-05-31 19:09:15 +0200243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200244 break;
245 case LY_IDENT_PREFIX:
246 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200248 if (module->type) {
249 /* go to the main module */
Radek Krejcib8048692015-08-05 13:36:34 +0200250 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200251 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200253 /* check the main module itself */
254 if (dup_prefix_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200255 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200256 return EXIT_FAILURE;
257 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200259 /* and all its submodules */
260 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200261 if (dup_prefix_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200262 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200263 return EXIT_FAILURE;
264 }
265 }
266 break;
Radek Krejcib05774c2015-06-18 13:52:59 +0200267 case LY_IDENT_FEATURE:
268 assert(module);
269
270 /* check feature name uniqness*/
Radek Krejci49babf32015-06-18 13:56:17 +0200271 /* check features in the current module */
Radek Krejcib05774c2015-06-18 13:52:59 +0200272 if (dup_feature_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200273 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200274 return EXIT_FAILURE;
275 }
276
277 /* and all its submodules */
278 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200279 if (dup_feature_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200280 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200281 return EXIT_FAILURE;
282 }
283 }
284 break;
285
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200286 default:
287 /* no check required */
288 break;
289 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200291 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200292}
293
Michal Vasko0d343d12015-08-24 14:57:36 +0200294/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200295static int
Radek Krejci1d82ef62015-08-07 14:44:40 +0200296check_mandatory(struct lys_node *node)
Radek Krejci3de29a72015-06-16 15:23:03 +0200297{
Radek Krejci76512572015-08-04 09:47:08 +0200298 struct lys_node *child;
Radek Krejci3de29a72015-06-16 15:23:03 +0200299
Radek Krejci1d82ef62015-08-07 14:44:40 +0200300 assert(node);
Radek Krejci3de29a72015-06-16 15:23:03 +0200301
Radek Krejci1d82ef62015-08-07 14:44:40 +0200302 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci3de29a72015-06-16 15:23:03 +0200303 return EXIT_FAILURE;
304 }
305
Radek Krejci1d82ef62015-08-07 14:44:40 +0200306 if (node->nodetype == LYS_CASE || node->nodetype == LYS_CHOICE) {
307 LY_TREE_FOR(node->child, child) {
Radek Krejcifd0bb0a2015-06-18 13:18:24 +0200308 if (check_mandatory(child)) {
309 return EXIT_FAILURE;
310 }
Radek Krejci3de29a72015-06-16 15:23:03 +0200311 }
312 }
313
314 return EXIT_SUCCESS;
315}
316
Michal Vasko0d343d12015-08-24 14:57:36 +0200317/* logs directly */
Radek Krejci3de29a72015-06-16 15:23:03 +0200318static int
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200319check_date(const char *date, unsigned int line)
Radek Krejcice7fb782015-05-29 16:52:34 +0200320{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 assert(date);
Radek Krejcice7fb782015-05-29 16:52:34 +0200324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200325 if (strlen(date) != LY_REV_SIZE - 1) {
326 goto error;
327 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200329 for (i = 0; i < LY_REV_SIZE - 1; i++) {
330 if (i == 4 || i == 7) {
331 if (date[i] != '-') {
332 goto error;
333 }
334 } else if (!isdigit(date[i])) {
335 goto error;
336 }
337 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200339 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200340
341error:
342
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200343 LOGVAL(LYE_INDATE, line, date);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200344 return EXIT_FAILURE;
Radek Krejcice7fb782015-05-29 16:52:34 +0200345}
346
Michal Vasko0d343d12015-08-24 14:57:36 +0200347/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200348static const char *
349read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200350{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200351 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200352
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 /* there should be <text> child */
354 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
355 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
356 } else if (node->child->content) {
357 len = strlen(node->child->content);
358 return lydict_insert(ctx, node->child->content, len);
359 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200360
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200361 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200362 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200363}
364
Michal Vasko0d343d12015-08-24 14:57:36 +0200365/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200366static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200367fill_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 +0200368{
Radek Krejci73adb602015-07-02 18:07:40 +0200369 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200370 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200371
Michal Vasko4cfcd252015-08-03 14:31:10 +0200372 GETVAL(value, yin, "name");
373 ident->name = lydict_insert(module->ctx, value, 0);
374
Radek Krejci76512572015-08-04 09:47:08 +0200375 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200376 return EXIT_FAILURE;
377 }
Radek Krejci04581c62015-05-22 21:24:00 +0200378
Radek Krejci73adb602015-07-02 18:07:40 +0200379 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200380 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
381 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200382 continue;
383 }
384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200385 if (!strcmp(node->name, "base")) {
386 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200387 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200388 return EXIT_FAILURE;
389 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200390 GETVAL(value, node, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200391 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200392 return EXIT_FAILURE;
393 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200394 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200395 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 return EXIT_FAILURE;
397 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398 }
Radek Krejci04581c62015-05-22 21:24:00 +0200399
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200400error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200402}
403
Michal Vasko0d343d12015-08-24 14:57:36 +0200404/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200405static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200406read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200407{
Radek Krejci73adb602015-07-02 18:07:40 +0200408 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200409 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200410
Radek Krejci73adb602015-07-02 18:07:40 +0200411 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200412 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
413 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200414 continue;
415 }
416
Radek Krejci41726f92015-06-19 13:11:05 +0200417 if (!strcmp(child->name, "description")) {
418 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200419 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200420 return EXIT_FAILURE;
421 }
422 restr->dsc = read_yin_subnode(ctx, child, "text");
423 if (!restr->dsc) {
424 return EXIT_FAILURE;
425 }
426 } else if (!strcmp(child->name, "reference")) {
427 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200428 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200429 return EXIT_FAILURE;
430 }
431 restr->ref = read_yin_subnode(ctx, child, "text");
432 if (!restr->ref) {
433 return EXIT_FAILURE;
434 }
435 } else if (!strcmp(child->name, "error-app-tag")) {
436 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200437 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200438 return EXIT_FAILURE;
439 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200440 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200441 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200442 } else if (!strcmp(child->name, "error-message")) {
443 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200444 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200445 return EXIT_FAILURE;
446 }
447 restr->emsg = read_yin_subnode(ctx, child, "value");
448 if (!restr->emsg) {
449 return EXIT_FAILURE;
450 }
451 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200452 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200453 return EXIT_FAILURE;
454 }
Radek Krejci41726f92015-06-19 13:11:05 +0200455 }
456
457 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200458
459error:
460 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200461}
462
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200463/* logs directly */
Radek Krejci41726f92015-06-19 13:11:05 +0200464static int
Radek Krejcib8048692015-08-05 13:36:34 +0200465fill_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 +0200466 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200467{
Michal Vasko69068852015-07-13 14:34:31 +0200468#define REGEX_ERR_LEN 128
Michal Vasko0fb82c62015-10-20 13:41:53 +0200469 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200470 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200471 struct lys_restr **restr;
472 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200473 pcre *precomp;
474 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200475 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200476 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200477
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200478 GETVAL(value, yin, "name");
Michal Vasko0fb82c62015-10-20 13:41:53 +0200479 value = transform_expr_xml2json(module->ctx, value, yin, 1);
480 if (!value) {
481 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482 }
Michal Vasko0fb82c62015-10-20 13:41:53 +0200483 type->module_name = value;
Radek Krejci667b97f2015-05-25 15:03:30 +0200484
Michal Vasko0fb82c62015-10-20 13:41:53 +0200485 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200486 if (rc == -1) {
Michal Vasko0fb82c62015-10-20 13:41:53 +0200487 LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200488 goto error;
489 } else if (rc == EXIT_FAILURE) {
490 /* HACK for unres */
491 type->der = (struct lys_tpdf *)parent;
492 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200493 if (rc == -1) {
494 goto error;
Michal Vaskof7eee892015-08-24 15:03:11 +0200495 } else {
496 return EXIT_SUCCESS;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200497 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200498 }
499 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200500
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200502 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200503 /* RFC 6020 9.7.4 - bit */
504
505 /* get bit specifications, at least one must be present */
506 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200507 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
508 /* garbage */
509 lyxml_free_elem(module->ctx, node);
510 continue;
511 }
512
Radek Krejci994b6f62015-06-18 16:47:27 +0200513 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200514 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200515 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200516 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200517 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200518 }
519 }
Radek Krejciac781922015-07-09 15:35:14 +0200520 if (!type->der->type.der && !type->info.bits.count) {
521 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200522 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200523 goto error;
524 }
Radek Krejciac781922015-07-09 15:35:14 +0200525 if (type->der->type.der && type->info.bits.count) {
526 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200527 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200528 goto error;
529 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200530
531 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200532 p = 0;
533 i = -1;
534 LY_TREE_FOR(yin->child, next) {
535 i++;
536
537 GETVAL(value, next, "name");
538 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200539 goto error;
540 }
541 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200542 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200543 type->info.bits.count = i + 1;
544 goto error;
545 }
546
547 /* check the name uniqueness */
548 for (j = 0; j < i; j++) {
549 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200550 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200551 type->info.bits.count = i + 1;
552 goto error;
553 }
554 }
555
Radek Krejci0d70c372015-07-02 16:23:10 +0200556 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200557 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200558 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
559 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200561 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200562
Radek Krejci0d70c372015-07-02 16:23:10 +0200563 if (!strcmp(node->name, "position")) {
564 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200565 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200566
567 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200568 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200569 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200570 type->info.bits.count = i + 1;
571 goto error;
572 }
573 type->info.bits.bit[i].pos = (uint32_t)p_;
574
575 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200576 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200577 p = type->info.bits.bit[i].pos;
578 p++;
579 } else {
580 /* check that the value is unique */
581 for (j = 0; j < i; j++) {
582 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200583 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 +0200584 type->info.bits.count = i + 1;
585 goto error;
586 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200587 }
588 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200589 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200590 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200591 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200592 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200593 }
594 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200595 /* assign value automatically */
596 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200597 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200598 type->info.bits.count = i + 1;
599 goto error;
600 }
601 type->info.bits.bit[i].pos = (uint32_t)p;
602 p++;
603 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200604
605 /* keep them ordered by position */
606 j = i;
607 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
608 /* switch them */
609 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
610 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
611 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
612 j--;
613 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200614 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200616
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200617 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200618 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200619 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200620 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
621 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200622 continue;
623 }
624
Radek Krejcif9401c32015-06-26 16:47:36 +0200625 if (!strcmp(node->name, "range")) {
626 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200627 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200628 goto error;
629 }
630
631 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200632 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200633 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200634 goto error;
635 }
636 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
637 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
638
639 /* get possible substatements */
640 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
641 goto error;
642 }
643 } else if (!strcmp(node->name, "fraction-digits")) {
644 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200645 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200646 goto error;
647 }
648 GETVAL(value, node, "value");
649 v = strtol(value, NULL, 10);
650
651 /* range check */
652 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200653 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200654 goto error;
655 }
656 type->info.dec64.dig = (uint8_t)v;
657 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200658 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200659 goto error;
660 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200661 }
662
663 /* mandatory sub-statement(s) check */
664 if (!type->info.dec64.dig && !type->der->type.der) {
665 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200666 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200667 goto error;
668 }
Radek Krejci7511f402015-07-10 09:56:30 +0200669 if (type->info.dec64.dig && type->der->type.der) {
670 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200671 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200672 goto error;
673 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200676 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200677 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200678
Radek Krejci994b6f62015-06-18 16:47:27 +0200679 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200680 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200681 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
682 /* garbage */
683 lyxml_free_elem(module->ctx, node);
684 continue;
685 }
686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200687 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200688 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200689 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200690 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200691 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692 }
693 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200694 if (!type->der->type.der && !type->info.enums.count) {
695 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200696 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200697 goto error;
698 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200699 if (type->der->type.der && type->info.enums.count) {
700 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200701 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200702 goto error;
703 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200704
Radek Krejci1574a8d2015-08-03 14:16:52 +0200705 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200706 v = 0;
707 i = -1;
708 LY_TREE_FOR(yin->child, next) {
709 i++;
710
711 GETVAL(value, next, "name");
712 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200713 goto error;
714 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200715 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200716 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 type->info.enums.count = i + 1;
718 goto error;
719 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200721 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200722 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200723 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200724 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 type->info.enums.count = i + 1;
726 goto error;
727 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200728
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 /* check the name uniqueness */
730 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200731 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200732 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 type->info.enums.count = i + 1;
734 goto error;
735 }
736 }
Radek Krejci04581c62015-05-22 21:24:00 +0200737
Radek Krejci0d70c372015-07-02 16:23:10 +0200738 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200739 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200740 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
741 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200742 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200743 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200744
Radek Krejci0d70c372015-07-02 16:23:10 +0200745 if (!strcmp(node->name, "value")) {
746 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200747 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200748
749 /* range check */
750 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200751 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200752 type->info.enums.count = i + 1;
753 goto error;
754 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200755 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200756
757 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200758 if (type->info.enums.enm[i].value > v) {
759 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200760 v++;
761 } else {
762 /* check that the value is unique */
763 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200764 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200765 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200766 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200767 type->info.enums.count = i + 1;
768 goto error;
769 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200770 }
771 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200772 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200773 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200774 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200775 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200776 }
777 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200778 /* assign value automatically */
779 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200780 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 type->info.enums.count = i + 1;
782 goto error;
783 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200784 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200785 v++;
786 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200787 }
788 break;
789
790 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200791 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200792
793 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200794 LY_TREE_FOR_SAFE(yin->child, next, node) {
795 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
796 /* garbage */
797 lyxml_free_elem(module->ctx, node);
798 continue;
799 }
800
801 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200802 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200803 goto error;
804 }
805 }
806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200807 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200808 if (type->der->type.der) {
809 /* this is just a derived type with no base specified/required */
810 break;
811 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200812 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200813 goto error;
814 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200815 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200816 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 goto error;
818 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200819 GETVAL(value, yin->child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200820 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200821 goto error;
822 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200823 break;
824
825 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200826 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200827 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200828 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
829 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200830 continue;
831 }
832
Radek Krejciaf351422015-06-19 14:49:38 +0200833 if (!strcmp(node->name, "require-instance")) {
834 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200835 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200836 goto error;
837 }
838 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200839 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200840 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200841 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200842 type->info.inst.req = -1;
843 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200844 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200845 goto error;
846 }
847 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200848 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200849 goto error;
850 }
Radek Krejciaf351422015-06-19 14:49:38 +0200851 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 break;
854
Radek Krejcif2860132015-06-20 12:37:20 +0200855 case LY_TYPE_BINARY:
856 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200857 case LY_TYPE_INT8:
858 case LY_TYPE_INT16:
859 case LY_TYPE_INT32:
860 case LY_TYPE_INT64:
861 case LY_TYPE_UINT8:
862 case LY_TYPE_UINT16:
863 case LY_TYPE_UINT32:
864 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200865 /* RFC 6020 9.2.4 - range */
866
867 /* length and range are actually the same restriction, so process
868 * them by this common code, we just need to differ the name and
869 * structure where the information will be stored
870 */
871 if (type->base == LY_TYPE_BINARY) {
872 restr = &type->info.binary.length;
873 name = "length";
874 } else {
875 restr = &type->info.num.range;
876 name = "range";
877 }
878
Radek Krejci73adb602015-07-02 18:07:40 +0200879 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200880 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
881 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200882 continue;
883 }
884
Radek Krejcif2860132015-06-20 12:37:20 +0200885 if (!strcmp(node->name, name)) {
886 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200887 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200888 goto error;
889 }
890
891 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200892 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200893 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200894 goto error;
895 }
896 *restr = calloc(1, sizeof **restr);
897 (*restr)->expr = lydict_insert(module->ctx, value, 0);
898
899 /* get possible substatements */
900 if (read_restr_substmt(module->ctx, *restr, node)) {
901 goto error;
902 }
903 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200904 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200905 goto error;
906 }
Radek Krejcif2860132015-06-20 12:37:20 +0200907 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200908 break;
909
910 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200911 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200912 LY_TREE_FOR(yin->child, 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 Krejcidc4c1412015-06-19 15:39:54 +0200918 if (!strcmp(node->name, "path")) {
919 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200920 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200921 goto error;
922 }
923
924 GETVAL(value, node, "value");
Michal Vasko0fb82c62015-10-20 13:41:53 +0200925 /* store in the JSON format */
926 type->info.lref.path = transform_expr_xml2json(module->ctx, value, node, 1);
927 if (!type->info.lref.path) {
928 goto error;
929 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200930 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200931 goto error;
932 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200933
Radek Krejcidc4c1412015-06-19 15:39:54 +0200934 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200935 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200936 goto error;
937 }
Radek Krejci73adb602015-07-02 18:07:40 +0200938 }
939
940 if (!type->info.lref.path) {
941 if (type->der->type.der) {
942 /* this is just a derived type with no path specified/required */
943 break;
944 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200945 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200946 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 break;
949
950 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200951 /* RFC 6020 9.4.4 - length */
952 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200953 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200954 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200955 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
956 /* garbage */
957 lyxml_free_elem(module->ctx, node);
958 continue;
959 }
960
Radek Krejci3733a802015-06-19 13:43:21 +0200961 if (!strcmp(node->name, "length")) {
962 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200963 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200964 goto error;
965 }
966
967 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200968 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200969 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200970 goto error;
971 }
972 type->info.str.length = calloc(1, sizeof *type->info.str.length);
973 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
974
Radek Krejci5fbc9162015-06-19 14:11:11 +0200975 /* get possible sub-statements */
976 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200977 goto error;
978 }
Radek Krejci82d971d2015-06-19 14:20:50 +0200979 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200980 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200981 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200982 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200983 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200984 goto error;
985 }
986 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200987 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200988 if (i) {
989 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
990 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +0200991 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200992
993 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200994 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
995 if (!precomp) {
996 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200997 free(type->info.str.patterns);
998 goto error;
999 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +02001000 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +02001001
Radek Krejci73adb602015-07-02 18:07:40 +02001002 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001003
1004 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +02001005 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +02001006 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001007 goto error;
1008 }
Radek Krejci73adb602015-07-02 18:07:40 +02001009 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001010 }
1011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 break;
1013
1014 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001015 /* RFC 6020 7.4 - type */
1016 /* count number of types in union */
1017 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001018 LY_TREE_FOR_SAFE(yin->child, next, node) {
1019 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1020 /* garbage */
1021 lyxml_free_elem(module->ctx, node);
1022 continue;
1023 }
1024
Radek Krejcie4c366b2015-07-02 10:11:31 +02001025 if (!strcmp(node->name, "type")) {
1026 i++;
1027 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001028 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001029 goto error;
1030 }
1031 }
1032
1033 if (!i) {
1034 if (type->der->type.der) {
1035 /* this is just a derived type with no base specified/required */
1036 break;
1037 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001038 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001039 goto error;
1040 }
1041
1042 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001043 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001044 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001045 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001046 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001047 goto error;
1048 }
1049 type->info.uni.count++;
1050
1051 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001052 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001053 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001054 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001055 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001056 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001057 goto error;
1058 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001060 break;
1061
1062 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001063 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1065 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001066 LY_TREE_FOR(yin->child, node) {
1067 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001068 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001069 goto error;
1070 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001071 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 break;
1073 }
1074
1075 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001076
1077error:
1078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001079 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001080}
1081
Michal Vasko0d343d12015-08-24 14:57:36 +02001082/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001084fill_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 +02001085{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001087 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001088 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 GETVAL(value, yin, "name");
1091 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1092 goto error;
1093 }
1094 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001097 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 goto error;
1099 }
Radek Krejcieac35532015-05-31 19:09:15 +02001100
Radek Krejci73adb602015-07-02 18:07:40 +02001101 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001102 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1103 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001104 continue;
1105 }
1106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001108 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001109 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 goto error;
1111 }
Radek Krejci73adb602015-07-02 18:07:40 +02001112 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1113 goto error;
1114 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001115 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 } else if (!strcmp(node->name, "default")) {
1117 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001118 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 goto error;
1120 }
1121 GETVAL(value, node, "value");
1122 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 } else if (!strcmp(node->name, "units")) {
1125 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001126 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 goto error;
1128 }
1129 GETVAL(value, node, "name");
1130 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1131 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001132 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 goto error;
1134 }
1135 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001138 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001139 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 goto error;
1141 }
Radek Krejcieac35532015-05-31 19:09:15 +02001142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001143 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001144 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001145 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001146 goto error;
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001151
1152error:
1153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001155}
1156
Michal Vasko0d343d12015-08-24 14:57:36 +02001157/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001158static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001159fill_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 +02001160{
1161 const char *value;
1162 struct lyxml_elem *child, *next;
1163 int c = 0;
1164
Radek Krejcib05774c2015-06-18 13:52:59 +02001165 GETVAL(value, yin, "name");
1166 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1167 goto error;
1168 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001169 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001170 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001171
Radek Krejci76512572015-08-04 09:47:08 +02001172 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001173 goto error;
1174 }
1175
1176 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001177 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1178 /* garbage */
1179 lyxml_free_elem(module->ctx, child);
1180 continue;
1181 }
1182
Radek Krejci3cf9e222015-06-18 11:37:50 +02001183 if (!strcmp(child->name, "if-feature")) {
1184 c++;
1185 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001186 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001187 goto error;
1188 }
1189 }
1190
1191 if (c) {
1192 f->features = calloc(c, sizeof *f->features);
1193 }
Radek Krejci73adb602015-07-02 18:07:40 +02001194 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001195 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02001196 if (unres_schema_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001197 goto error;
1198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001199 }
1200
Radek Krejci3cf9e222015-06-18 11:37:50 +02001201 return EXIT_SUCCESS;
1202
1203error:
1204
1205 return EXIT_FAILURE;
1206}
1207
Michal Vasko0d343d12015-08-24 14:57:36 +02001208/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001209static int
Radek Krejcib8048692015-08-05 13:36:34 +02001210fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001211{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 GETVAL(value, yin, "condition");
Michal Vaskof9893382015-10-09 14:03:04 +02001215 must->expr = transform_expr_xml2json(module->ctx, value, yin, 1);
1216 if (!must->expr) {
1217 goto error;
1218 }
Radek Krejci800af702015-06-02 13:46:01 +02001219
Radek Krejci41726f92015-06-19 13:11:05 +02001220 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001221
Radek Krejci41726f92015-06-19 13:11:05 +02001222error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001224 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001225}
1226
Michal Vasko0d343d12015-08-24 14:57:36 +02001227/* logs directly
1228 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001229 * type: 0 - min, 1 - max
1230 */
1231static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001232deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001233{
1234 const char *value;
1235 char *endptr;
1236 unsigned long val;
1237 uint32_t *ui32val;
1238
1239 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001240 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001241 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001242 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001243 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001244 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001245 }
Radek Krejci76512572015-08-04 09:47:08 +02001246 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001247 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001248 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001249 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001250 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001251 }
1252 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001253 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1254 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001255 goto error;
1256 }
1257
1258 GETVAL(value, node, "value");
1259 while (isspace(value[0])) {
1260 value++;
1261 }
1262
1263 /* convert it to uint32_t */
1264 errno = 0;
1265 endptr = NULL;
1266 val = strtoul(value, &endptr, 10);
1267 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001268 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001269 goto error;
1270 }
1271 if (type) {
1272 d->max = (uint32_t)val;
1273 } else {
1274 d->min = (uint32_t)val;
1275 }
1276
1277 if (d->mod == LY_DEVIATE_ADD) {
1278 /* check that there is no current value */
1279 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001280 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1281 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001282 goto error;
1283 }
1284 }
1285
1286 if (d->mod == LY_DEVIATE_DEL) {
1287 /* check values */
1288 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001289 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1290 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001291 goto error;
1292 }
1293 /* remove current min-elements value of the target */
1294 *ui32val = 0;
1295 } else { /* add (already checked) and replace */
1296 /* set new value specified in deviation */
1297 *ui32val = (uint32_t)val;
1298 }
1299
1300 return EXIT_SUCCESS;
1301
1302error:
1303
1304 return EXIT_FAILURE;
1305}
1306
Michal Vasko0d343d12015-08-24 14:57:36 +02001307/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001308static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001309fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001310{
1311 const char *value, **stritem;
1312 struct lyxml_elem *next, *child, *develem;
1313 int c_dev = 0, c_must, c_uniq;
1314 int f_min = 0; /* flags */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001315 int i, j, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001316 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001317 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001318 struct lys_node_choice *choice = NULL;
1319 struct lys_node_leaf *leaf = NULL;
1320 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001321 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001322 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001323 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001324
1325 GETVAL(value, yin, "target-node");
1326 dev->target_name = lydict_insert(module->ctx, value, 0);
1327
1328 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001329 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1330 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001331 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001332 goto error;
1333 }
1334 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001335 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 goto error;
1337 }
1338 /* mark the target module as deviated */
1339 dev->target->module->deviated = 1;
1340
1341 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001342 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1343 /* garbage */
1344 lyxml_free_elem(module->ctx, child);
1345 continue;
1346 }
1347
Radek Krejcieb00f512015-07-01 16:44:58 +02001348 if (!strcmp(child->name, "description")) {
1349 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001350 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001351 goto error;
1352 }
1353 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1354 if (!dev->dsc) {
1355 goto error;
1356 }
1357 } else if (!strcmp(child->name, "reference")) {
1358 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001359 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001360 goto error;
1361 }
1362 dev->ref = read_yin_subnode(module->ctx, child, "text");
1363 if (!dev->ref) {
1364 goto error;
1365 }
1366 } else if (!strcmp(child->name, "deviate")) {
1367 c_dev++;
1368
1369 /* skip lyxml_free_elem() at the end of the loop, node will be
1370 * further processed later
1371 */
1372 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001373
Radek Krejcieb00f512015-07-01 16:44:58 +02001374 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001375 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001376 goto error;
1377 }
1378
1379 lyxml_free_elem(module->ctx, child);
1380 }
1381
1382 if (c_dev) {
1383 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1384 }
1385
1386 LY_TREE_FOR(yin->child, develem) {
1387 /* init */
1388 f_min = 0;
1389 c_must = 0;
1390 c_uniq = 0;
1391
1392 /* get deviation type */
1393 GETVAL(value, develem, "value");
1394 if (!strcmp(value, "not-supported")) {
1395 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1396 /* no property expected in this case */
1397 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001398 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001399 goto error;
1400 }
1401
Radek Krejci5b917642015-07-02 09:03:13 +02001402 /* and neither any other deviate statement is expected,
1403 * not-supported deviation must be the only deviation of the target
1404 */
1405 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001406 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1407 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001408 goto error;
1409 }
1410
1411
Radek Krejcieb00f512015-07-01 16:44:58 +02001412 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001413 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001414 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415
Radek Krejci5b917642015-07-02 09:03:13 +02001416 dev->deviate_size = 1;
1417 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001418 } else if (!strcmp(value, "add")) {
1419 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1420 } else if (!strcmp(value, "replace")) {
1421 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1422 } else if (!strcmp(value, "delete")) {
1423 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1424 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001425 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001426 goto error;
1427 }
1428 d = &dev->deviate[dev->deviate_size];
1429
1430 /* process deviation properties */
1431 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001432 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1433 /* garbage */
1434 lyxml_free_elem(module->ctx, child);
1435 continue;
1436 }
1437
Radek Krejcieb00f512015-07-01 16:44:58 +02001438 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001439 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001440 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001441 goto error;
1442 }
1443
1444 /* for we deviate from RFC 6020 and allow config property even it is/is not
1445 * specified in the target explicitly since config property inherits. So we expect
1446 * that config is specified in every node. But for delete, we check that the value
1447 * is the same as here in deviation
1448 */
1449 GETVAL(value, child, "value");
1450 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001451 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001452 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001453 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001455 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001456 goto error;
1457 }
1458
1459 if (d->mod == LY_DEVIATE_DEL) {
1460 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001461 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001462 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1463 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001464 goto error;
1465 }
1466 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001467 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001468
1469 /* ... and inherit config value from the target's parent */
1470 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001471 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 } else {
1473 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001474 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001475 }
1476 } else { /* add and replace are the same in this case */
1477 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001478 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479
1480 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001481 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 }
1483 } else if (!strcmp(child->name, "default")) {
1484 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001485 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001486 goto error;
1487 }
1488 GETVAL(value, child, "value");
1489 d->dflt = lydict_insert(module->ctx, value, 0);
1490
Radek Krejci76512572015-08-04 09:47:08 +02001491 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001492 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001493
1494 if (d->mod == LY_DEVIATE_ADD) {
1495 /* check that there is no current value */
1496 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001497 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1498 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001499 goto error;
1500 }
1501 }
1502
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001503 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1504 if (rc) {
1505 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1506 goto error;
1507 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001509 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001510 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1511 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 goto error;
1513 }
1514 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001515 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001516 if (!choice->dflt) {
1517 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001518 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 goto error;
1520 }
1521 }
Radek Krejci76512572015-08-04 09:47:08 +02001522 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001523 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001524
1525 if (d->mod == LY_DEVIATE_ADD) {
1526 /* check that there is no current value */
1527 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001528 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1529 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001530 goto error;
1531 }
1532 }
1533
1534 if (d->mod == LY_DEVIATE_DEL) {
1535 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001536 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1537 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001538 goto error;
1539 }
1540 /* remove value */
1541 lydict_remove(leaf->module->ctx, leaf->dflt);
1542 leaf->dflt = NULL;
1543 } else { /* add (already checked) and replace */
1544 /* remove value */
1545 lydict_remove(leaf->module->ctx, leaf->dflt);
1546
1547 /* set new value */
1548 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1549 }
1550 } else {
1551 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001552 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1553 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001554 goto error;
1555 }
1556 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001557 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001558 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 goto error;
1560 }
1561
1562 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001563 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001564 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1565 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 goto error;
1567 }
1568
1569 GETVAL(value, child, "value");
1570 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001571 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001572 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001573 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001574 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001575 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 goto error;
1577 }
1578
1579 if (d->mod == LY_DEVIATE_ADD) {
1580 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001581 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001582 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1583 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001584 goto error;
1585 }
1586 }
1587
1588 if (d->mod == LY_DEVIATE_DEL) {
1589 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001590 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001591 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1592 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001593 goto error;
1594 }
1595 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001596 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001597 } else { /* add (already checked) and replace */
1598 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001599 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001600
1601 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001602 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001603 }
1604 } else if (!strcmp(child->name, "min-elements")) {
1605 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001606 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 goto error;
1608 }
1609 f_min = 1;
1610
1611 if (deviate_minmax(dev->target, child, d, 0)) {
1612 goto error;
1613 }
1614 } else if (!strcmp(child->name, "max-elements")) {
1615 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001616 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 goto error;
1618 }
1619
1620 if (deviate_minmax(dev->target, child, d, 1)) {
1621 goto error;
1622 }
1623 } else if (!strcmp(child->name, "must")) {
1624 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001625 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1626 continue;
1627 } else if (!strcmp(child->name, "type")) {
1628 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001629 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 goto error;
1631 }
1632
1633 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001634 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001635 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001636 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001637 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001639 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1640 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001641 goto error;
1642 }
1643
1644 if (d->mod == LY_DEVIATE_ADD) {
1645 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001646 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1647 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 goto error;
1649 } else if (d->mod == LY_DEVIATE_DEL) {
1650 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001651 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1652 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 goto error;
1654 }
1655
1656 /* replace */
1657 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001658 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001659
1660 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001661 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001662 goto error;
1663 }
1664 d->type = t;
1665 } else if (!strcmp(child->name, "unique")) {
1666 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001667 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1668 continue;
1669 } else if (!strcmp(child->name, "units")) {
1670 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001671 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001672 goto error;
1673 }
1674
1675 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001676 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001677 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001678 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001679 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001680 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001681 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1682 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 goto error;
1684 }
1685
1686 /* get units value */
1687 GETVAL(value, child, "name");
1688 d->units = lydict_insert(module->ctx, value, 0);
1689
1690 /* apply to target */
1691 if (d->mod == LY_DEVIATE_ADD) {
1692 /* check that there is no current value */
1693 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001694 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1695 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001696 goto error;
1697 }
1698 }
1699
1700 if (d->mod == LY_DEVIATE_DEL) {
1701 /* check values */
1702 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001703 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1704 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001705 goto error;
1706 }
1707 /* remove current units value of the target */
1708 lydict_remove(dev->target->module->ctx, *stritem);
1709 } else { /* add (already checked) and replace */
1710 /* remove current units value of the target ... */
1711 lydict_remove(dev->target->module->ctx, *stritem);
1712
1713 /* ... and replace it with the value specified in deviation */
1714 *stritem = lydict_insert(module->ctx, value, 0);
1715 }
1716 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001717 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001718 goto error;
1719 }
1720
1721 lyxml_free_elem(module->ctx, child);
1722 }
1723
1724 if (c_must) {
1725 /* check target node type */
1726 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001727 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001728 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1729 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001730 break;
Radek Krejci76512572015-08-04 09:47:08 +02001731 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001732 trg_must = &((struct lys_node_container *)dev->target)->must;
1733 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 break;
Radek Krejci76512572015-08-04 09:47:08 +02001735 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001736 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1737 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 break;
Radek Krejci76512572015-08-04 09:47:08 +02001739 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001740 trg_must = &((struct lys_node_list *)dev->target)->must;
1741 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001742 break;
Radek Krejci76512572015-08-04 09:47:08 +02001743 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001744 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1745 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 break;
1747 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001748 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1749 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001750 goto error;
1751 }
1752
1753 if (d->mod == LY_DEVIATE_RPL) {
1754 /* remove target's musts and allocate new array for it */
1755 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001756 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1757 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001758 goto error;
1759 }
1760
1761 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001762 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001763 }
1764 free(*trg_must);
1765 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1766 d->must_size = c_must;
1767 *trg_must_size = 0;
1768 } else if (d->mod == LY_DEVIATE_ADD) {
1769 /* reallocate the must array of the target */
1770 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1771 *trg_must = d->must;
1772 d->must = &(*trg_must[*trg_must_size]);
1773 d->must_size = c_must;
1774 } else { /* LY_DEVIATE_DEL */
1775 d->must = calloc(c_must, sizeof *d->must);
1776 }
1777 }
1778 if (c_uniq) {
1779 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001780 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001781 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1782 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001783 goto error;
1784 }
1785
Radek Krejcib8048692015-08-05 13:36:34 +02001786 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001787 if (d->mod == LY_DEVIATE_RPL) {
1788 /* remove target's unique and allocate new array for it */
1789 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001790 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1791 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001792 goto error;
1793 }
1794
1795 for (i = 0; i < list->unique_size; i++) {
1796 free(list->unique[i].leafs);
1797 }
1798 free(list->unique);
1799 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1800 d->unique_size = c_uniq;
1801 list->unique_size = 0;
1802 } else if (d->mod == LY_DEVIATE_ADD) {
1803 /* reallocate the unique array of the target */
1804 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1805 list->unique = d->unique;
1806 d->unique = &list->unique[list->unique_size];
1807 d->unique_size = c_uniq;
1808 } else { /* LY_DEVIATE_DEL */
1809 d->unique = calloc(c_uniq, sizeof *d->unique);
1810 }
1811 }
1812
1813 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001814 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001815 if (!strcmp(child->name, "must")) {
1816 if (d->mod == LY_DEVIATE_DEL) {
1817 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1818 goto error;
1819 }
1820
1821 /* find must to delete, we are ok with just matching conditions */
1822 for (i = 0; i < *trg_must_size; i++) {
1823 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1824 /* we have a match, free the must structure ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001825 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001826 /* ... and maintain the array */
1827 (*trg_must_size)--;
1828 if (i != *trg_must_size) {
1829 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1830 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1831 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1832 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1833 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1834 }
1835 if (!(*trg_must_size)) {
1836 free(*trg_must);
1837 *trg_must = NULL;
1838 } else {
1839 (*trg_must)[*trg_must_size].expr = NULL;
1840 (*trg_must)[*trg_must_size].dsc = NULL;
1841 (*trg_must)[*trg_must_size].ref = NULL;
1842 (*trg_must)[*trg_must_size].eapptag = NULL;
1843 (*trg_must)[*trg_must_size].emsg = NULL;
1844 }
1845
1846 i = -1; /* set match flag */
1847 break;
1848 }
1849 }
1850 d->must_size++;
1851 if (i != -1) {
1852 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001853 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1854 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001855 goto error;
1856 }
1857 } else { /* replace or add */
1858 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1859 goto error;
1860 }
1861 (*trg_must_size)++;
1862 }
1863 } else if (!strcmp(child->name, "unique")) {
1864 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001865 GETVAL(value, child, "tag");
Michal Vasko184521f2015-09-24 13:14:26 +02001866 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], 0, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001867 goto error;
1868 }
1869
1870 /* find unique structures to delete */
1871 for (i = 0; i < list->unique_size; i++) {
1872 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1873 continue;
1874 }
1875
1876 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1877 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1878 break;
1879 }
1880 }
1881
1882 if (j == d->unique[d->unique_size].leafs_size) {
1883 /* we have a match, free the unique structure ... */
1884 free(list->unique[i].leafs);
1885 /* ... and maintain the array */
1886 list->unique_size--;
1887 if (i != list->unique_size) {
1888 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1889 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1890 }
1891
1892 if (!list->unique_size) {
1893 free(list->unique);
1894 list->unique = NULL;
1895 } else {
1896 list->unique[list->unique_size].leafs_size = 0;
1897 list->unique[list->unique_size].leafs = NULL;
1898 }
1899
1900 i = -1; /* set match flag */
1901 break;
1902 }
1903 }
1904
1905 d->unique_size++;
1906 if (i != -1) {
1907 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001908 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1909 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001910 goto error;
1911 }
1912 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001913 GETVAL(value, child, "tag");
Michal Vasko184521f2015-09-24 13:14:26 +02001914 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], 0, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001915 goto error;
1916 }
1917 list->unique_size++;
1918 }
1919 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 }
Radek Krejci5b917642015-07-02 09:03:13 +02001921
1922 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 }
1924
Radek Krejcieb00f512015-07-01 16:44:58 +02001925 return EXIT_SUCCESS;
1926
1927error:
1928
1929 if (dev->deviate) {
1930 for (i = 0; i < dev->deviate_size; i++) {
1931 lydict_remove(module->ctx, dev->deviate[i].dflt);
1932 lydict_remove(module->ctx, dev->deviate[i].units);
1933
1934 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1935 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001936 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001937 }
1938 free(dev->deviate[i].must);
1939
1940 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1941 free(dev->deviate[i].unique[j].leafs);
1942 }
1943 free(dev->deviate[i].unique);
1944 }
1945 }
1946 free(dev->deviate);
1947 }
1948
1949 return EXIT_FAILURE;
1950}
1951
Michal Vasko0d343d12015-08-24 14:57:36 +02001952/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001953static int
Radek Krejcib8048692015-08-05 13:36:34 +02001954fill_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 +02001955 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001956{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001957 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001959 struct lys_node *node;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001960 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02001961
Michal Vasko591e0b22015-08-13 13:53:43 +02001962 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001963 GETVAL(value, yin, "target-node");
1964 aug->target_name = lydict_insert(module->ctx, value, 0);
1965 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001966
Michal Vasko1d87a922015-08-21 12:57:16 +02001967 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001968 goto error;
1969 }
1970
1971 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001972 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1973 /* garbage */
1974 lyxml_free_elem(module->ctx, child);
1975 continue;
1976 }
1977
Radek Krejci3cf9e222015-06-18 11:37:50 +02001978 if (!strcmp(child->name, "if-feature")) {
1979 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001981 } else if (!strcmp(child->name, "when")) {
1982 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001983 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001984 goto error;
1985 }
1986
1987 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001988 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001989 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001990 goto error;
1991 }
Michal Vaskofcdac172015-10-07 09:35:05 +02001992 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001993 goto error;
1994 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 lyxml_free_elem(module->ctx, child);
1996 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001997
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998 /* check allowed data sub-statements */
1999 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002007 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002008 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002012 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002013 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002014 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002016 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002017 goto error;
2018 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002019
Radek Krejci1d82ef62015-08-07 14:44:40 +02002020 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002021 goto error;
2022 }
2023
2024 /* check for mandatory nodes - if the target node is in another module
2025 * the added nodes cannot be mandatory
2026 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002027 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002028 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 goto error;
2030 }
2031
Radek Krejci1d82ef62015-08-07 14:44:40 +02002032 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002033 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002034 }
2035
2036 if (c) {
2037 aug->features = calloc(c, sizeof *aug->features);
2038 }
2039
2040 LY_TREE_FOR_SAFE(yin->child, next, child) {
2041 if (!strcmp(child->name, "if-feature")) {
2042 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002043 if (unres_schema_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002044 goto error;
2045 }
Radek Krejci73adb602015-07-02 18:07:40 +02002046 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002047 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002048 }
2049
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002050 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002051 * connected to the tree and adjusted (if possible right now).
2052 * However, if this is augment in a uses, it gets resolved
2053 * when the uses does and cannot be resolved now for sure
2054 * (the grouping was not yet copied into uses).
2055 */
2056 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02002057 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002058 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2059 goto error;
2060 }
Michal Vasko49291b32015-08-06 09:49:41 +02002061 }
Radek Krejci106efc02015-06-10 14:36:27 +02002062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002064
2065error:
2066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002068}
2069
Michal Vasko0d343d12015-08-24 14:57:36 +02002070/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071static int
Michal Vasko0d204592015-10-07 09:50:04 +02002072fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002073{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 struct lyxml_elem *sub, *next;
2075 const char *value;
2076 char *endptr;
2077 int f_mand = 0, f_min = 0, f_max = 0;
2078 int c_must = 0;
2079 int r;
2080 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002081
Radek Krejci76512572015-08-04 09:47:08 +02002082 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 goto error;
2084 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002085
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002086 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002087 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002090 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2091 /* garbage */
2092 lyxml_free_elem(module->ctx, sub);
2093 continue;
2094 }
2095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 /* limited applicability */
2097 if (!strcmp(sub->name, "default")) {
2098 /* leaf or choice */
2099 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002100 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 goto error;
2102 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002103
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 /* check possibility of statements combination */
2105 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002106 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002108 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 goto error;
2110 }
2111 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002112 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 GETVAL(value, sub, "value");
2116 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2117 } else if (!strcmp(sub->name, "mandatory")) {
2118 /* leaf, choice or anyxml */
2119 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002120 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 goto error;
2122 }
2123 /* just checking the flags in leaf is not sufficient, we would allow
2124 * multiple mandatory statements with the "false" value
2125 */
2126 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002127
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 /* check possibility of statements combination */
2129 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002130 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002132 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 goto error;
2134 }
2135 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002136 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 GETVAL(value, sub, "value");
2140 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002141 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002143 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002145 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 goto error;
2147 }
2148 } else if (!strcmp(sub->name, "min-elements")) {
2149 /* list or leaf-list */
2150 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002151 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 goto error;
2153 }
2154 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 /* check possibility of statements combination */
2157 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002158 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002160 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002161 goto error;
2162 }
2163 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002164 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 GETVAL(value, sub, "value");
2168 while (isspace(value[0])) {
2169 value++;
2170 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002172 /* convert it to uint32_t */
2173 errno = 0;
2174 endptr = NULL;
2175 val = strtoul(value, &endptr, 10);
2176 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002177 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 goto error;
2179 }
2180 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 /* magic - bit 3 in flags means min set */
2183 rfn->flags |= 0x04;
2184 } else if (!strcmp(sub->name, "max-elements")) {
2185 /* list or leaf-list */
2186 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002187 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 goto error;
2189 }
2190 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002191
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 /* check possibility of statements combination */
2193 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002194 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002196 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 goto error;
2198 }
2199 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002200 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002203 GETVAL(value, sub, "value");
2204 while (isspace(value[0])) {
2205 value++;
2206 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 /* convert it to uint32_t */
2209 errno = 0;
2210 endptr = NULL;
2211 val = strtoul(value, &endptr, 10);
2212 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002213 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 goto error;
2215 }
2216 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 /* magic - bit 4 in flags means min set */
2219 rfn->flags |= 0x08;
2220 } else if (!strcmp(sub->name, "presence")) {
2221 /* container */
2222 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002223 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 goto error;
2225 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 /* check possibility of statements combination */
2228 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002229 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002231 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 goto error;
2233 }
2234 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002235 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 GETVAL(value, sub, "value");
2239 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2240 } else if (!strcmp(sub->name, "must")) {
2241 /* leaf-list, list, container or anyxml */
2242 /* check possibility of statements combination */
2243 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002244 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002246 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002247 goto error;
2248 }
2249 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002250 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002254 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002257 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 goto error;
2259 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002261 lyxml_free_elem(module->ctx, sub);
2262 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 /* process nodes with cardinality of 0..n */
2265 if (c_must) {
2266 rfn->must = calloc(c_must, sizeof *rfn->must);
2267 }
Radek Krejci73adb602015-07-02 18:07:40 +02002268 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002269 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002270 if (r) {
2271 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 }
Michal Vasko0d204592015-10-07 09:50:04 +02002273 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002274 goto error;
2275 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002279
2280error:
2281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002282 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002283}
2284
Michal Vasko0d343d12015-08-24 14:57:36 +02002285/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002286static int
Radek Krejcib8048692015-08-05 13:36:34 +02002287fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002288{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 struct lyxml_elem *child;
2290 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002293 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2294 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002295 continue;
2296 }
2297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 if (!strcmp(child->name, "prefix")) {
2299 GETVAL(value, child, "value");
2300 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2301 goto error;
2302 }
2303 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2304 } else if (!strcmp(child->name, "revision-date")) {
2305 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002306 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002307 goto error;
2308 }
2309 GETVAL(value, child, "date");
2310 if (check_date(value, LOGLINE(child))) {
2311 goto error;
2312 }
2313 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2314 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002315 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 goto error;
2317 }
2318 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 /* check mandatory information */
2321 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002322 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 goto error;
2324 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002327 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002328 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002329 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2330 if (!imp->module) {
2331 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2332 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002333 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002334 goto error;
2335 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002339
2340error:
2341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002343}
2344
Michal Vasko0d343d12015-08-24 14:57:36 +02002345/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002346static int
Radek Krejcib8048692015-08-05 13:36:34 +02002347fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002348{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 struct lyxml_elem *child;
2350 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002352 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002353 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2354 /* garbage */
2355 continue;
2356 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002357 if (!strcmp(child->name, "revision-date")) {
2358 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002359 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 goto error;
2361 }
2362 GETVAL(value, child, "date");
2363 if (check_date(value, LOGLINE(child))) {
2364 goto error;
2365 }
2366 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2367 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002368 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 goto error;
2370 }
2371 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002374 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002376 inc->submodule = (struct lys_submodule *) lyp_search_file(module->ctx, module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci63a91a92015-07-29 13:31:04 +02002377 if (!inc->submodule) {
2378 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2379 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002380 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002381 goto error;
2382 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 /* check that belongs-to corresponds */
2386 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002387 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388 }
2389 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002390 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2391 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 goto error;
2393 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002396
2397error:
2398
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002400}
2401
Michal Vasko0d343d12015-08-24 14:57:36 +02002402/* logs directly
2403 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002404 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002405 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002406 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002407 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408static int
Radek Krejcib8048692015-08-05 13:36:34 +02002409read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002410 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002411{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 const char *value;
2413 struct lyxml_elem *sub, *next;
2414 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002417 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 if (opt & OPT_IDENT) {
2421 GETVAL(value, xmlnode, "name");
2422 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2423 goto error;
2424 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002425 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002427
Radek Krejci6764bb32015-07-03 15:16:04 +02002428 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002429 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002430 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002431 }
2432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 /* process local parameters */
2434 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002435 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002436 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002437 lyxml_free_elem(ctx, sub);
2438 continue;
2439 }
2440 if (strcmp(sub->ns->value, LY_NSYIN)) {
2441 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002442 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002443 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002444 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002445 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002446 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002447 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002448 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002449 goto error;
2450 }
2451 }
2452
2453 /* else garbage */
2454 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002455 continue;
2456 }
2457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002458 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002459 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002460 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002461 goto error;
2462 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 node->dsc = read_yin_subnode(ctx, sub, "text");
2464 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002465 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 }
2467 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002468 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002469 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002470 goto error;
2471 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002472 node->ref = read_yin_subnode(ctx, sub, "text");
2473 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002474 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 }
2476 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002477 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002478 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002479 goto error;
2480 }
2481 GETVAL(value, sub, "value");
2482 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002487 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002488 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002489 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002490 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 }
2492 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002493 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002494 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 goto error;
2496 }
2497 GETVAL(value, sub, "value");
2498 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002499 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002501 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002502 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002503 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002504 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002505 }
2506 } else {
2507 /* skip the lyxml_free_elem */
2508 continue;
2509 }
2510 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002511 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002512
Radek Krejci1d82ef62015-08-07 14:44:40 +02002513 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002514 /* get config flag from parent */
2515 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002516 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002517 } else {
2518 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002519 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 }
2521 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002522
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002523 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002524
2525error:
2526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002528}
2529
Michal Vasko0d343d12015-08-24 14:57:36 +02002530/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002531static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002532read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002533{
Radek Krejci76512572015-08-04 09:47:08 +02002534 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002535 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002536 const char *value;
2537
2538 retval = calloc(1, sizeof *retval);
2539
2540 GETVAL(value, yin, "condition");
Michal Vaskof9893382015-10-09 14:03:04 +02002541 retval->cond = transform_expr_xml2json(module->ctx, value, yin, 1);
2542 if (!retval->cond) {
2543 goto error;
2544 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002545
Radek Krejci73adb602015-07-02 18:07:40 +02002546 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002547 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2548 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002549 continue;
2550 }
2551
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002552 if (!strcmp(child->name, "description")) {
2553 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002554 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002555 goto error;
2556 }
2557 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2558 if (!retval->dsc) {
2559 goto error;
2560 }
2561 } else if (!strcmp(child->name, "reference")) {
2562 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002563 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002564 goto error;
2565 }
2566 retval->ref = read_yin_subnode(module->ctx, child, "text");
2567 if (!retval->ref) {
2568 goto error;
2569 }
2570 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002571 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002572 goto error;
2573 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002574 }
2575
2576 return retval;
2577
2578error:
2579
Michal Vasko0308dd62015-10-07 09:14:40 +02002580 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002581 return NULL;
2582}
2583
Michal Vasko0d343d12015-08-24 14:57:36 +02002584/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002585static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002586read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2587 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002588{
Michal Vasko29fc0182015-08-24 15:02:39 +02002589 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002590 struct lys_node_case *cs;
2591 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002592 int c_ftrs = 0;
2593 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002594
Radek Krejcie867c852015-08-27 09:52:34 +02002595 /* init */
2596 memset(&root, 0, sizeof root);
2597
Radek Krejci1d82ef62015-08-07 14:44:40 +02002598 cs = calloc(1, sizeof *cs);
2599 cs->nodetype = LYS_CASE;
2600 cs->prev = (struct lys_node *)cs;
2601 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002602
Radek Krejci6a113852015-07-03 16:04:20 +02002603 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 goto error;
2605 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002606
Radek Krejcia9544502015-08-14 08:24:29 +02002607 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2608
Michal Vasko3a0043f2015-08-12 12:11:30 +02002609 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002610 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002611 goto error;
2612 }
2613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002614 /* process choice's specific children */
2615 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002616 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2617 /* garbage */
2618 lyxml_free_elem(module->ctx, sub);
2619 continue;
2620 }
2621
Michal Vasko29fc0182015-08-24 15:02:39 +02002622 if (!strcmp(sub->name, "container") ||
2623 !strcmp(sub->name, "leaf-list") ||
2624 !strcmp(sub->name, "leaf") ||
2625 !strcmp(sub->name, "list") ||
2626 !strcmp(sub->name, "uses") ||
2627 !strcmp(sub->name, "choice") ||
2628 !strcmp(sub->name, "anyxml")) {
2629
2630 lyxml_unlink_elem(module->ctx, sub, 1);
2631 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002632 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002633 c_ftrs++;
2634 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2635 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002636 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002637 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002638 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002639 goto error;
2640 }
2641
Radek Krejci1d82ef62015-08-07 14:44:40 +02002642 cs->when = read_yin_when(module, sub);
2643 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002644 goto error;
2645 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002646 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002647 goto error;
2648 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002649
2650 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002652 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002653 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002654 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002656
Radek Krejci3cf9e222015-06-18 11:37:50 +02002657 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002658 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002659 }
Radek Krejci73adb602015-07-02 18:07:40 +02002660 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002661 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002662 if (unres_schema_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002663 goto error;
2664 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 }
Radek Krejcib388c152015-06-04 17:03:03 +02002666
Michal Vasko29fc0182015-08-24 15:02:39 +02002667 /* last part - process data nodes */
2668 LY_TREE_FOR_SAFE(root.child, next, sub) {
2669 if (!strcmp(sub->name, "container")) {
2670 node = read_yin_container(module, retval, sub, resolve, unres);
2671 } else if (!strcmp(sub->name, "leaf-list")) {
2672 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2673 } else if (!strcmp(sub->name, "leaf")) {
2674 node = read_yin_leaf(module, retval, sub, resolve, unres);
2675 } else if (!strcmp(sub->name, "list")) {
2676 node = read_yin_list(module, retval, sub, resolve, unres);
2677 } else if (!strcmp(sub->name, "choice")) {
2678 node = read_yin_choice(module, retval, sub, resolve, unres);
2679 } else if (!strcmp(sub->name, "uses")) {
2680 node = read_yin_uses(module, retval, sub, resolve, unres);
2681 } else if (!strcmp(sub->name, "anyxml")) {
2682 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2683 }
2684 if (!node) {
2685 goto error;
2686 }
2687
2688 lyxml_free_elem(module->ctx, sub);
2689 }
2690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002691 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002692
2693error:
2694
Michal Vasko29fc0182015-08-24 15:02:39 +02002695 while (root.child) {
2696 lyxml_free_elem(module->ctx, root.child);
2697 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002698 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002701}
2702
Michal Vasko0d343d12015-08-24 14:57:36 +02002703/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002704static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002705read_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 +02002706{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 struct lyxml_elem *sub, *next;
2708 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002709 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002710 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002711 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002712 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002715 choice->nodetype = LYS_CHOICE;
2716 choice->prev = (struct lys_node *)choice;
2717 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002718
Michal Vaskoe0c59842015-09-24 13:52:20 +02002719 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2720 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 goto error;
2722 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002723
Radek Krejcia9544502015-08-14 08:24:29 +02002724 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2725
Michal Vasko3a0043f2015-08-12 12:11:30 +02002726 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002727 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002728 goto error;
2729 }
2730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 /* process choice's specific children */
2732 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002733 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2734 /* garbage */
2735 lyxml_free_elem(module->ctx, sub);
2736 continue;
2737 }
2738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002740 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 goto error;
2742 }
2743 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002744 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 }
2747 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 goto error;
2750 }
2751 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 goto error;
2754 }
2755 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002756 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 goto error;
2758 }
2759 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002760 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 goto error;
2762 }
2763 } else if (!strcmp(sub->name, "default")) {
2764 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002765 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 goto error;
2767 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002768 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 } else if (!strcmp(sub->name, "mandatory")) {
2770 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002771 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 goto error;
2773 }
2774 /* just checking the flags in leaf is not sufficient, we would allow
2775 * multiple mandatory statements with the "false" value
2776 */
2777 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 GETVAL(value, sub, "value");
2780 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002781 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002782 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002783 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002784 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002785 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 goto error;
2787 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002788 } else if (!strcmp(sub->name, "when")) {
2789 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002790 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002791 goto error;
2792 }
2793
2794 choice->when = read_yin_when(module, sub);
2795 if (!choice->when) {
2796 goto error;
2797 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002798 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002799 goto error;
2800 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002801 } else if (!strcmp(sub->name, "if-feature")) {
2802 c_ftrs++;
2803
2804 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2805 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002806 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002807 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002810
Radek Krejci1d82ef62015-08-07 14:44:40 +02002811 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 lyxml_free_elem(ctx, sub);
2813 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002814
Radek Krejci3cf9e222015-06-18 11:37:50 +02002815 if (c_ftrs) {
2816 choice->features = calloc(c_ftrs, sizeof *choice->features);
2817 }
2818
Radek Krejci73adb602015-07-02 18:07:40 +02002819 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002820 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002821 if (unres_schema_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002822 goto error;
2823 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002824 }
2825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002827 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002828 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002829 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2830 goto error;
2831 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 /* link default with the case */
2834 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002835 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002836 goto error;
2837 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002841
2842error:
2843
Radek Krejci1d82ef62015-08-07 14:44:40 +02002844 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002846 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002847}
2848
Michal Vasko0d343d12015-08-24 14:57:36 +02002849/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002850static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002851read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002852 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002853{
Radek Krejci76512572015-08-04 09:47:08 +02002854 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002855 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 struct lyxml_elem *sub, *next;
2857 const char *value;
2858 int r;
2859 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002860 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002863 anyxml->nodetype = LYS_ANYXML;
2864 anyxml->prev = (struct lys_node *)anyxml;
2865 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002866
Michal Vaskoe0c59842015-09-24 13:52:20 +02002867 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2868 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 goto error;
2870 }
Radek Krejci863c2852015-06-03 15:47:11 +02002871
Radek Krejcia9544502015-08-14 08:24:29 +02002872 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002873
2874 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002875 goto error;
2876 }
2877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002879 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2880 /* garbage */
2881 lyxml_free_elem(module->ctx, sub);
2882 continue;
2883 }
2884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 if (!strcmp(sub->name, "mandatory")) {
2886 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002887 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 goto error;
2889 }
2890 /* just checking the flags in leaf is not sufficient, we would allow
2891 * multiple mandatory statements with the "false" value
2892 */
2893 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 GETVAL(value, sub, "value");
2896 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002897 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002898 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002899 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002900 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002901 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 goto error;
2903 }
2904 /* else false is the default value, so we can ignore it */
2905 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002906 } else if (!strcmp(sub->name, "when")) {
2907 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002908 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002909 goto error;
2910 }
2911
2912 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002913 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002914 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002915 goto error;
2916 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002917 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002918 goto error;
2919 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002920 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 } else if (!strcmp(sub->name, "must")) {
2922 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002923 } else if (!strcmp(sub->name, "if-feature")) {
2924 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002925
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002927 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 }
2930 }
Radek Krejci863c2852015-06-03 15:47:11 +02002931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002932 /* middle part - process nodes with cardinality of 0..n */
2933 if (c_must) {
2934 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2935 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002936 if (c_ftrs) {
2937 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2938 }
Radek Krejci863c2852015-06-03 15:47:11 +02002939
Radek Krejci73adb602015-07-02 18:07:40 +02002940 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002941 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002942 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002943 if (r) {
2944 goto error;
2945 }
Michal Vasko0d204592015-10-07 09:50:04 +02002946 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002947 goto error;
2948 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002949 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002950 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002951 if (unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002952 goto error;
2953 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 }
Radek Krejci863c2852015-06-03 15:47:11 +02002956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002958
2959error:
2960
Radek Krejci1d82ef62015-08-07 14:44:40 +02002961 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002964}
2965
Michal Vasko0d343d12015-08-24 14:57:36 +02002966/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002967static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002968read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002969 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002970{
Radek Krejci76512572015-08-04 09:47:08 +02002971 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002972 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 struct lyxml_elem *sub, *next;
2974 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002975 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002976 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002979 leaf->nodetype = LYS_LEAF;
2980 leaf->prev = (struct lys_node *)leaf;
2981 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002982
Michal Vaskoe0c59842015-09-24 13:52:20 +02002983 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2984 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 goto error;
2986 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002987
Radek Krejcia9544502015-08-14 08:24:29 +02002988 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002989
2990 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002991 goto error;
2992 }
2993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002995 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2996 /* garbage */
2997 lyxml_free_elem(module->ctx, sub);
2998 continue;
2999 }
3000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003002 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003003 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003004 goto error;
3005 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003006 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 goto error;
3008 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003009 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 } else if (!strcmp(sub->name, "default")) {
3011 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003012 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 goto error;
3014 }
3015 GETVAL(value, sub, "value");
3016 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003017 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 } else if (!strcmp(sub->name, "units")) {
3019 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003020 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 goto error;
3022 }
3023 GETVAL(value, sub, "name");
3024 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3025 } else if (!strcmp(sub->name, "mandatory")) {
3026 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003027 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003028 goto error;
3029 }
3030 /* just checking the flags in leaf is not sufficient, we would allow
3031 * multiple mandatory statements with the "false" value
3032 */
3033 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 GETVAL(value, sub, "value");
3036 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003037 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003038 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003039 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003040 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003041 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 goto error;
3043 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003044 } else if (!strcmp(sub->name, "when")) {
3045 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003046 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003047 goto error;
3048 }
3049
3050 leaf->when = read_yin_when(module, sub);
3051 if (!leaf->when) {
3052 goto error;
3053 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003054 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003055 goto error;
3056 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003059 c_must++;
3060 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003061 } else if (!strcmp(sub->name, "if-feature")) {
3062 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003066 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003070 lyxml_free_elem(module->ctx, sub);
3071 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003074 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003075 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 goto error;
3077 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003078 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003079 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003080 goto error;
3081 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003082 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 /* middle part - process nodes with cardinality of 0..n */
3085 if (c_must) {
3086 leaf->must = calloc(c_must, sizeof *leaf->must);
3087 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003088 if (c_ftrs) {
3089 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3090 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003091
Radek Krejci73adb602015-07-02 18:07:40 +02003092 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003094 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 if (r) {
3096 goto error;
3097 }
Michal Vasko0d204592015-10-07 09:50:04 +02003098 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003099 goto error;
3100 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003101 } else if (!strcmp(sub->name, "if-feature")) {
3102 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003103 if (unres_schema_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003104 goto error;
3105 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003109 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003110
3111error:
3112
Radek Krejci1d82ef62015-08-07 14:44:40 +02003113 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003116}
3117
Michal Vasko0d343d12015-08-24 14:57:36 +02003118/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003119static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003120read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003121 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003122{
Radek Krejci76512572015-08-04 09:47:08 +02003123 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003124 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 struct lyxml_elem *sub, *next;
3126 const char *value;
3127 char *endptr;
3128 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003129 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003130 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003131 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003134 llist->nodetype = LYS_LEAFLIST;
3135 llist->prev = (struct lys_node *)llist;
3136 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003137
Michal Vaskoe0c59842015-09-24 13:52:20 +02003138 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3139 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 goto error;
3141 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003142
Radek Krejcia9544502015-08-14 08:24:29 +02003143 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003144
3145 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003146 goto error;
3147 }
3148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003150 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3151 /* garbage */
3152 lyxml_free_elem(module->ctx, sub);
3153 continue;
3154 }
3155
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003156 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003157 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003158 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 goto error;
3160 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003161 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 goto error;
3163 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003164 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 } else if (!strcmp(sub->name, "units")) {
3166 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003167 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 goto error;
3169 }
3170 GETVAL(value, sub, "name");
3171 llist->units = lydict_insert(module->ctx, value, strlen(value));
3172 } else if (!strcmp(sub->name, "ordered-by")) {
3173 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003174 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 goto error;
3176 }
3177 /* just checking the flags in llist is not sufficient, we would
3178 * allow multiple ordered-by statements with the "system" value
3179 */
3180 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003181
Radek Krejci1574a8d2015-08-03 14:16:52 +02003182 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3184 * state data
3185 */
3186 lyxml_free_elem(module->ctx, sub);
3187 continue;
3188 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 GETVAL(value, sub, "value");
3191 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003192 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003193 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003194 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003196 } /* else system is the default value, so we can ignore it */
3197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 } else if (!strcmp(sub->name, "must")) {
3199 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003200 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003201 } else if (!strcmp(sub->name, "if-feature")) {
3202 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 } else if (!strcmp(sub->name, "min-elements")) {
3206 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003207 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 goto error;
3209 }
3210 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 GETVAL(value, sub, "value");
3213 while (isspace(value[0])) {
3214 value++;
3215 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003217 /* convert it to uint32_t */
3218 errno = 0;
3219 endptr = NULL;
3220 val = strtoul(value, &endptr, 10);
3221 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003222 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003223 goto error;
3224 }
3225 llist->min = (uint32_t) val;
3226 } else if (!strcmp(sub->name, "max-elements")) {
3227 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003228 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 goto error;
3230 }
3231 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003233 GETVAL(value, sub, "value");
3234 while (isspace(value[0])) {
3235 value++;
3236 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 /* convert it to uint32_t */
3239 errno = 0;
3240 endptr = NULL;
3241 val = strtoul(value, &endptr, 10);
3242 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003243 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003244 goto error;
3245 }
3246 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003247 } else if (!strcmp(sub->name, "when")) {
3248 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003249 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003250 goto error;
3251 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003252
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003253 llist->when = read_yin_when(module, sub);
3254 if (!llist->when) {
3255 goto error;
3256 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003257 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003258 goto error;
3259 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003261 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 lyxml_free_elem(module->ctx, sub);
3266 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003269 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003270 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 goto error;
3272 }
3273 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003274 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 goto error;
3276 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 /* middle part - process nodes with cardinality of 0..n */
3279 if (c_must) {
3280 llist->must = calloc(c_must, sizeof *llist->must);
3281 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003282 if (c_ftrs) {
3283 llist->features = calloc(c_ftrs, sizeof *llist->features);
3284 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003285
Radek Krejci73adb602015-07-02 18:07:40 +02003286 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003287 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003288 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003289 if (r) {
3290 goto error;
3291 }
Michal Vasko0d204592015-10-07 09:50:04 +02003292 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003293 goto error;
3294 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003295 } else if (!strcmp(sub->name, "if-feature")) {
3296 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003297 if (unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003298 LOGLINE(sub)) == -1) {
3299 goto error;
3300 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003305
3306error:
3307
Radek Krejci1d82ef62015-08-07 14:44:40 +02003308 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003309
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003311}
3312
Michal Vasko0d343d12015-08-24 14:57:36 +02003313/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003314static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003315read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3316 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003317{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003318 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003319 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003321 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003322 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003324 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 char *auxs;
3326 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 /* init */
3329 memset(&root, 0, sizeof root);
3330 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003333 list->nodetype = LYS_LIST;
3334 list->prev = (struct lys_node *)list;
3335 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003336
Michal Vaskoe0c59842015-09-24 13:52:20 +02003337 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3338 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 goto error;
3340 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003341
Radek Krejcia9544502015-08-14 08:24:29 +02003342 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 /* process list's specific children */
3345 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003346 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3347 /* garbage */
3348 lyxml_free_elem(module->ctx, sub);
3349 continue;
3350 }
3351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 /* data statements */
3353 if (!strcmp(sub->name, "container") ||
3354 !strcmp(sub->name, "leaf-list") ||
3355 !strcmp(sub->name, "leaf") ||
3356 !strcmp(sub->name, "list") ||
3357 !strcmp(sub->name, "choice") ||
3358 !strcmp(sub->name, "uses") ||
3359 !strcmp(sub->name, "grouping") ||
3360 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003361 lyxml_unlink_elem(module->ctx, sub, 1);
3362 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 /* array counters */
3365 } else if (!strcmp(sub->name, "key")) {
3366 /* check cardinality 0..1 */
3367 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003368 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 goto error;
3370 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003372 /* count the number of keys */
3373 GETVAL(value, sub, "value");
3374 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003375 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 while ((value = strpbrk(value, " \t\n"))) {
3377 list->keys_size++;
3378 while (isspace(*value)) {
3379 value++;
3380 }
3381 }
3382 list->keys_size++;
3383 list->keys = calloc(list->keys_size, sizeof *list->keys);
3384 } else if (!strcmp(sub->name, "unique")) {
3385 c_uniq++;
Michal Vaskof8879c22015-08-21 09:07:36 +02003386 lyxml_unlink_elem(module->ctx, sub, 1);
3387 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 } else if (!strcmp(sub->name, "typedef")) {
3389 c_tpdf++;
3390 } else if (!strcmp(sub->name, "must")) {
3391 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003392 } else if (!strcmp(sub->name, "if-feature")) {
3393 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 /* optional stetments */
3396 } else if (!strcmp(sub->name, "ordered-by")) {
3397 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003398 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 goto error;
3400 }
3401 /* just checking the flags in llist is not sufficient, we would
3402 * allow multiple ordered-by statements with the "system" value
3403 */
3404 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003405
Radek Krejci1574a8d2015-08-03 14:16:52 +02003406 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3408 * state data
3409 */
3410 lyxml_free_elem(module->ctx, sub);
3411 continue;
3412 }
Radek Krejci345ad742015-06-03 11:04:18 +02003413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 GETVAL(value, sub, "value");
3415 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003416 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003418 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 goto error;
3420 }
3421 /* else system is the default value, so we can ignore it */
3422 lyxml_free_elem(module->ctx, sub);
3423 } else if (!strcmp(sub->name, "min-elements")) {
3424 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003425 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 goto error;
3427 }
3428 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003429
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 GETVAL(value, sub, "value");
3431 while (isspace(value[0])) {
3432 value++;
3433 }
Radek Krejci345ad742015-06-03 11:04:18 +02003434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 /* convert it to uint32_t */
3436 errno = 0;
3437 auxs = NULL;
3438 val = strtoul(value, &auxs, 10);
3439 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003440 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 goto error;
3442 }
3443 list->min = (uint32_t) val;
3444 lyxml_free_elem(module->ctx, sub);
3445 } else if (!strcmp(sub->name, "max-elements")) {
3446 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003447 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 goto error;
3449 }
3450 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 GETVAL(value, sub, "value");
3453 while (isspace(value[0])) {
3454 value++;
3455 }
Radek Krejci345ad742015-06-03 11:04:18 +02003456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 /* convert it to uint32_t */
3458 errno = 0;
3459 auxs = NULL;
3460 val = strtoul(value, &auxs, 10);
3461 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003462 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 goto error;
3464 }
3465 list->max = (uint32_t) val;
3466 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003467 } else if (!strcmp(sub->name, "when")) {
3468 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003469 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003470 goto error;
3471 }
3472
3473 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003474 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003475 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003476 goto error;
3477 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003478 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003479 goto error;
3480 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003481 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003482 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003483 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003484 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003485 }
3486 }
Radek Krejci345ad742015-06-03 11:04:18 +02003487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003489 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003490 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 goto error;
3492 }
3493 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003494 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003495 goto error;
3496 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003497
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3499 if (c_tpdf) {
3500 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3501 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003502 if (c_must) {
3503 list->must = calloc(c_must, sizeof *list->must);
3504 }
3505 if (c_ftrs) {
3506 list->features = calloc(c_ftrs, sizeof *list->features);
3507 }
Radek Krejci73adb602015-07-02 18:07:40 +02003508 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003510 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 if (r) {
3513 goto error;
3514 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003515 } else if (!strcmp(sub->name, "if-feature")) {
3516 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003517 if (unres_schema_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003518 goto error;
3519 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003520 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003521 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003522 if (r) {
3523 goto error;
3524 }
Michal Vasko0d204592015-10-07 09:50:04 +02003525 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003526 goto error;
3527 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 }
3529 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003530
Radek Krejci10c760e2015-08-14 14:45:43 +02003531 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003532 goto error;
3533 }
3534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 /* last part - process data nodes */
3536 LY_TREE_FOR_SAFE(root.child, next, sub) {
3537 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003538 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003540 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003542 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003544 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003546 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003548 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003550 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003552 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003553 } else {
3554 LOGINT;
3555 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003557 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 goto error;
3559 }
Radek Krejci73adb602015-07-02 18:07:40 +02003560
3561 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 if (!key_str) {
3565 /* config false list without a key */
3566 return retval;
3567 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003568 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003569 goto error;
3570 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 /* process unique statements */
3573 if (c_uniq) {
3574 list->unique = calloc(c_uniq, sizeof *list->unique);
3575 }
3576 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003577 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003578 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003579 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003580 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003581 LOGLINE(sub)) == -1) {
3582 goto error;
3583 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003585 lyxml_free_elem(module->ctx, sub);
3586 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003589
3590error:
3591
Radek Krejci1d82ef62015-08-07 14:44:40 +02003592 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 while (root.child) {
3594 lyxml_free_elem(module->ctx, root.child);
3595 }
3596 while (uniq.child) {
3597 lyxml_free_elem(module->ctx, uniq.child);
3598 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003599
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003601}
3602
Michal Vasko0d343d12015-08-24 14:57:36 +02003603/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003604static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003605read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3606 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003607{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003609 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003610 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003611 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 const char *value;
3613 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003614 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 /* init */
3617 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003620 cont->nodetype = LYS_CONTAINER;
3621 cont->prev = (struct lys_node *)cont;
3622 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003623
Michal Vaskoe0c59842015-09-24 13:52:20 +02003624 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3625 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003626 goto error;
3627 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003628
Radek Krejcia9544502015-08-14 08:24:29 +02003629 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 /* process container's specific children */
3632 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003633 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003634 /* garbage */
3635 lyxml_free_elem(module->ctx, sub);
3636 continue;
3637 }
3638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 if (!strcmp(sub->name, "presence")) {
3640 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003641 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003642 goto error;
3643 }
3644 GETVAL(value, sub, "value");
3645 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003646
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003648 } else if (!strcmp(sub->name, "when")) {
3649 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003650 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003651 goto error;
3652 }
3653
3654 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003655 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003656 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003657 goto error;
3658 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003659 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003660 goto error;
3661 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003662 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003663
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003664 /* data statements */
3665 } else if (!strcmp(sub->name, "container") ||
3666 !strcmp(sub->name, "leaf-list") ||
3667 !strcmp(sub->name, "leaf") ||
3668 !strcmp(sub->name, "list") ||
3669 !strcmp(sub->name, "choice") ||
3670 !strcmp(sub->name, "uses") ||
3671 !strcmp(sub->name, "grouping") ||
3672 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003673 lyxml_unlink_elem(module->ctx, sub, 1);
3674 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 /* array counters */
3677 } else if (!strcmp(sub->name, "typedef")) {
3678 c_tpdf++;
3679 } else if (!strcmp(sub->name, "must")) {
3680 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003681 } else if (!strcmp(sub->name, "if-feature")) {
3682 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003684 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 }
3687 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3690 if (c_tpdf) {
3691 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3692 }
3693 if (c_must) {
3694 cont->must = calloc(c_must, sizeof *cont->must);
3695 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003696 if (c_ftrs) {
3697 cont->features = calloc(c_ftrs, sizeof *cont->features);
3698 }
Radek Krejci800af702015-06-02 13:46:01 +02003699
Radek Krejci73adb602015-07-02 18:07:40 +02003700 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003702 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 if (r) {
3704 goto error;
3705 }
3706 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003707 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 if (r) {
3709 goto error;
3710 }
Michal Vasko0d204592015-10-07 09:50:04 +02003711 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003712 goto error;
3713 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003714 } else if (!strcmp(sub->name, "if-feature")) {
3715 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003716 if (unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003717 LOGLINE(sub)) == -1) {
3718 goto error;
3719 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003722
Radek Krejci10c760e2015-08-14 14:45:43 +02003723 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003724 goto error;
3725 }
3726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 /* last part - process data nodes */
3728 LY_TREE_FOR_SAFE(root.child, next, sub) {
3729 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003730 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003732 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003734 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003735 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003736 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003737 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003738 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003740 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003742 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003744 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003746 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003747 goto error;
3748 }
Radek Krejci73adb602015-07-02 18:07:40 +02003749
3750 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003754
3755error:
3756
Radek Krejci1d82ef62015-08-07 14:44:40 +02003757 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 while (root.child) {
3759 lyxml_free_elem(module->ctx, root.child);
3760 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763}
3764
Michal Vasko0d343d12015-08-24 14:57:36 +02003765/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003766static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003767read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003768 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003772 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003773 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 int r;
3775 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 /* init */
3778 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003781 grp->nodetype = LYS_GROUPING;
3782 grp->prev = (struct lys_node *)grp;
3783 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003784
Michal Vasko71e1aa82015-08-12 12:17:51 +02003785 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 goto error;
3787 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003788
Radek Krejcia9544502015-08-14 08:24:29 +02003789 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3790
Radek Krejci1d82ef62015-08-07 14:44:40 +02003791 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003792 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3793 /* garbage */
3794 lyxml_free_elem(module->ctx, sub);
3795 continue;
3796 }
3797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 /* data statements */
3799 if (!strcmp(sub->name, "container") ||
3800 !strcmp(sub->name, "leaf-list") ||
3801 !strcmp(sub->name, "leaf") ||
3802 !strcmp(sub->name, "list") ||
3803 !strcmp(sub->name, "choice") ||
3804 !strcmp(sub->name, "uses") ||
3805 !strcmp(sub->name, "grouping") ||
3806 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003807 lyxml_unlink_elem(module->ctx, sub, 1);
3808 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 /* array counters */
3811 } else if (!strcmp(sub->name, "typedef")) {
3812 c_tpdf++;
3813 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003814 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003815 goto error;
3816 }
3817 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003819 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3820 if (c_tpdf) {
3821 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3822 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003823 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003824 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003825
Radek Krejci73adb602015-07-02 18:07:40 +02003826 if (r) {
3827 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003830
Radek Krejci10c760e2015-08-14 14:45:43 +02003831 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003832 goto error;
3833 }
3834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 /* last part - process data nodes */
3836 LY_TREE_FOR_SAFE(root.child, next, sub) {
3837 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003838 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003844 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003846 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003848 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003850 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003851 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003852 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 goto error;
3856 }
Radek Krejci73adb602015-07-02 18:07:40 +02003857
3858 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003862
3863error:
3864
Radek Krejci1d82ef62015-08-07 14:44:40 +02003865 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003866 while (root.child) {
3867 lyxml_free_elem(module->ctx, root.child);
3868 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003870 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003871}
3872
Michal Vasko0d343d12015-08-24 14:57:36 +02003873/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003874static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003875read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3876 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003877{
Radek Krejcie0674f82015-06-15 13:58:51 +02003878 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003879 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003880 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003881 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003882 int r;
3883 int c_tpdf = 0;
3884
Radek Krejcie0674f82015-06-15 13:58:51 +02003885 /* init */
3886 memset(&root, 0, sizeof root);
3887
Michal Vasko38d01f72015-06-15 09:41:06 +02003888 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003889 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003890
3891 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003892 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003893 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003894 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003895 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003896 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003897 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003898 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003899 }
3900
Radek Krejci76512572015-08-04 09:47:08 +02003901 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003902
Radek Krejci6a113852015-07-03 16:04:20 +02003903 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003904 goto error;
3905 }
3906
Radek Krejcia9544502015-08-14 08:24:29 +02003907 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3908
Michal Vasko38d01f72015-06-15 09:41:06 +02003909 /* data statements */
3910 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003911 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3912 /* garbage */
3913 lyxml_free_elem(module->ctx, sub);
3914 continue;
3915 }
3916
Michal Vasko38d01f72015-06-15 09:41:06 +02003917 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 !strcmp(sub->name, "leaf-list") ||
3919 !strcmp(sub->name, "leaf") ||
3920 !strcmp(sub->name, "list") ||
3921 !strcmp(sub->name, "choice") ||
3922 !strcmp(sub->name, "uses") ||
3923 !strcmp(sub->name, "grouping") ||
3924 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003925 lyxml_unlink_elem(module->ctx, sub, 1);
3926 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003929 } else if (!strcmp(sub->name, "typedef")) {
3930 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003931
Michal Vasko38d01f72015-06-15 09:41:06 +02003932 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003933 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003934 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003935 }
3936 }
3937
3938 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3939 if (c_tpdf) {
3940 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3941 }
3942
Radek Krejci73adb602015-07-02 18:07:40 +02003943 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003944 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003945
Radek Krejci73adb602015-07-02 18:07:40 +02003946 if (r) {
3947 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003948 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003949 }
3950
Radek Krejci10c760e2015-08-14 14:45:43 +02003951 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003952 goto error;
3953 }
3954
Michal Vasko38d01f72015-06-15 09:41:06 +02003955 /* last part - process data nodes */
3956 LY_TREE_FOR_SAFE(root.child, next, sub) {
3957 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003959 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003961 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003963 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003965 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003967 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003969 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003970 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003971 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003972 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003973 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003974 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003975 goto error;
3976 }
Radek Krejci73adb602015-07-02 18:07:40 +02003977
3978 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003979 }
3980
Michal Vasko38d01f72015-06-15 09:41:06 +02003981 return retval;
3982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003983error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003984
Radek Krejci1d82ef62015-08-07 14:44:40 +02003985 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003986 while (root.child) {
3987 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003988 }
3989
3990 return NULL;
3991}
3992
Michal Vasko0d343d12015-08-24 14:57:36 +02003993/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003994static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003995read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3996 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003997{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003998 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003999 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004000 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004001 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004002 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004003 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004004 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004005
Michal Vaskoc6551b32015-06-16 10:51:43 +02004006 memset(&root, 0, sizeof root);
4007
Michal Vasko0ea41032015-06-16 08:53:55 +02004008 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004009 notif->nodetype = LYS_NOTIF;
4010 notif->prev = (struct lys_node *)notif;
4011 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004012
Radek Krejci6a113852015-07-03 16:04:20 +02004013 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004014 goto error;
4015 }
4016
Radek Krejcia9544502015-08-14 08:24:29 +02004017 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4018
Michal Vasko0ea41032015-06-16 08:53:55 +02004019 /* process rpc's specific children */
4020 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004021 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4022 /* garbage */
4023 lyxml_free_elem(module->ctx, sub);
4024 continue;
4025 }
4026
Michal Vasko0ea41032015-06-16 08:53:55 +02004027 /* data statements */
4028 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004029 !strcmp(sub->name, "leaf-list") ||
4030 !strcmp(sub->name, "leaf") ||
4031 !strcmp(sub->name, "list") ||
4032 !strcmp(sub->name, "choice") ||
4033 !strcmp(sub->name, "uses") ||
4034 !strcmp(sub->name, "grouping") ||
4035 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004036 lyxml_unlink_elem(module->ctx, sub, 1);
4037 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004040 } else if (!strcmp(sub->name, "typedef")) {
4041 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004042 } else if (!strcmp(sub->name, "if-feature")) {
4043 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004044 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004045 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004046 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004047 }
4048 }
4049
4050 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4051 if (c_tpdf) {
4052 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4053 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004054 if (c_ftrs) {
4055 notif->features = calloc(c_ftrs, sizeof *notif->features);
4056 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004057
Radek Krejci73adb602015-07-02 18:07:40 +02004058 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004059 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004060 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004061
4062 if (r) {
4063 goto error;
4064 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004065 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004066 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004067 if (unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004068 LOGLINE(sub)) == -1) {
4069 goto error;
4070 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004071 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004072 }
4073
Radek Krejci10c760e2015-08-14 14:45:43 +02004074 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004075 goto error;
4076 }
4077
Michal Vasko0ea41032015-06-16 08:53:55 +02004078 /* last part - process data nodes */
4079 LY_TREE_FOR_SAFE(root.child, next, sub) {
4080 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004081 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004082 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004084 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004086 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004087 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004088 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004089 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004090 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004091 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004092 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004093 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004094 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004095 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004096 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004097 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004098 goto error;
4099 }
Radek Krejci73adb602015-07-02 18:07:40 +02004100
4101 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004102 }
4103
Michal Vasko0ea41032015-06-16 08:53:55 +02004104 return retval;
4105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004107
Radek Krejci1d82ef62015-08-07 14:44:40 +02004108 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004109 while (root.child) {
4110 lyxml_free_elem(module->ctx, root.child);
4111 }
4112
4113 return NULL;
4114}
4115
Michal Vasko0d343d12015-08-24 14:57:36 +02004116/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004117static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004118read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4119 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004120{
Radek Krejcie0674f82015-06-15 13:58:51 +02004121 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004122 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004123 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004124 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004125 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004127 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004128
Radek Krejcie0674f82015-06-15 13:58:51 +02004129 /* init */
4130 memset(&root, 0, sizeof root);
4131
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004133 rpc->nodetype = LYS_RPC;
4134 rpc->prev = (struct lys_node *)rpc;
4135 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004136
Radek Krejci6a113852015-07-03 16:04:20 +02004137 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004138 goto error;
4139 }
4140
Radek Krejcia9544502015-08-14 08:24:29 +02004141 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4142
Michal Vasko38d01f72015-06-15 09:41:06 +02004143 /* process rpc's specific children */
4144 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004145 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4146 /* garbage */
4147 lyxml_free_elem(module->ctx, sub);
4148 continue;
4149 }
4150
Michal Vasko38d01f72015-06-15 09:41:06 +02004151 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004152 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004153 && (rpc->child->nodetype == LYS_INPUT
4154 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004155 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004156 goto error;
4157 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004158 lyxml_unlink_elem(module->ctx, sub, 1);
4159 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004160 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004161 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004162 && (rpc->child->nodetype == LYS_INPUT
4163 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004164 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 goto error;
4166 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004167 lyxml_unlink_elem(module->ctx, sub, 1);
4168 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004170 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004171 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004172 lyxml_unlink_elem(module->ctx, sub, 1);
4173 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004175 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004176 } else if (!strcmp(sub->name, "typedef")) {
4177 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004178 } else if (!strcmp(sub->name, "if-feature")) {
4179 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004180 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004181 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004182 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004183 }
4184 }
4185
4186 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4187 if (c_tpdf) {
4188 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4189 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004190 if (c_ftrs) {
4191 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4192 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004193
Radek Krejci73adb602015-07-02 18:07:40 +02004194 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004195 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004196 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004197
4198 if (r) {
4199 goto error;
4200 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004201 } else if (!strcmp(sub->name, "if-feature")) {
4202 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004203 if (unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004204 LOGLINE(sub)) == -1) {
4205 goto error;
4206 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004207 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004208 }
4209
Radek Krejci10c760e2015-08-14 14:45:43 +02004210 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004211 goto error;
4212 }
4213
Michal Vasko38d01f72015-06-15 09:41:06 +02004214 /* last part - process data nodes */
4215 LY_TREE_FOR_SAFE(root.child, next, sub) {
4216 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004218 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004219 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004220 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004221 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004222 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004223 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004224 goto error;
4225 }
Radek Krejci73adb602015-07-02 18:07:40 +02004226
4227 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004228 }
4229
Michal Vasko38d01f72015-06-15 09:41:06 +02004230 return retval;
4231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004232error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004233
Radek Krejci1d82ef62015-08-07 14:44:40 +02004234 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004235 while (root.child) {
4236 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004237 }
4238
4239 return NULL;
4240}
4241
Michal Vasko0d343d12015-08-24 14:57:36 +02004242/* logs directly
4243 *
Radek Krejci74705112015-06-05 10:25:44 +02004244 * resolve - referenced grouping should be bounded to the namespace (resolved)
4245 * only when uses does not appear in grouping. In a case of grouping's uses,
4246 * we just get information but we do not apply augment or refine to it.
4247 */
Radek Krejci76512572015-08-04 09:47:08 +02004248static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004249read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004250 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004251{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004253 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004254 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004255 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004256 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004257 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004259 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004260 uses->nodetype = LYS_USES;
4261 uses->prev = (struct lys_node *)uses;
4262 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004263
Radek Krejcia9544502015-08-14 08:24:29 +02004264 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004265 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004266
Michal Vaskoe0c59842015-09-24 13:52:20 +02004267 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4268 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004269 goto error;
4270 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004271
Radek Krejcia9544502015-08-14 08:24:29 +02004272 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004275 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004276 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4277 /* garbage */
4278 lyxml_free_elem(module->ctx, sub);
4279 continue;
4280 }
4281
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004282 if (!strcmp(sub->name, "refine")) {
4283 c_ref++;
4284 } else if (!strcmp(sub->name, "augment")) {
4285 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004286 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004287 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004288 } else if (!strcmp(sub->name, "when")) {
4289 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004290 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004291 goto error;
4292 }
4293
4294 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004295 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004296 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004297 goto error;
4298 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004299 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004300 goto error;
4301 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004302 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004304 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004305 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 }
4307 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004309 /* process properties with cardinality 0..n */
4310 if (c_ref) {
4311 uses->refine = calloc(c_ref, sizeof *uses->refine);
4312 }
4313 if (c_aug) {
4314 uses->augment = calloc(c_aug, sizeof *uses->augment);
4315 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004316 if (c_ftrs) {
4317 uses->features = calloc(c_ftrs, sizeof *uses->features);
4318 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004319
Radek Krejci10c760e2015-08-14 14:45:43 +02004320 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004321 goto error;
4322 }
4323
Radek Krejcia9544502015-08-14 08:24:29 +02004324 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 if (!strcmp(sub->name, "refine")) {
Michal Vasko0d204592015-10-07 09:50:04 +02004326 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004327 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004328 goto error;
4329 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004330 } else if (!strcmp(sub->name, "augment")) {
4331 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4332 if (r) {
4333 goto error;
4334 }
4335 } else if (!strcmp(sub->name, "if-feature")) {
4336 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004337 if (unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004338 LOGLINE(sub)) == -1) {
4339 goto error;
4340 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 }
4342 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004343
Michal Vasko0bd29d12015-08-19 11:45:49 +02004344 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004345 goto error;
4346 }
Radek Krejci74705112015-06-05 10:25:44 +02004347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 if (resolve) {
4349 /* inherit config flag */
4350 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004351 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 } else {
4353 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004354 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004355 }
4356 }
Radek Krejcib388c152015-06-04 17:03:03 +02004357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004358 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004359
4360error:
4361
Radek Krejci1d82ef62015-08-07 14:44:40 +02004362 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004365}
4366
Michal Vasko0d343d12015-08-24 14:57:36 +02004367/* logs directly
4368 *
4369 * common code for yin_read_module() and yin_read_submodule()
4370 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004372read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004373{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004375 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004376 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4377 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004379 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004381 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004382 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 +02004383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004384 /* init */
4385 memset(&root, 0, sizeof root);
4386 memset(&grps, 0, sizeof grps);
4387 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004388 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 /*
4391 * in the first run, we process elements with cardinality of 1 or 0..1 and
4392 * count elements with cardinality 0..n. Data elements (choices, containers,
4393 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4394 * need have all top-level and groupings already prepared at that time. In
4395 * the middle loop, we process other elements with carinality of 0..n since
4396 * we need to allocate arrays to store them.
4397 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004398 LY_TREE_FOR_SAFE(yin->child, next, child) {
4399 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004400 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004401 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 continue;
4403 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004404
Radek Krejci1d82ef62015-08-07 14:44:40 +02004405 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004407 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 goto error;
4409 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004410 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004412 lyxml_free_elem(ctx, child);
4413 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004415 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 goto error;
4417 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004418 GETVAL(value, child, "value");
4419 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 goto error;
4421 }
4422 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004423 lyxml_free_elem(ctx, child);
4424 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004425 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004426 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 goto error;
4428 }
4429 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004430 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004431 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004432 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004433 }
4434 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004435 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 goto error;
4437 }
Radek Krejcif3886932015-06-04 17:36:06 +02004438
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004439 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004440 if (!child->child) {
4441 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004443 } else if (strcmp(child->child->name, "prefix")) {
4444 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004446 } else if (child->child->next) {
4447 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 goto error;
4449 }
4450 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004451 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 /* check here differs from a generic prefix check, since this prefix
4453 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004454 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004455 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 goto error;
4457 }
4458 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004459
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004461 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004462
4463 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004464 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004466 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004468 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004470 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004471 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004472 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004474 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004475 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004476 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004477 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004478 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004479 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004482 } else if (!strcmp(child->name, "container") ||
4483 !strcmp(child->name, "leaf-list") ||
4484 !strcmp(child->name, "leaf") ||
4485 !strcmp(child->name, "list") ||
4486 !strcmp(child->name, "choice") ||
4487 !strcmp(child->name, "uses") ||
4488 !strcmp(child->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004489 lyxml_unlink_elem(module->ctx, child, 1);
4490 lyxml_add_child(module->ctx, &root, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004491 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 /* keep groupings separated and process them before other data statements */
Michal Vaskof8879c22015-08-21 09:07:36 +02004493 lyxml_unlink_elem(module->ctx, child, 1);
4494 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004497 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004499 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 goto error;
4501 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004502 module->dsc = read_yin_subnode(ctx, child, "text");
4503 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 if (!module->dsc) {
4505 goto error;
4506 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004507 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004509 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 goto error;
4511 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004512 module->ref = read_yin_subnode(ctx, child, "text");
4513 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 if (!module->ref) {
4515 goto error;
4516 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004517 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004519 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 goto error;
4521 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004522 module->org = read_yin_subnode(ctx, child, "text");
4523 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 if (!module->org) {
4525 goto error;
4526 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004527 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004529 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 goto error;
4531 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004532 module->contact = read_yin_subnode(ctx, child, "text");
4533 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 if (!module->contact) {
4535 goto error;
4536 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004537 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 /* TODO: support YANG 1.1 ? */
4539 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004540 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004541 goto error;
4542 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004543 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004545 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 goto error;
4547 }
4548 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004549 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004550
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004551 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004552 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004553 lyxml_unlink_elem(module->ctx, child, 1);
4554 lyxml_add_child(module->ctx, &rpcs, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004555 } else if (!strcmp(child->name, "notification")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004556 lyxml_unlink_elem(module->ctx, child, 1);
4557 lyxml_add_child(module->ctx, &notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004558
Radek Krejci1d82ef62015-08-07 14:44:40 +02004559 } else if (!strcmp(child->name, "extension")) {
4560 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004561
Radek Krejci3d468122015-10-02 13:36:12 +02004562 /* we have the following supported (hardcoded) extensions: */
4563 /* ietf-netconf's get-filter-element-attributes */
4564 if (!strcmp(module->ns, LY_NSNC) &&
4565 !strcmp(value, "get-filter-element-attributes")) {
4566 LOGDBG("NETCONF filter extension found");
4567 /* NACM's default-deny-write and default-deny-all */
4568 } else if (!strcmp(module->ns, LY_NSNACM) &&
4569 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4570 LOGDBG("NACM extension found");
4571 /* other extensions are not supported, so inform about such an extension */
4572 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004573 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004574 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004575 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004577 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 }
4580 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 if (!submodule) {
4583 /* check for mandatory statements */
4584 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004585 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004586 goto error;
4587 }
4588 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004589 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 goto error;
4591 }
4592 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 /* allocate arrays for elements with cardinality of 0..n */
4595 if (c_imp) {
4596 module->imp = calloc(c_imp, sizeof *module->imp);
4597 }
4598 if (c_rev) {
4599 module->rev = calloc(c_rev, sizeof *module->rev);
4600 }
4601 if (c_tpdf) {
4602 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4603 }
4604 if (c_ident) {
4605 module->ident = calloc(c_ident, sizeof *module->ident);
4606 }
4607 if (c_inc) {
4608 module->inc = calloc(c_inc, sizeof *module->inc);
4609 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004610 if (c_aug) {
4611 module->augment = calloc(c_aug, sizeof *module->augment);
4612 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004613 if (c_ftrs) {
4614 module->features = calloc(c_ftrs, sizeof *module->features);
4615 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004616 if (c_dev) {
4617 module->deviation = calloc(c_dev, sizeof *module->deviation);
4618 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004621 LY_TREE_FOR(yin->child, child) {
4622 if (!strcmp(child->name, "import")) {
4623 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 module->imp_size++;
4625 if (r) {
4626 goto error;
4627 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 /* check duplicities in imported modules */
4630 for (i = 0; i < module->imp_size - 1; i++) {
4631 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004632 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 goto error;
4634 }
4635 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004636 } else if (!strcmp(child->name, "include")) {
4637 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 module->inc_size++;
4639 if (r) {
4640 goto error;
4641 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 /* check duplications in include submodules */
4644 for (i = 0; i < module->inc_size - 1; i++) {
4645 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004646 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004647 module->inc[i].submodule->name);
4648 goto error;
4649 }
4650 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (!strcmp(child->name, "revision")) {
4652 GETVAL(value, child, "date");
4653 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
4656 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4657 /* check uniqueness of the revision date - not required by RFC */
4658 for (i = 0; i < module->rev_size; i++) {
4659 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004661 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 }
4663 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004664
Radek Krejci1d82ef62015-08-07 14:44:40 +02004665 LY_TREE_FOR(child->child, child2) {
4666 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004668 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 goto error;
4670 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 if (!module->rev[module->rev_size].dsc) {
4673 goto error;
4674 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004675 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004677 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004678 goto error;
4679 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 if (!module->rev[module->rev_size].ref) {
4682 goto error;
4683 }
4684 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004685 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 goto error;
4687 }
4688 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 /* keep the latest revision at position 0 */
4691 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4692 /* switch their position */
4693 value = strdup(module->rev[0].date);
4694 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4695 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4696 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4699 value = module->rev[0].dsc;
4700 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4701 module->rev[module->rev_size].dsc = value;
4702 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4705 value = module->rev[0].ref;
4706 module->rev[0].ref = module->rev[module->rev_size].ref;
4707 module->rev[module->rev_size].ref = value;
4708 }
4709 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004711 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 } else if (!strcmp(child->name, "typedef")) {
4713 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 if (r) {
4717 goto error;
4718 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 } else if (!strcmp(child->name, "identity")) {
4720 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004721 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004723 if (r) {
4724 goto error;
4725 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004726 } else if (!strcmp(child->name, "feature")) {
4727 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004728 module->features_size++;
4729
4730 if (r) {
4731 goto error;
4732 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004733 } else if (!strcmp(child->name, "augment")) {
4734 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004735 module->augment_size++;
4736
4737 if (r) {
4738 goto error;
4739 }
4740
4741 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4742 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 } else if (!strcmp(child->name, "deviation")) {
4744 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004745 module->deviation_size++;
4746
4747 if (r) {
4748 goto error;
4749 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004752
Radek Krejcif5be10f2015-06-16 13:29:36 +02004753 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 * refer to them
4755 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004756 LY_TREE_FOR_SAFE(grps.child, next, child) {
4757 node = read_yin_grouping(module, NULL, child, 0, unres);
4758 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004759 goto error;
4760 }
Radek Krejci74705112015-06-05 10:25:44 +02004761
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004763 }
Radek Krejci74705112015-06-05 10:25:44 +02004764
Radek Krejcif5be10f2015-06-16 13:29:36 +02004765 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004766 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004767
Radek Krejci1d82ef62015-08-07 14:44:40 +02004768 if (!strcmp(child->name, "container")) {
4769 node = read_yin_container(module, NULL, child, 1, unres);
4770 } else if (!strcmp(child->name, "leaf-list")) {
4771 node = read_yin_leaflist(module, NULL, child, 1, unres);
4772 } else if (!strcmp(child->name, "leaf")) {
4773 node = read_yin_leaf(module, NULL, child, 1, unres);
4774 } else if (!strcmp(child->name, "list")) {
4775 node = read_yin_list(module, NULL, child, 1, unres);
4776 } else if (!strcmp(child->name, "choice")) {
4777 node = read_yin_choice(module, NULL, child, 1, unres);
4778 } else if (!strcmp(child->name, "uses")) {
4779 node = read_yin_uses(module, NULL, child, 1, unres);
4780 } else if (!strcmp(child->name, "anyxml")) {
4781 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004783 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004784 goto error;
4785 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004786
Radek Krejci1d82ef62015-08-07 14:44:40 +02004787 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004788 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004789
4790 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004791 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4792 node = read_yin_rpc(module, NULL, child, 0, unres);
4793 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004794 goto error;
4795 }
4796
Radek Krejci1d82ef62015-08-07 14:44:40 +02004797 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004798 }
4799
4800 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004801 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4802 node = read_yin_notif(module, NULL, child, 0, unres);
4803 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004804 goto error;
4805 }
4806
Radek Krejci1d82ef62015-08-07 14:44:40 +02004807 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004808 }
4809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004811
4812error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 /* cleanup */
4814 while (root.child) {
4815 lyxml_free_elem(module->ctx, root.child);
4816 }
4817 while (grps.child) {
4818 lyxml_free_elem(module->ctx, grps.child);
4819 }
4820 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004821 lyxml_free_elem(module->ctx, rpcs.child);
4822 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004823
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004824 free(unres->item);
4825 unres->item = NULL;
4826 free(unres->type);
4827 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004828 free(unres->str_snode);
4829 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004830#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004831 free(unres->line);
4832 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004833#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004834 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004837}
4838
Michal Vasko0d343d12015-08-24 14:57:36 +02004839/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004840struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004841yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004842{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004844 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 yin = lyxml_read(module->ctx, data, 0);
4850 if (!yin) {
4851 return NULL;
4852 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 /* check root element */
4855 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004856 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 goto error;
4858 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 GETVAL(value, yin, "name");
4861 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4862 goto error;
4863 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 submodule = calloc(1, sizeof *submodule);
4866 if (!submodule) {
4867 LOGMEM;
4868 goto error;
4869 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 submodule->ctx = module->ctx;
4872 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4873 submodule->type = 1;
4874 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004875 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004878 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 goto error;
4880 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 /* cleanup */
4883 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004888
4889error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 /* cleanup */
4891 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004892 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004893
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004894 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004895}
4896
Michal Vasko0d343d12015-08-24 14:57:36 +02004897/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004898struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004899yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004900{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004902 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 const char *value;
4904 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 yin = lyxml_read(ctx, data, 0);
4907 if (!yin) {
4908 return NULL;
4909 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 /* check root element */
4912 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004913 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 goto error;
4915 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004916
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004917 GETVAL(value, yin, "name");
4918 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4919 goto error;
4920 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004922 module = calloc(1, sizeof *module);
4923 if (!module) {
4924 LOGMEM;
4925 goto error;
4926 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 module->ctx = ctx;
4929 module->name = lydict_insert(ctx, value, strlen(value));
4930 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004931 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004932
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004933 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004934 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004935 goto error;
4936 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004937
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004938 /* add to the context's list of modules */
4939 if (ctx->models.used == ctx->models.size) {
4940 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4941 if (!newlist) {
4942 LOGMEM;
4943 goto error;
4944 }
4945 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4946 newlist[i] = NULL;
4947 }
4948 ctx->models.size *= 2;
4949 ctx->models.list = newlist;
4950 }
4951 for (i = 0; ctx->models.list[i]; i++) {
4952 /* check name (name/revision) and namespace uniqueness */
4953 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004954 if (ctx->models.list[i]->rev_size == module->rev_size) {
4955 /* both have the same number of revisions */
4956 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4957 /* both have the same revision -> we already have the same module */
4958 /* so free the new one and update the old one's implement flag if needed */
4959 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004960 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02004961 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004962
4963 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4964
4965 if (implement && !ctx->models.list[i]->implemented) {
4966 lyp_set_implemented(ctx->models.list[i]);
4967 }
4968 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004969 }
4970 }
Radek Krejcif647e612015-07-30 11:36:07 +02004971 /* else (both elses) keep searching, for now the caller is just adding
4972 * another revision of an already present schema
4973 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4975 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4976 ctx->models.list[i]->name, module->name, module->ns);
4977 goto error;
4978 }
4979 }
4980 ctx->models.list[i] = module;
4981 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004982 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004983
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004984 /* cleanup */
4985 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004987 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004988
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004989 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004990
4991error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 /* cleanup */
4993 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004994 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004996 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004997}