blob: 601df67574844fe3f355a8ed56a0976298eff308 [file] [log] [blame]
Radek Krejcida04f4a2015-05-21 12:54:09 +02001/**
2 * @file yin.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief YIN parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Radek Krejci812b10a2015-05-28 16:48:25 +020022#include <assert.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020023#include <ctype.h>
Radek Krejci8b4f23c2015-06-02 16:09:25 +020024#include <errno.h>
25#include <limits.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020026#include <stdint.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020027#include <stdlib.h>
28#include <string.h>
Radek Krejci25d782a2015-05-22 15:03:23 +020029#include <stddef.h>
Michal Vasko69068852015-07-13 14:34:31 +020030#include <sys/types.h>
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +020031#include <pcre.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
Radek Krejci998a0b82015-08-17 13:14:36 +020033#include "libyang.h"
34#include "common.h"
35#include "context.h"
Radek Krejci41912fe2015-10-22 10:22:12 +020036#include "dict_private.h"
Michal Vaskofcdac172015-10-07 09:35:05 +020037#include "xpath.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020038#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020039#include "resolve.h"
40#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020041#include "xml_internal.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020042
Radek Krejcice7fb782015-05-29 16:52:34 +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");
Michal Vaskoc94283a2015-10-29 09:07:20 +0100373 ident->name = value;
Michal Vasko4cfcd252015-08-03 14:31:10 +0200374
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 Vaskoc94283a2015-10-29 09:07:20 +0100391 value = transform_schema2json(module, value, LOGLINE(node));
392 if (!value) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200393 return EXIT_FAILURE;
394 }
Michal Vaskoc94283a2015-10-29 09:07:20 +0100395
396 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
397 lydict_remove(module->ctx, value);
398 return EXIT_FAILURE;
399 }
400 lydict_remove(module->ctx, value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200401 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200402 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403 return EXIT_FAILURE;
404 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200405 }
Radek Krejci04581c62015-05-22 21:24:00 +0200406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407 return EXIT_SUCCESS;
Michal Vasko2d851a92015-10-20 16:16:36 +0200408
409error:
410 return EXIT_FAILURE;
Radek Krejci04581c62015-05-22 21:24:00 +0200411}
412
Michal Vasko0d343d12015-08-24 14:57:36 +0200413/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200414static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200415read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200416{
Radek Krejci73adb602015-07-02 18:07:40 +0200417 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200418 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200419
Radek Krejci73adb602015-07-02 18:07:40 +0200420 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200421 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
422 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200423 continue;
424 }
425
Radek Krejci41726f92015-06-19 13:11:05 +0200426 if (!strcmp(child->name, "description")) {
427 if (restr->dsc) {
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->dsc = read_yin_subnode(ctx, child, "text");
432 if (!restr->dsc) {
433 return EXIT_FAILURE;
434 }
435 } else if (!strcmp(child->name, "reference")) {
436 if (restr->ref) {
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 }
440 restr->ref = read_yin_subnode(ctx, child, "text");
441 if (!restr->ref) {
442 return EXIT_FAILURE;
443 }
444 } else if (!strcmp(child->name, "error-app-tag")) {
445 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200446 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200447 return EXIT_FAILURE;
448 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200449 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200450 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200451 } else if (!strcmp(child->name, "error-message")) {
452 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200453 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200454 return EXIT_FAILURE;
455 }
456 restr->emsg = read_yin_subnode(ctx, child, "value");
457 if (!restr->emsg) {
458 return EXIT_FAILURE;
459 }
460 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200461 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200462 return EXIT_FAILURE;
463 }
Radek Krejci41726f92015-06-19 13:11:05 +0200464 }
465
466 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200467
468error:
469 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200470}
471
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200472/* logs directly */
Radek Krejci41726f92015-06-19 13:11:05 +0200473static int
Radek Krejcib8048692015-08-05 13:36:34 +0200474fill_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 +0200475 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200476{
Michal Vasko69068852015-07-13 14:34:31 +0200477#define REGEX_ERR_LEN 128
Michal Vasko1dca6882015-10-22 14:29:42 +0200478 const char *value, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200479 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200480 struct lys_restr **restr;
481 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200482 pcre *precomp;
483 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200484 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200485 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200486
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200487 GETVAL(value, yin, "name");
Michal Vaskofba15262015-10-21 12:10:28 +0200488 value = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko1dca6882015-10-22 14:29:42 +0200489 if (!value) {
490 goto error;
Michal Vaskoa5835e92015-10-20 15:07:39 +0200491 }
Michal Vaskob362b4c2015-10-20 15:15:46 +0200492
493 i = parse_identifier(value);
494 if (i < 1) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200495 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[-i], &value[-i]);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200496 goto error;
497 }
498 /* module name */
499 if (value[i]) {
500 type->module_name = lydict_insert(module->ctx, value, i);
501 value += i;
Michal Vasko534f8442015-10-21 13:25:49 +0200502 if ((value[0] != ':') || (parse_identifier(value + 1) < 1)) {
Michal Vasko0160ffe2015-10-21 13:25:26 +0200503 LOGVAL(LYE_INCHAR, LOGLINE(yin), value[0], value);
Michal Vaskob362b4c2015-10-20 15:15:46 +0200504 goto error;
505 }
Michal Vasko534f8442015-10-21 13:25:49 +0200506 ++value;
Michal Vaskob362b4c2015-10-20 15:15:46 +0200507 }
Michal Vaskoa5835e92015-10-20 15:07:39 +0200508
Michal Vasko1dca6882015-10-22 14:29:42 +0200509 rc = resolve_superior_type(value, type->module_name, module, parent, &type->der);
Michal Vaskof7eee892015-08-24 15:03:11 +0200510 if (rc == -1) {
Michal Vasko1dca6882015-10-22 14:29:42 +0200511 LOGVAL(LYE_INMOD, LOGLINE(yin), type->module_name);
Michal Vaskof7eee892015-08-24 15:03:11 +0200512 goto error;
513 } else if (rc == EXIT_FAILURE) {
514 /* HACK for unres */
515 type->der = (struct lys_tpdf *)parent;
516 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200517 if (rc == -1) {
518 goto error;
Michal Vaskof7eee892015-08-24 15:03:11 +0200519 } else {
520 return EXIT_SUCCESS;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200521 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200522 }
523 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200526 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200527 /* RFC 6020 9.7.4 - bit */
528
529 /* get bit specifications, at least one must be present */
530 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200531 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
532 /* garbage */
533 lyxml_free_elem(module->ctx, node);
534 continue;
535 }
536
Radek Krejci994b6f62015-06-18 16:47:27 +0200537 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200538 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200539 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200540 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200541 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200542 }
543 }
Radek Krejciac781922015-07-09 15:35:14 +0200544 if (!type->der->type.der && !type->info.bits.count) {
545 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200546 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200547 goto error;
548 }
Radek Krejciac781922015-07-09 15:35:14 +0200549 if (type->der->type.der && type->info.bits.count) {
550 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200551 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200552 goto error;
553 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200554
555 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200556 p = 0;
557 i = -1;
558 LY_TREE_FOR(yin->child, next) {
559 i++;
560
561 GETVAL(value, next, "name");
562 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200563 goto error;
564 }
565 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200566 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200567 type->info.bits.count = i + 1;
568 goto error;
569 }
570
571 /* check the name uniqueness */
572 for (j = 0; j < i; j++) {
573 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200574 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200575 type->info.bits.count = i + 1;
576 goto error;
577 }
578 }
579
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200581 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200582 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
583 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200584 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200585 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200586
Radek Krejci0d70c372015-07-02 16:23:10 +0200587 if (!strcmp(node->name, "position")) {
588 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200589 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200590
591 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200592 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200593 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200594 type->info.bits.count = i + 1;
595 goto error;
596 }
597 type->info.bits.bit[i].pos = (uint32_t)p_;
598
599 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200600 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200601 p = type->info.bits.bit[i].pos;
602 p++;
603 } else {
604 /* check that the value is unique */
605 for (j = 0; j < i; j++) {
606 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200607 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 +0200608 type->info.bits.count = i + 1;
609 goto error;
610 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200611 }
612 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200613 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200614 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200615 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200616 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200617 }
618 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200619 /* assign value automatically */
620 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200621 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200622 type->info.bits.count = i + 1;
623 goto error;
624 }
625 type->info.bits.bit[i].pos = (uint32_t)p;
626 p++;
627 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200628
629 /* keep them ordered by position */
630 j = i;
631 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
632 /* switch them */
633 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
634 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
635 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
636 j--;
637 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200638 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200639 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200640
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200641 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200642 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200643 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200644 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
645 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200646 continue;
647 }
648
Radek Krejcif9401c32015-06-26 16:47:36 +0200649 if (!strcmp(node->name, "range")) {
650 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200651 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200652 goto error;
653 }
654
655 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200656 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200657 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200658 goto error;
659 }
660 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
661 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
662
663 /* get possible substatements */
664 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
665 goto error;
666 }
667 } else if (!strcmp(node->name, "fraction-digits")) {
668 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200669 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200670 goto error;
671 }
672 GETVAL(value, node, "value");
673 v = strtol(value, NULL, 10);
674
675 /* range check */
676 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200677 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200678 goto error;
679 }
680 type->info.dec64.dig = (uint8_t)v;
681 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200682 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200683 goto error;
684 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200685 }
686
687 /* mandatory sub-statement(s) check */
688 if (!type->info.dec64.dig && !type->der->type.der) {
689 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200690 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200691 goto error;
692 }
Radek Krejci7511f402015-07-10 09:56:30 +0200693 if (type->info.dec64.dig && type->der->type.der) {
694 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200695 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200696 goto error;
697 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200698 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200699
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200700 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200701 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200702
Radek Krejci994b6f62015-06-18 16:47:27 +0200703 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200704 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200705 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
706 /* garbage */
707 lyxml_free_elem(module->ctx, node);
708 continue;
709 }
710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200711 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200712 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200713 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200714 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200715 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 }
717 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200718 if (!type->der->type.der && !type->info.enums.count) {
719 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200720 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200721 goto error;
722 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200723 if (type->der->type.der && type->info.enums.count) {
724 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200725 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200726 goto error;
727 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200728
Radek Krejci1574a8d2015-08-03 14:16:52 +0200729 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200730 v = 0;
731 i = -1;
732 LY_TREE_FOR(yin->child, next) {
733 i++;
734
735 GETVAL(value, next, "name");
736 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200737 goto error;
738 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200739 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200740 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200741 type->info.enums.count = i + 1;
742 goto error;
743 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200744
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200745 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200746 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200747 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200748 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200749 type->info.enums.count = i + 1;
750 goto error;
751 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200753 /* check the name uniqueness */
754 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200755 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200756 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200757 type->info.enums.count = i + 1;
758 goto error;
759 }
760 }
Radek Krejci04581c62015-05-22 21:24:00 +0200761
Radek Krejci0d70c372015-07-02 16:23:10 +0200762 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200763 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200764 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
765 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200766 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200767 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768
Radek Krejci0d70c372015-07-02 16:23:10 +0200769 if (!strcmp(node->name, "value")) {
770 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200771 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200772
773 /* range check */
774 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200775 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200776 type->info.enums.count = i + 1;
777 goto error;
778 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200779 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200780
781 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200782 if (type->info.enums.enm[i].value > v) {
783 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200784 v++;
785 } else {
786 /* check that the value is unique */
787 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200788 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200789 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200790 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200791 type->info.enums.count = i + 1;
792 goto error;
793 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 }
795 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200796 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200797 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200798 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200799 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200800 }
801 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 /* assign value automatically */
803 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200804 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200805 type->info.enums.count = i + 1;
806 goto error;
807 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200808 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200809 v++;
810 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 }
812 break;
813
814 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200815 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816
817 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200818 LY_TREE_FOR_SAFE(yin->child, next, node) {
819 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
820 /* garbage */
821 lyxml_free_elem(module->ctx, node);
822 continue;
823 }
824
825 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200826 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200827 goto error;
828 }
829 }
830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200831 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200832 if (type->der->type.der) {
833 /* this is just a derived type with no base specified/required */
834 break;
835 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200836 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200837 goto error;
838 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200839 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200840 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841 goto error;
842 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200843 GETVAL(value, yin->child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200844 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200845 goto error;
846 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200847 break;
848
849 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200850 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200851 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200852 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
853 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200854 continue;
855 }
856
Radek Krejciaf351422015-06-19 14:49:38 +0200857 if (!strcmp(node->name, "require-instance")) {
858 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200859 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200860 goto error;
861 }
862 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200863 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200864 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200865 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200866 type->info.inst.req = -1;
867 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200868 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200869 goto error;
870 }
871 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200872 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200873 goto error;
874 }
Radek Krejciaf351422015-06-19 14:49:38 +0200875 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200877 break;
878
Radek Krejcif2860132015-06-20 12:37:20 +0200879 case LY_TYPE_BINARY:
880 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200881 case LY_TYPE_INT8:
882 case LY_TYPE_INT16:
883 case LY_TYPE_INT32:
884 case LY_TYPE_INT64:
885 case LY_TYPE_UINT8:
886 case LY_TYPE_UINT16:
887 case LY_TYPE_UINT32:
888 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200889 /* RFC 6020 9.2.4 - range */
890
891 /* length and range are actually the same restriction, so process
892 * them by this common code, we just need to differ the name and
893 * structure where the information will be stored
894 */
895 if (type->base == LY_TYPE_BINARY) {
896 restr = &type->info.binary.length;
897 name = "length";
898 } else {
899 restr = &type->info.num.range;
900 name = "range";
901 }
902
Radek Krejci73adb602015-07-02 18:07:40 +0200903 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200904 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
905 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200906 continue;
907 }
908
Radek Krejcif2860132015-06-20 12:37:20 +0200909 if (!strcmp(node->name, name)) {
910 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200911 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200912 goto error;
913 }
914
915 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200916 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200917 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200918 goto error;
919 }
920 *restr = calloc(1, sizeof **restr);
921 (*restr)->expr = lydict_insert(module->ctx, value, 0);
922
923 /* get possible substatements */
924 if (read_restr_substmt(module->ctx, *restr, node)) {
925 goto error;
926 }
927 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200928 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200929 goto error;
930 }
Radek Krejcif2860132015-06-20 12:37:20 +0200931 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200932 break;
933
934 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200935 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200936 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200937 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
938 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200939 continue;
940 }
941
Radek Krejcidc4c1412015-06-19 15:39:54 +0200942 if (!strcmp(node->name, "path")) {
943 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200944 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200945 goto error;
946 }
947
948 GETVAL(value, node, "value");
Michal Vasko1dca6882015-10-22 14:29:42 +0200949 /* store in the JSON format */
Michal Vaskofba15262015-10-21 12:10:28 +0200950 type->info.lref.path = transform_schema2json(module, value, LOGLINE(node));
Michal Vasko1dca6882015-10-22 14:29:42 +0200951 if (!type->info.lref.path) {
952 goto error;
953 }
Michal Vasko0bd29d12015-08-19 11:45:49 +0200954 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200955 goto error;
956 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200957
Radek Krejcidc4c1412015-06-19 15:39:54 +0200958 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200959 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200960 goto error;
961 }
Radek Krejci73adb602015-07-02 18:07:40 +0200962 }
963
964 if (!type->info.lref.path) {
965 if (type->der->type.der) {
966 /* this is just a derived type with no path specified/required */
967 break;
968 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200969 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200970 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200971 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200972 break;
973
974 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200975 /* RFC 6020 9.4.4 - length */
976 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200977 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200978 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200979 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
980 /* garbage */
981 lyxml_free_elem(module->ctx, node);
982 continue;
983 }
984
Radek Krejci3733a802015-06-19 13:43:21 +0200985 if (!strcmp(node->name, "length")) {
986 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200987 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200988 goto error;
989 }
990
991 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200992 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200993 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200994 goto error;
995 }
996 type->info.str.length = calloc(1, sizeof *type->info.str.length);
997 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
998
Radek Krejci5fbc9162015-06-19 14:11:11 +0200999 /* get possible sub-statements */
1000 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001001 goto error;
1002 }
Radek Krejci82d971d2015-06-19 14:20:50 +02001003 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001004 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001005 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001006 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001007 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001008 goto error;
1009 }
1010 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001011 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001012 if (i) {
1013 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
1014 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001015 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +02001016
1017 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +02001018 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1019 if (!precomp) {
1020 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +02001021 free(type->info.str.patterns);
1022 goto error;
1023 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +02001024 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +02001025
Radek Krejci73adb602015-07-02 18:07:40 +02001026 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001027
1028 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +02001029 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +02001030 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001031 goto error;
1032 }
Radek Krejci73adb602015-07-02 18:07:40 +02001033 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001034 }
1035 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001036 break;
1037
1038 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001039 /* RFC 6020 7.4 - type */
1040 /* count number of types in union */
1041 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001042 LY_TREE_FOR_SAFE(yin->child, next, node) {
1043 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1044 /* garbage */
1045 lyxml_free_elem(module->ctx, node);
1046 continue;
1047 }
1048
Radek Krejcie4c366b2015-07-02 10:11:31 +02001049 if (!strcmp(node->name, "type")) {
1050 i++;
1051 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001052 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001053 goto error;
1054 }
1055 }
1056
1057 if (!i) {
1058 if (type->der->type.der) {
1059 /* this is just a derived type with no base specified/required */
1060 break;
1061 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001062 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001063 goto error;
1064 }
1065
1066 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001067 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001068 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001069 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001070 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001071 goto error;
1072 }
1073 type->info.uni.count++;
1074
1075 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001076 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001077 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001078 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001079 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001080 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001081 goto error;
1082 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001083 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001084 break;
1085
1086 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001087 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1089 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001090 LY_TREE_FOR(yin->child, node) {
1091 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001092 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001093 goto error;
1094 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001095 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 break;
1097 }
1098
1099 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001100
1101error:
1102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001104}
1105
Michal Vasko0d343d12015-08-24 14:57:36 +02001106/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001108fill_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 +02001109{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001111 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001112 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 GETVAL(value, yin, "name");
1115 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1116 goto error;
1117 }
1118 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001120 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001121 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 goto error;
1123 }
Radek Krejcieac35532015-05-31 19:09:15 +02001124
Radek Krejci73adb602015-07-02 18:07:40 +02001125 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001126 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1127 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001128 continue;
1129 }
1130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001131 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001132 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001133 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001134 goto error;
1135 }
Radek Krejci73adb602015-07-02 18:07:40 +02001136 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1137 goto error;
1138 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001139 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 } else if (!strcmp(node->name, "default")) {
1141 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001142 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001143 goto error;
1144 }
1145 GETVAL(value, node, "value");
1146 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001147 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 } else if (!strcmp(node->name, "units")) {
1149 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001150 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001151 goto error;
1152 }
1153 GETVAL(value, node, "name");
1154 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1155 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001156 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001157 goto error;
1158 }
1159 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001160
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001161 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001162 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001163 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001164 goto error;
1165 }
Radek Krejcieac35532015-05-31 19:09:15 +02001166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001167 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001168 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001169 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001170 goto error;
1171 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001172 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001174 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001175
1176error:
1177
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001178 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001179}
1180
Michal Vasko0d343d12015-08-24 14:57:36 +02001181/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001182static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001183fill_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 +02001184{
1185 const char *value;
1186 struct lyxml_elem *child, *next;
Michal Vasko2d851a92015-10-20 16:16:36 +02001187 int c = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001188
Radek Krejcib05774c2015-06-18 13:52:59 +02001189 GETVAL(value, yin, "name");
1190 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1191 goto error;
1192 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001193 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001194 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001195
Radek Krejci76512572015-08-04 09:47:08 +02001196 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001197 goto error;
1198 }
1199
1200 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001201 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1202 /* garbage */
1203 lyxml_free_elem(module->ctx, child);
1204 continue;
1205 }
1206
Radek Krejci3cf9e222015-06-18 11:37:50 +02001207 if (!strcmp(child->name, "if-feature")) {
1208 c++;
1209 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001210 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001211 goto error;
1212 }
1213 }
1214
1215 if (c) {
1216 f->features = calloc(c, sizeof *f->features);
1217 }
Radek Krejci73adb602015-07-02 18:07:40 +02001218 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001219 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02001220 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02001221 goto error;
1222 }
1223 ret = unres_schema_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value,
1224 LOGLINE(child));
1225 lydict_remove(module->ctx, value);
1226 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001227 goto error;
1228 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001229 }
1230
Radek Krejci3cf9e222015-06-18 11:37:50 +02001231 return EXIT_SUCCESS;
1232
1233error:
1234
1235 return EXIT_FAILURE;
1236}
1237
Michal Vasko0d343d12015-08-24 14:57:36 +02001238/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001239static int
Radek Krejcib8048692015-08-05 13:36:34 +02001240fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001241{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001242 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001244 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02001245 must->expr = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02001246 if (!must->expr) {
1247 goto error;
1248 }
Radek Krejci800af702015-06-02 13:46:01 +02001249
Radek Krejci41726f92015-06-19 13:11:05 +02001250 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001251
Radek Krejci41726f92015-06-19 13:11:05 +02001252error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001255}
1256
Michal Vasko0d343d12015-08-24 14:57:36 +02001257/* logs directly
1258 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001259 * type: 0 - min, 1 - max
1260 */
1261static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001262deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001263{
1264 const char *value;
1265 char *endptr;
1266 unsigned long val;
1267 uint32_t *ui32val;
1268
1269 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001270 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001271 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001272 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001273 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001274 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001275 }
Radek Krejci76512572015-08-04 09:47:08 +02001276 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001277 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001278 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001279 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001280 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001281 }
1282 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001283 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1284 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001285 goto error;
1286 }
1287
1288 GETVAL(value, node, "value");
1289 while (isspace(value[0])) {
1290 value++;
1291 }
1292
1293 /* convert it to uint32_t */
1294 errno = 0;
1295 endptr = NULL;
1296 val = strtoul(value, &endptr, 10);
1297 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001298 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001299 goto error;
1300 }
1301 if (type) {
1302 d->max = (uint32_t)val;
1303 } else {
1304 d->min = (uint32_t)val;
1305 }
1306
1307 if (d->mod == LY_DEVIATE_ADD) {
1308 /* check that there is no current value */
1309 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001310 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1311 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001312 goto error;
1313 }
1314 }
1315
1316 if (d->mod == LY_DEVIATE_DEL) {
1317 /* check values */
1318 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001319 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1320 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001321 goto error;
1322 }
1323 /* remove current min-elements value of the target */
1324 *ui32val = 0;
1325 } else { /* add (already checked) and replace */
1326 /* set new value specified in deviation */
1327 *ui32val = (uint32_t)val;
1328 }
1329
1330 return EXIT_SUCCESS;
1331
1332error:
1333
1334 return EXIT_FAILURE;
1335}
1336
Michal Vasko0d343d12015-08-24 14:57:36 +02001337/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001338static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001339fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001340{
1341 const char *value, **stritem;
1342 struct lyxml_elem *next, *child, *develem;
1343 int c_dev = 0, c_must, c_uniq;
1344 int f_min = 0; /* flags */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001345 int i, j, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001346 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001347 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001348 struct lys_node_choice *choice = NULL;
1349 struct lys_node_leaf *leaf = NULL;
1350 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001351 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001352 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001353 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001354
1355 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001356 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001357 if (!dev->target_name) {
1358 goto error;
1359 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001360
1361 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001362 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1363 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001364 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001365 goto error;
1366 }
1367 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001368 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001369 goto error;
1370 }
1371 /* mark the target module as deviated */
1372 dev->target->module->deviated = 1;
1373
1374 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001375 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1376 /* garbage */
1377 lyxml_free_elem(module->ctx, child);
1378 continue;
1379 }
1380
Radek Krejcieb00f512015-07-01 16:44:58 +02001381 if (!strcmp(child->name, "description")) {
1382 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001383 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001384 goto error;
1385 }
1386 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1387 if (!dev->dsc) {
1388 goto error;
1389 }
1390 } else if (!strcmp(child->name, "reference")) {
1391 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001392 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001393 goto error;
1394 }
1395 dev->ref = read_yin_subnode(module->ctx, child, "text");
1396 if (!dev->ref) {
1397 goto error;
1398 }
1399 } else if (!strcmp(child->name, "deviate")) {
1400 c_dev++;
1401
1402 /* skip lyxml_free_elem() at the end of the loop, node will be
1403 * further processed later
1404 */
1405 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001406
Radek Krejcieb00f512015-07-01 16:44:58 +02001407 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001408 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001409 goto error;
1410 }
1411
1412 lyxml_free_elem(module->ctx, child);
1413 }
1414
1415 if (c_dev) {
1416 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1417 }
1418
1419 LY_TREE_FOR(yin->child, develem) {
1420 /* init */
1421 f_min = 0;
1422 c_must = 0;
1423 c_uniq = 0;
1424
1425 /* get deviation type */
1426 GETVAL(value, develem, "value");
1427 if (!strcmp(value, "not-supported")) {
1428 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1429 /* no property expected in this case */
1430 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001431 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001432 goto error;
1433 }
1434
Radek Krejci5b917642015-07-02 09:03:13 +02001435 /* and neither any other deviate statement is expected,
1436 * not-supported deviation must be the only deviation of the target
1437 */
1438 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001439 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1440 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001441 goto error;
1442 }
1443
1444
Radek Krejcieb00f512015-07-01 16:44:58 +02001445 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001446 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001447 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001448
Radek Krejci5b917642015-07-02 09:03:13 +02001449 dev->deviate_size = 1;
1450 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001451 } else if (!strcmp(value, "add")) {
1452 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1453 } else if (!strcmp(value, "replace")) {
1454 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1455 } else if (!strcmp(value, "delete")) {
1456 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1457 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001458 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001459 goto error;
1460 }
1461 d = &dev->deviate[dev->deviate_size];
1462
1463 /* process deviation properties */
1464 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001465 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1466 /* garbage */
1467 lyxml_free_elem(module->ctx, child);
1468 continue;
1469 }
1470
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001472 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001473 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001474 goto error;
1475 }
1476
1477 /* for we deviate from RFC 6020 and allow config property even it is/is not
1478 * specified in the target explicitly since config property inherits. So we expect
1479 * that config is specified in every node. But for delete, we check that the value
1480 * is the same as here in deviation
1481 */
1482 GETVAL(value, child, "value");
1483 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001484 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001485 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001486 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001487 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001488 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001489 goto error;
1490 }
1491
1492 if (d->mod == LY_DEVIATE_DEL) {
1493 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001494 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001495 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1496 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001497 goto error;
1498 }
1499 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001500 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001501
1502 /* ... and inherit config value from the target's parent */
1503 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001504 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 } else {
1506 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001507 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 }
1509 } else { /* add and replace are the same in this case */
1510 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001511 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001512
1513 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001514 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001515 }
1516 } else if (!strcmp(child->name, "default")) {
1517 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001518 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001519 goto error;
1520 }
1521 GETVAL(value, child, "value");
1522 d->dflt = lydict_insert(module->ctx, value, 0);
1523
Radek Krejci76512572015-08-04 09:47:08 +02001524 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001525 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001526
1527 if (d->mod == LY_DEVIATE_ADD) {
1528 /* check that there is no current value */
1529 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001530 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1531 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 goto error;
1533 }
1534 }
1535
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001536 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1537 if (rc) {
1538 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1539 goto error;
1540 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001541 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001542 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001543 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1544 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001545 goto error;
1546 }
1547 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001548 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001549 if (!choice->dflt) {
1550 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001551 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001552 goto error;
1553 }
1554 }
Radek Krejci76512572015-08-04 09:47:08 +02001555 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001556 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001557
1558 if (d->mod == LY_DEVIATE_ADD) {
1559 /* check that there is no current value */
1560 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001561 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1562 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 goto error;
1564 }
1565 }
1566
1567 if (d->mod == LY_DEVIATE_DEL) {
1568 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001569 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1570 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001571 goto error;
1572 }
1573 /* remove value */
1574 lydict_remove(leaf->module->ctx, leaf->dflt);
1575 leaf->dflt = NULL;
1576 } else { /* add (already checked) and replace */
1577 /* remove value */
1578 lydict_remove(leaf->module->ctx, leaf->dflt);
1579
1580 /* set new value */
1581 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1582 }
1583 } else {
1584 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001585 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1586 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001587 goto error;
1588 }
1589 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001590 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001591 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001592 goto error;
1593 }
1594
1595 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001596 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001597 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1598 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001599 goto error;
1600 }
1601
1602 GETVAL(value, child, "value");
1603 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001604 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001605 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001606 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001608 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001609 goto error;
1610 }
1611
1612 if (d->mod == LY_DEVIATE_ADD) {
1613 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001614 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001615 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1616 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 goto error;
1618 }
1619 }
1620
1621 if (d->mod == LY_DEVIATE_DEL) {
1622 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001623 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001624 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1625 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 goto error;
1627 }
1628 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001629 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001630 } else { /* add (already checked) and replace */
1631 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001632 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001633
1634 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001635 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001636 }
1637 } else if (!strcmp(child->name, "min-elements")) {
1638 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001639 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001640 goto error;
1641 }
1642 f_min = 1;
1643
1644 if (deviate_minmax(dev->target, child, d, 0)) {
1645 goto error;
1646 }
1647 } else if (!strcmp(child->name, "max-elements")) {
1648 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001649 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 goto error;
1651 }
1652
1653 if (deviate_minmax(dev->target, child, d, 1)) {
1654 goto error;
1655 }
1656 } else if (!strcmp(child->name, "must")) {
1657 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001658 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1659 continue;
1660 } else if (!strcmp(child->name, "type")) {
1661 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001662 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001663 goto error;
1664 }
1665
1666 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001667 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001668 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001669 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001670 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001672 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1673 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001674 goto error;
1675 }
1676
1677 if (d->mod == LY_DEVIATE_ADD) {
1678 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001679 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1680 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001681 goto error;
1682 } else if (d->mod == LY_DEVIATE_DEL) {
1683 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001684 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1685 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001686 goto error;
1687 }
1688
1689 /* replace */
1690 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001691 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001692
1693 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001694 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001695 goto error;
1696 }
1697 d->type = t;
1698 } else if (!strcmp(child->name, "unique")) {
1699 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001700 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1701 continue;
1702 } else if (!strcmp(child->name, "units")) {
1703 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001704 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001705 goto error;
1706 }
1707
1708 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001709 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001710 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001711 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001712 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001714 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1715 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 goto error;
1717 }
1718
1719 /* get units value */
1720 GETVAL(value, child, "name");
1721 d->units = lydict_insert(module->ctx, value, 0);
1722
1723 /* apply to target */
1724 if (d->mod == LY_DEVIATE_ADD) {
1725 /* check that there is no current value */
1726 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001727 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1728 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 goto error;
1730 }
1731 }
1732
1733 if (d->mod == LY_DEVIATE_DEL) {
1734 /* check values */
1735 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001736 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1737 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 goto error;
1739 }
1740 /* remove current units value of the target */
1741 lydict_remove(dev->target->module->ctx, *stritem);
1742 } else { /* add (already checked) and replace */
1743 /* remove current units value of the target ... */
1744 lydict_remove(dev->target->module->ctx, *stritem);
1745
1746 /* ... and replace it with the value specified in deviation */
1747 *stritem = lydict_insert(module->ctx, value, 0);
1748 }
1749 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001750 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001751 goto error;
1752 }
1753
1754 lyxml_free_elem(module->ctx, child);
1755 }
1756
1757 if (c_must) {
1758 /* check target node type */
1759 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001760 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001761 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1762 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001763 break;
Radek Krejci76512572015-08-04 09:47:08 +02001764 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001765 trg_must = &((struct lys_node_container *)dev->target)->must;
1766 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001767 break;
Radek Krejci76512572015-08-04 09:47:08 +02001768 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001769 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1770 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 break;
Radek Krejci76512572015-08-04 09:47:08 +02001772 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001773 trg_must = &((struct lys_node_list *)dev->target)->must;
1774 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 break;
Radek Krejci76512572015-08-04 09:47:08 +02001776 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001777 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1778 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 break;
1780 default:
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
1786 if (d->mod == LY_DEVIATE_RPL) {
1787 /* remove target's musts and allocate new array for it */
1788 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001789 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1790 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001791 goto error;
1792 }
1793
1794 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001795 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001796 }
1797 free(*trg_must);
1798 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1799 d->must_size = c_must;
1800 *trg_must_size = 0;
1801 } else if (d->mod == LY_DEVIATE_ADD) {
1802 /* reallocate the must array of the target */
1803 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1804 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001805 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001806 d->must_size = c_must;
1807 } else { /* LY_DEVIATE_DEL */
1808 d->must = calloc(c_must, sizeof *d->must);
1809 }
1810 }
1811 if (c_uniq) {
1812 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001813 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001814 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1815 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001816 goto error;
1817 }
1818
Radek Krejcib8048692015-08-05 13:36:34 +02001819 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001820 if (d->mod == LY_DEVIATE_RPL) {
1821 /* remove target's unique and allocate new array for it */
1822 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001823 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1824 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001825 goto error;
1826 }
1827
1828 for (i = 0; i < list->unique_size; i++) {
1829 free(list->unique[i].leafs);
1830 }
1831 free(list->unique);
1832 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1833 d->unique_size = c_uniq;
1834 list->unique_size = 0;
1835 } else if (d->mod == LY_DEVIATE_ADD) {
1836 /* reallocate the unique array of the target */
1837 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1838 list->unique = d->unique;
1839 d->unique = &list->unique[list->unique_size];
1840 d->unique_size = c_uniq;
1841 } else { /* LY_DEVIATE_DEL */
1842 d->unique = calloc(c_uniq, sizeof *d->unique);
1843 }
1844 }
1845
1846 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001847 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001848 if (!strcmp(child->name, "must")) {
1849 if (d->mod == LY_DEVIATE_DEL) {
1850 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1851 goto error;
1852 }
1853
1854 /* find must to delete, we are ok with just matching conditions */
1855 for (i = 0; i < *trg_must_size; i++) {
1856 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1857 /* we have a match, free the must structure ... */
Michal Vasko5e7d9ca2015-10-23 10:37:28 +02001858 lys_restr_free(dev->target->module->ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001859 /* ... and maintain the array */
1860 (*trg_must_size)--;
1861 if (i != *trg_must_size) {
1862 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1863 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1864 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1865 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1866 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1867 }
1868 if (!(*trg_must_size)) {
1869 free(*trg_must);
1870 *trg_must = NULL;
1871 } else {
1872 (*trg_must)[*trg_must_size].expr = NULL;
1873 (*trg_must)[*trg_must_size].dsc = NULL;
1874 (*trg_must)[*trg_must_size].ref = NULL;
1875 (*trg_must)[*trg_must_size].eapptag = NULL;
1876 (*trg_must)[*trg_must_size].emsg = NULL;
1877 }
1878
1879 i = -1; /* set match flag */
1880 break;
1881 }
1882 }
1883 d->must_size++;
1884 if (i != -1) {
1885 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001886 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1887 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001888 goto error;
1889 }
1890 } else { /* replace or add */
1891 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1892 goto error;
1893 }
1894 (*trg_must_size)++;
1895 }
1896 } else if (!strcmp(child->name, "unique")) {
1897 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001898 GETVAL(value, child, "tag");
Michal Vasko184521f2015-09-24 13:14:26 +02001899 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], 0, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001900 goto error;
1901 }
1902
1903 /* find unique structures to delete */
1904 for (i = 0; i < list->unique_size; i++) {
1905 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1906 continue;
1907 }
1908
1909 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1910 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1911 break;
1912 }
1913 }
1914
1915 if (j == d->unique[d->unique_size].leafs_size) {
1916 /* we have a match, free the unique structure ... */
1917 free(list->unique[i].leafs);
1918 /* ... and maintain the array */
1919 list->unique_size--;
1920 if (i != list->unique_size) {
1921 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1922 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1923 }
1924
1925 if (!list->unique_size) {
1926 free(list->unique);
1927 list->unique = NULL;
1928 } else {
1929 list->unique[list->unique_size].leafs_size = 0;
1930 list->unique[list->unique_size].leafs = NULL;
1931 }
1932
1933 i = -1; /* set match flag */
1934 break;
1935 }
1936 }
1937
1938 d->unique_size++;
1939 if (i != -1) {
1940 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001941 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1942 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001943 goto error;
1944 }
1945 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001946 GETVAL(value, child, "tag");
Michal Vasko184521f2015-09-24 13:14:26 +02001947 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], 0, LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001948 goto error;
1949 }
1950 list->unique_size++;
1951 }
1952 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001953 }
Radek Krejci5b917642015-07-02 09:03:13 +02001954
1955 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001956 }
1957
Radek Krejcieb00f512015-07-01 16:44:58 +02001958 return EXIT_SUCCESS;
1959
1960error:
1961
1962 if (dev->deviate) {
1963 for (i = 0; i < dev->deviate_size; i++) {
1964 lydict_remove(module->ctx, dev->deviate[i].dflt);
1965 lydict_remove(module->ctx, dev->deviate[i].units);
1966
1967 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1968 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001969 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001970 }
1971 free(dev->deviate[i].must);
1972
1973 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1974 free(dev->deviate[i].unique[j].leafs);
1975 }
1976 free(dev->deviate[i].unique);
1977 }
1978 }
1979 free(dev->deviate);
1980 }
1981
1982 return EXIT_FAILURE;
1983}
1984
Michal Vasko0d343d12015-08-24 14:57:36 +02001985/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001986static int
Radek Krejcib8048692015-08-05 13:36:34 +02001987fill_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 +02001988 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001989{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001990 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001992 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02001993 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02001994
Michal Vasko591e0b22015-08-13 13:53:43 +02001995 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001996 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001997 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02001998 if (!aug->target_name) {
1999 goto error;
2000 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002001 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002002
Michal Vasko1d87a922015-08-21 12:57:16 +02002003 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002004 goto error;
2005 }
2006
2007 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002008 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2009 /* garbage */
2010 lyxml_free_elem(module->ctx, child);
2011 continue;
2012 }
2013
Radek Krejci3cf9e222015-06-18 11:37:50 +02002014 if (!strcmp(child->name, "if-feature")) {
2015 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002017 } else if (!strcmp(child->name, "when")) {
2018 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002019 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002020 goto error;
2021 }
2022
2023 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002024 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002026 goto error;
2027 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002028 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002029 goto error;
2030 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002031 lyxml_free_elem(module->ctx, child);
2032 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002033
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002034 /* check allowed data sub-statements */
2035 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002036 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002037 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002038 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002039 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002040 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002041 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002042 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002043 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002044 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002045 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002046 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002048 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002049 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002050 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002051 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002052 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002053 goto error;
2054 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002055
Radek Krejci1d82ef62015-08-07 14:44:40 +02002056 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002057 goto error;
2058 }
2059
2060 /* check for mandatory nodes - if the target node is in another module
2061 * the added nodes cannot be mandatory
2062 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002063 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002064 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002065 goto error;
2066 }
2067
Radek Krejci1d82ef62015-08-07 14:44:40 +02002068 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002069 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002070 }
2071
2072 if (c) {
2073 aug->features = calloc(c, sizeof *aug->features);
2074 }
2075
2076 LY_TREE_FOR_SAFE(yin->child, next, child) {
2077 if (!strcmp(child->name, "if-feature")) {
2078 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002079 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002080 goto error;
2081 }
2082 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value,
2083 LOGLINE(child));
2084 lydict_remove(module->ctx, value);
2085 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002086 goto error;
2087 }
Radek Krejci73adb602015-07-02 18:07:40 +02002088 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002089 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002090 }
2091
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002092 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002093 * connected to the tree and adjusted (if possible right now).
2094 * However, if this is augment in a uses, it gets resolved
2095 * when the uses does and cannot be resolved now for sure
2096 * (the grouping was not yet copied into uses).
2097 */
2098 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02002099 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002100 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2101 goto error;
2102 }
Michal Vasko49291b32015-08-06 09:49:41 +02002103 }
Radek Krejci106efc02015-06-10 14:36:27 +02002104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002106
2107error:
2108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002109 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002110}
2111
Michal Vasko0d343d12015-08-24 14:57:36 +02002112/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113static int
Michal Vasko0d204592015-10-07 09:50:04 +02002114fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002115{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 struct lyxml_elem *sub, *next;
2117 const char *value;
2118 char *endptr;
2119 int f_mand = 0, f_min = 0, f_max = 0;
2120 int c_must = 0;
2121 int r;
2122 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002123
Radek Krejci76512572015-08-04 09:47:08 +02002124 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 goto error;
2126 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002127
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002128 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002129 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002130 if (!rfn->target_name) {
2131 goto error;
2132 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002135 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2136 /* garbage */
2137 lyxml_free_elem(module->ctx, sub);
2138 continue;
2139 }
2140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 /* limited applicability */
2142 if (!strcmp(sub->name, "default")) {
2143 /* leaf or choice */
2144 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002145 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002146 goto error;
2147 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 /* check possibility of statements combination */
2150 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002151 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002153 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 goto error;
2155 }
2156 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002157 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 GETVAL(value, sub, "value");
2161 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2162 } else if (!strcmp(sub->name, "mandatory")) {
2163 /* leaf, choice or anyxml */
2164 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002165 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002166 goto error;
2167 }
2168 /* just checking the flags in leaf is not sufficient, we would allow
2169 * multiple mandatory statements with the "false" value
2170 */
2171 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 /* check possibility of statements combination */
2174 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002175 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002177 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002178 goto error;
2179 }
2180 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002181 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 GETVAL(value, sub, "value");
2185 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002186 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002188 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002190 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 goto error;
2192 }
2193 } else if (!strcmp(sub->name, "min-elements")) {
2194 /* list or leaf-list */
2195 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002196 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 goto error;
2198 }
2199 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 /* check possibility of statements combination */
2202 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002203 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002205 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 goto error;
2207 }
2208 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002209 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 GETVAL(value, sub, "value");
2213 while (isspace(value[0])) {
2214 value++;
2215 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 /* convert it to uint32_t */
2218 errno = 0;
2219 endptr = NULL;
2220 val = strtoul(value, &endptr, 10);
2221 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002222 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 goto error;
2224 }
2225 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002226
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 /* magic - bit 3 in flags means min set */
2228 rfn->flags |= 0x04;
2229 } else if (!strcmp(sub->name, "max-elements")) {
2230 /* list or leaf-list */
2231 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002232 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 goto error;
2234 }
2235 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002237 /* check possibility of statements combination */
2238 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002239 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002241 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 goto error;
2243 }
2244 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002245 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 GETVAL(value, sub, "value");
2249 while (isspace(value[0])) {
2250 value++;
2251 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 /* convert it to uint32_t */
2254 errno = 0;
2255 endptr = NULL;
2256 val = strtoul(value, &endptr, 10);
2257 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002258 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 goto error;
2260 }
2261 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002262
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002263 /* magic - bit 4 in flags means min set */
2264 rfn->flags |= 0x08;
2265 } else if (!strcmp(sub->name, "presence")) {
2266 /* container */
2267 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002268 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 goto error;
2270 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 /* check possibility of statements combination */
2273 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002274 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002276 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 goto error;
2278 }
2279 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002280 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 GETVAL(value, sub, "value");
2284 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2285 } else if (!strcmp(sub->name, "must")) {
2286 /* leaf-list, list, container or anyxml */
2287 /* check possibility of statements combination */
2288 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002289 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002291 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 goto error;
2293 }
2294 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002295 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002299 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002302 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002303 goto error;
2304 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 lyxml_free_elem(module->ctx, sub);
2307 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 /* process nodes with cardinality of 0..n */
2310 if (c_must) {
2311 rfn->must = calloc(c_must, sizeof *rfn->must);
2312 }
Radek Krejci73adb602015-07-02 18:07:40 +02002313 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002314 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002315 if (r) {
2316 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002317 }
Michal Vasko0d204592015-10-07 09:50:04 +02002318 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002319 goto error;
2320 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002323 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002324
2325error:
2326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002328}
2329
Michal Vasko0d343d12015-08-24 14:57:36 +02002330/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331static int
Radek Krejcib8048692015-08-05 13:36:34 +02002332fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002333{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 struct lyxml_elem *child;
2335 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002336 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002339 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2340 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002341 continue;
2342 }
2343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 if (!strcmp(child->name, "prefix")) {
2345 GETVAL(value, child, "value");
2346 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2347 goto error;
2348 }
2349 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2350 } else if (!strcmp(child->name, "revision-date")) {
2351 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002352 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002353 goto error;
2354 }
2355 GETVAL(value, child, "date");
2356 if (check_date(value, LOGLINE(child))) {
2357 goto error;
2358 }
2359 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2360 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002361 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002362 goto error;
2363 }
2364 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 /* check mandatory information */
2367 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002368 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 goto error;
2370 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002373
2374 /* check for circular import, store it if passed */
2375 if (!module->ctx->models.parsing) {
2376 count = 0;
2377 } else {
2378 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2379 if (value == module->ctx->models.parsing[count]) {
2380 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2381 goto error;
2382 }
2383 }
2384 }
2385 ++count;
2386 module->ctx->models.parsing =
2387 realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2388 module->ctx->models.parsing[count - 1] = value;
2389 module->ctx->models.parsing[count] = NULL;
2390
2391 /* try to load the module */
Radek Krejci63a91a92015-07-29 13:31:04 +02002392 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002394 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002395 }
2396
2397 /* remove the new module name now that its parsing is finished (even if failed) */
2398 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2399 LOGINT;
2400 }
2401 --count;
2402 if (count) {
2403 module->ctx->models.parsing[count] = NULL;
2404 } else {
2405 free(module->ctx->models.parsing);
2406 module->ctx->models.parsing = NULL;
2407 }
2408
2409 /* check the result */
2410 if (!imp->module) {
2411 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2412 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2413 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002414 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002415
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002417
2418error:
2419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002421}
2422
Michal Vasko0d343d12015-08-24 14:57:36 +02002423/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424static int
Radek Krejcib8048692015-08-05 13:36:34 +02002425fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002426{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427 struct lyxml_elem *child;
2428 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002429 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002432 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2433 /* garbage */
2434 continue;
2435 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002436 if (!strcmp(child->name, "revision-date")) {
2437 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002438 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 goto error;
2440 }
2441 GETVAL(value, child, "date");
2442 if (check_date(value, LOGLINE(child))) {
2443 goto error;
2444 }
2445 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2446 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002447 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002448 goto error;
2449 }
2450 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002452 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002453
2454 /* check for circular include, store it if passed */
2455 if (!module->ctx->models.parsing) {
2456 count = 0;
2457 } else {
2458 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2459 if (value == module->ctx->models.parsing[count]) {
2460 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2461 goto error;
2462 }
2463 }
2464 }
2465 ++count;
2466 module->ctx->models.parsing =
2467 realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2468 module->ctx->models.parsing[count - 1] = value;
2469 module->ctx->models.parsing[count] = NULL;
2470
2471 /* try to load the submodule */
Radek Krejci63a91a92015-07-29 13:31:04 +02002472 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 if (!inc->submodule) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002474 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value, inc->rev[0] ? inc->rev : NULL);
2475 }
2476
2477 /* remove the new submodule name now that its parsing is finished (even if failed) */
2478 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2479 LOGINT;
2480 }
2481 --count;
2482 if (count) {
2483 module->ctx->models.parsing[count] = NULL;
2484 } else {
2485 free(module->ctx->models.parsing);
2486 module->ctx->models.parsing = NULL;
2487 }
2488
2489 /* check the result */
2490 if (!inc->submodule) {
2491 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2492 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2493 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 /* check that belongs-to corresponds */
2497 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002498 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 }
2500 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002501 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Michal Vasko105aa752015-10-22 11:40:11 +02002502 LOGERR(LY_EVALID, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 goto error;
2504 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002505
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002506 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002507
2508error:
2509
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002511}
2512
Michal Vasko0d343d12015-08-24 14:57:36 +02002513/* logs directly
2514 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002515 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002516 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002517 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002518 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519static int
Radek Krejcib8048692015-08-05 13:36:34 +02002520read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002521 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002522{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002523 const char *value;
2524 struct lyxml_elem *sub, *next;
2525 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002527 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002528 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002529 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002531 if (opt & OPT_IDENT) {
2532 GETVAL(value, xmlnode, "name");
2533 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2534 goto error;
2535 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002536 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002537 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002538
Radek Krejci6764bb32015-07-03 15:16:04 +02002539 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002540 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002541 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002542 }
2543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002544 /* process local parameters */
2545 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002546 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002547 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002548 lyxml_free_elem(ctx, sub);
2549 continue;
2550 }
2551 if (strcmp(sub->ns->value, LY_NSYIN)) {
2552 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002553 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002554 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002555 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002556 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002557 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002558 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002559 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002560 goto error;
2561 }
2562 }
2563
2564 /* else garbage */
2565 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002566 continue;
2567 }
2568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002569 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002570 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002571 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002572 goto error;
2573 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002574 node->dsc = read_yin_subnode(ctx, sub, "text");
2575 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002576 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 }
2578 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002579 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002580 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002581 goto error;
2582 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002583 node->ref = read_yin_subnode(ctx, sub, "text");
2584 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002585 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002586 }
2587 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002588 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002589 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002590 goto error;
2591 }
2592 GETVAL(value, sub, "value");
2593 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002594 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002596 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002598 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002599 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002600 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002601 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 }
2603 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002604 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002605 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002606 goto error;
2607 }
2608 GETVAL(value, sub, "value");
2609 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002610 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002612 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002613 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002614 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002615 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002616 }
2617 } else {
2618 /* skip the lyxml_free_elem */
2619 continue;
2620 }
2621 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002623
Radek Krejci1d82ef62015-08-07 14:44:40 +02002624 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 /* get config flag from parent */
2626 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002627 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 } else {
2629 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002630 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 }
2632 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002633
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002635
2636error:
2637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002639}
2640
Michal Vasko0d343d12015-08-24 14:57:36 +02002641/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002642static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002643read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002644{
Radek Krejci76512572015-08-04 09:47:08 +02002645 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002646 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002647 const char *value;
2648
2649 retval = calloc(1, sizeof *retval);
2650
2651 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002652 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002653 if (!retval->cond) {
2654 goto error;
2655 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002656
Radek Krejci73adb602015-07-02 18:07:40 +02002657 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002658 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2659 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002660 continue;
2661 }
2662
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002663 if (!strcmp(child->name, "description")) {
2664 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002665 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002666 goto error;
2667 }
2668 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2669 if (!retval->dsc) {
2670 goto error;
2671 }
2672 } else if (!strcmp(child->name, "reference")) {
2673 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002674 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002675 goto error;
2676 }
2677 retval->ref = read_yin_subnode(module->ctx, child, "text");
2678 if (!retval->ref) {
2679 goto error;
2680 }
2681 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002682 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002683 goto error;
2684 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002685 }
2686
2687 return retval;
2688
2689error:
2690
Michal Vasko0308dd62015-10-07 09:14:40 +02002691 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002692 return NULL;
2693}
2694
Michal Vasko0d343d12015-08-24 14:57:36 +02002695/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002696static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002697read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2698 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002699{
Michal Vasko29fc0182015-08-24 15:02:39 +02002700 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002701 struct lys_node_case *cs;
2702 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002703 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002704 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002705
Radek Krejcie867c852015-08-27 09:52:34 +02002706 /* init */
2707 memset(&root, 0, sizeof root);
2708
Radek Krejci1d82ef62015-08-07 14:44:40 +02002709 cs = calloc(1, sizeof *cs);
2710 cs->nodetype = LYS_CASE;
2711 cs->prev = (struct lys_node *)cs;
2712 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002713
Radek Krejci6a113852015-07-03 16:04:20 +02002714 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 goto error;
2716 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002717
Radek Krejcia9544502015-08-14 08:24:29 +02002718 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2719
Michal Vasko3a0043f2015-08-12 12:11:30 +02002720 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002721 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002722 goto error;
2723 }
2724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 /* process choice's specific children */
2726 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002727 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2728 /* garbage */
2729 lyxml_free_elem(module->ctx, sub);
2730 continue;
2731 }
2732
Michal Vasko29fc0182015-08-24 15:02:39 +02002733 if (!strcmp(sub->name, "container") ||
2734 !strcmp(sub->name, "leaf-list") ||
2735 !strcmp(sub->name, "leaf") ||
2736 !strcmp(sub->name, "list") ||
2737 !strcmp(sub->name, "uses") ||
2738 !strcmp(sub->name, "choice") ||
2739 !strcmp(sub->name, "anyxml")) {
2740
Michal Vaskof3930de2015-10-22 12:03:59 +02002741 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002742 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002743 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002744 c_ftrs++;
2745 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2746 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002747 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002749 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002750 goto error;
2751 }
2752
Radek Krejci1d82ef62015-08-07 14:44:40 +02002753 cs->when = read_yin_when(module, sub);
2754 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002755 goto error;
2756 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002757 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002758 goto error;
2759 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002760
2761 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002763 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002767
Radek Krejci3cf9e222015-06-18 11:37:50 +02002768 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002769 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002770 }
Radek Krejci73adb602015-07-02 18:07:40 +02002771 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002772 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002773 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002774 goto error;
2775 }
2776 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value,
2777 LOGLINE(sub));
2778 lydict_remove(module->ctx, value);
2779 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002780 goto error;
2781 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 }
Radek Krejcib388c152015-06-04 17:03:03 +02002783
Michal Vasko29fc0182015-08-24 15:02:39 +02002784 /* last part - process data nodes */
2785 LY_TREE_FOR_SAFE(root.child, next, sub) {
2786 if (!strcmp(sub->name, "container")) {
2787 node = read_yin_container(module, retval, sub, resolve, unres);
2788 } else if (!strcmp(sub->name, "leaf-list")) {
2789 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2790 } else if (!strcmp(sub->name, "leaf")) {
2791 node = read_yin_leaf(module, retval, sub, resolve, unres);
2792 } else if (!strcmp(sub->name, "list")) {
2793 node = read_yin_list(module, retval, sub, resolve, unres);
2794 } else if (!strcmp(sub->name, "choice")) {
2795 node = read_yin_choice(module, retval, sub, resolve, unres);
2796 } else if (!strcmp(sub->name, "uses")) {
2797 node = read_yin_uses(module, retval, sub, resolve, unres);
2798 } else if (!strcmp(sub->name, "anyxml")) {
2799 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2800 }
2801 if (!node) {
2802 goto error;
2803 }
2804
2805 lyxml_free_elem(module->ctx, sub);
2806 }
2807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002809
2810error:
2811
Michal Vasko29fc0182015-08-24 15:02:39 +02002812 while (root.child) {
2813 lyxml_free_elem(module->ctx, root.child);
2814 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002815 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002817 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002818}
2819
Michal Vasko0d343d12015-08-24 14:57:36 +02002820/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002821static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002822read_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 +02002823{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002824 struct lyxml_elem *sub, *next;
2825 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002826 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002827 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002828 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002829 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002832 choice->nodetype = LYS_CHOICE;
2833 choice->prev = (struct lys_node *)choice;
2834 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002835
Michal Vaskoe0c59842015-09-24 13:52:20 +02002836 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2837 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 goto error;
2839 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002840
Radek Krejcia9544502015-08-14 08:24:29 +02002841 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2842
Michal Vasko3a0043f2015-08-12 12:11:30 +02002843 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002844 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002845 goto error;
2846 }
2847
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 /* process choice's specific children */
2849 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002850 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2851 /* garbage */
2852 lyxml_free_elem(module->ctx, sub);
2853 continue;
2854 }
2855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002857 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 goto error;
2859 }
2860 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002861 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 goto error;
2863 }
2864 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002865 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 goto error;
2867 }
2868 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002869 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 goto error;
2871 }
2872 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002873 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002874 goto error;
2875 }
2876 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002877 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 goto error;
2879 }
2880 } else if (!strcmp(sub->name, "default")) {
2881 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002882 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 goto error;
2884 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002885 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002886 } else if (!strcmp(sub->name, "mandatory")) {
2887 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002888 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002889 goto error;
2890 }
2891 /* just checking the flags in leaf is not sufficient, we would allow
2892 * multiple mandatory statements with the "false" value
2893 */
2894 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002896 GETVAL(value, sub, "value");
2897 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002898 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002899 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002900 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002901 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002902 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 goto error;
2904 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002905 } else if (!strcmp(sub->name, "when")) {
2906 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002907 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002908 goto error;
2909 }
2910
2911 choice->when = read_yin_when(module, sub);
2912 if (!choice->when) {
2913 goto error;
2914 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002915 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002916 goto error;
2917 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002918 } else if (!strcmp(sub->name, "if-feature")) {
2919 c_ftrs++;
2920
2921 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2922 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002924 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002927
Radek Krejci1d82ef62015-08-07 14:44:40 +02002928 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 lyxml_free_elem(ctx, sub);
2930 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002931
Radek Krejci3cf9e222015-06-18 11:37:50 +02002932 if (c_ftrs) {
2933 choice->features = calloc(c_ftrs, sizeof *choice->features);
2934 }
2935
Radek Krejci73adb602015-07-02 18:07:40 +02002936 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002937 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002938 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002939 goto error;
2940 }
2941 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value,
2942 LOGLINE(sub));
2943 lydict_remove(module->ctx, value);
2944 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002945 goto error;
2946 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002947 }
2948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002950 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002951 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2953 goto error;
2954 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 /* link default with the case */
2957 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002958 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002959 goto error;
2960 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002964
2965error:
2966
Radek Krejci1d82ef62015-08-07 14:44:40 +02002967 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002968
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002970}
2971
Michal Vasko0d343d12015-08-24 14:57:36 +02002972/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002973static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002974read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002975 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002976{
Radek Krejci76512572015-08-04 09:47:08 +02002977 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002978 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 struct lyxml_elem *sub, *next;
2980 const char *value;
2981 int r;
2982 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002983 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002986 anyxml->nodetype = LYS_ANYXML;
2987 anyxml->prev = (struct lys_node *)anyxml;
2988 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002989
Michal Vaskoe0c59842015-09-24 13:52:20 +02002990 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2991 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 goto error;
2993 }
Radek Krejci863c2852015-06-03 15:47:11 +02002994
Radek Krejcia9544502015-08-14 08:24:29 +02002995 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002996
2997 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002998 goto error;
2999 }
3000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003002 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3003 /* garbage */
3004 lyxml_free_elem(module->ctx, sub);
3005 continue;
3006 }
3007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 if (!strcmp(sub->name, "mandatory")) {
3009 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003010 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 goto error;
3012 }
3013 /* just checking the flags in leaf is not sufficient, we would allow
3014 * multiple mandatory statements with the "false" value
3015 */
3016 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 GETVAL(value, sub, "value");
3019 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003020 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003021 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003022 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003023 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003024 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 goto error;
3026 }
3027 /* else false is the default value, so we can ignore it */
3028 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003029 } else if (!strcmp(sub->name, "when")) {
3030 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003031 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003032 goto error;
3033 }
3034
3035 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003036 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003037 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003038 goto error;
3039 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003040 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003041 goto error;
3042 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003043 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 } else if (!strcmp(sub->name, "must")) {
3045 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003046 } else if (!strcmp(sub->name, "if-feature")) {
3047 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003049 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003050 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003052 }
3053 }
Radek Krejci863c2852015-06-03 15:47:11 +02003054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 /* middle part - process nodes with cardinality of 0..n */
3056 if (c_must) {
3057 anyxml->must = calloc(c_must, sizeof *anyxml->must);
3058 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003059 if (c_ftrs) {
3060 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
3061 }
Radek Krejci863c2852015-06-03 15:47:11 +02003062
Radek Krejci73adb602015-07-02 18:07:40 +02003063 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003065 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 if (r) {
3067 goto error;
3068 }
Michal Vasko0d204592015-10-07 09:50:04 +02003069 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003070 goto error;
3071 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003072 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003073 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003074 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003075 goto error;
3076 }
3077 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value,
3078 LOGLINE(sub));
3079 lydict_remove(module->ctx, value);
3080 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003081 goto error;
3082 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 }
Radek Krejci863c2852015-06-03 15:47:11 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003087
3088error:
3089
Radek Krejci1d82ef62015-08-07 14:44:40 +02003090 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02003091
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003093}
3094
Michal Vasko0d343d12015-08-24 14:57:36 +02003095/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003096static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003097read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003098 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003099{
Radek Krejci76512572015-08-04 09:47:08 +02003100 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003101 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 struct lyxml_elem *sub, *next;
3103 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003104 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003105 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003108 leaf->nodetype = LYS_LEAF;
3109 leaf->prev = (struct lys_node *)leaf;
3110 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003111
Michal Vaskoe0c59842015-09-24 13:52:20 +02003112 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3113 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 goto error;
3115 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003116
Radek Krejcia9544502015-08-14 08:24:29 +02003117 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003118
3119 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003120 goto error;
3121 }
3122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003124 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3125 /* garbage */
3126 lyxml_free_elem(module->ctx, sub);
3127 continue;
3128 }
3129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003131 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003132 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 goto error;
3134 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003135 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 goto error;
3137 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003138 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 } else if (!strcmp(sub->name, "default")) {
3140 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003141 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 goto error;
3143 }
3144 GETVAL(value, sub, "value");
3145 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003146 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003147 } else if (!strcmp(sub->name, "units")) {
3148 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003149 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003150 goto error;
3151 }
3152 GETVAL(value, sub, "name");
3153 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3154 } else if (!strcmp(sub->name, "mandatory")) {
3155 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003156 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 goto error;
3158 }
3159 /* just checking the flags in leaf is not sufficient, we would allow
3160 * multiple mandatory statements with the "false" value
3161 */
3162 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 GETVAL(value, sub, "value");
3165 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003166 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003167 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003168 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003169 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003170 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 goto error;
3172 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003173 } else if (!strcmp(sub->name, "when")) {
3174 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003175 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003176 goto error;
3177 }
3178
3179 leaf->when = read_yin_when(module, sub);
3180 if (!leaf->when) {
3181 goto error;
3182 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003183 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003184 goto error;
3185 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003188 c_must++;
3189 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003190 } else if (!strcmp(sub->name, "if-feature")) {
3191 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003195 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003199 lyxml_free_elem(module->ctx, sub);
3200 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003203 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003204 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 goto error;
3206 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003207 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003208 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003209 goto error;
3210 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003211 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 /* middle part - process nodes with cardinality of 0..n */
3214 if (c_must) {
3215 leaf->must = calloc(c_must, sizeof *leaf->must);
3216 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003217 if (c_ftrs) {
3218 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3219 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003220
Radek Krejci73adb602015-07-02 18:07:40 +02003221 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003223 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003224 if (r) {
3225 goto error;
3226 }
Michal Vasko0d204592015-10-07 09:50:04 +02003227 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003228 goto error;
3229 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003230 } else if (!strcmp(sub->name, "if-feature")) {
3231 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003232 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003233 goto error;
3234 }
3235 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value,
3236 LOGLINE(sub));
3237 lydict_remove(module->ctx, value);
3238 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003239 goto error;
3240 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003243
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003244 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003245
3246error:
3247
Radek Krejci1d82ef62015-08-07 14:44:40 +02003248 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003251}
3252
Michal Vasko0d343d12015-08-24 14:57:36 +02003253/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003254static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003255read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003256 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003257{
Radek Krejci76512572015-08-04 09:47:08 +02003258 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003259 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 struct lyxml_elem *sub, *next;
3261 const char *value;
3262 char *endptr;
3263 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003264 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003265 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003266 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003269 llist->nodetype = LYS_LEAFLIST;
3270 llist->prev = (struct lys_node *)llist;
3271 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003272
Michal Vaskoe0c59842015-09-24 13:52:20 +02003273 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3274 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 goto error;
3276 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003277
Radek Krejcia9544502015-08-14 08:24:29 +02003278 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003279
3280 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003281 goto error;
3282 }
3283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003285 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3286 /* garbage */
3287 lyxml_free_elem(module->ctx, sub);
3288 continue;
3289 }
3290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003291 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003292 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003293 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 goto error;
3295 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003296 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 goto error;
3298 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003299 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 } else if (!strcmp(sub->name, "units")) {
3301 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003302 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 goto error;
3304 }
3305 GETVAL(value, sub, "name");
3306 llist->units = lydict_insert(module->ctx, value, strlen(value));
3307 } else if (!strcmp(sub->name, "ordered-by")) {
3308 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003309 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 goto error;
3311 }
3312 /* just checking the flags in llist is not sufficient, we would
3313 * allow multiple ordered-by statements with the "system" value
3314 */
3315 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003316
Radek Krejci1574a8d2015-08-03 14:16:52 +02003317 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3319 * state data
3320 */
3321 lyxml_free_elem(module->ctx, sub);
3322 continue;
3323 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 GETVAL(value, sub, "value");
3326 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003327 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003329 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003330 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003331 } /* else system is the default value, so we can ignore it */
3332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003333 } else if (!strcmp(sub->name, "must")) {
3334 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003335 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003336 } else if (!strcmp(sub->name, "if-feature")) {
3337 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 } else if (!strcmp(sub->name, "min-elements")) {
3341 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003342 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
3345 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 GETVAL(value, sub, "value");
3348 while (isspace(value[0])) {
3349 value++;
3350 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 /* convert it to uint32_t */
3353 errno = 0;
3354 endptr = NULL;
3355 val = strtoul(value, &endptr, 10);
3356 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003357 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 goto error;
3359 }
3360 llist->min = (uint32_t) val;
3361 } else if (!strcmp(sub->name, "max-elements")) {
3362 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003363 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 goto error;
3365 }
3366 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 GETVAL(value, sub, "value");
3369 while (isspace(value[0])) {
3370 value++;
3371 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003372
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 /* convert it to uint32_t */
3374 errno = 0;
3375 endptr = NULL;
3376 val = strtoul(value, &endptr, 10);
3377 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003378 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 goto error;
3380 }
3381 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003382 } else if (!strcmp(sub->name, "when")) {
3383 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003384 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003385 goto error;
3386 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003387
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003388 llist->when = read_yin_when(module, sub);
3389 if (!llist->when) {
3390 goto error;
3391 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003392 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003393 goto error;
3394 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003396 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 lyxml_free_elem(module->ctx, sub);
3401 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003404 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003405 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 goto error;
3407 }
3408 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003409 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 goto error;
3411 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 /* middle part - process nodes with cardinality of 0..n */
3414 if (c_must) {
3415 llist->must = calloc(c_must, sizeof *llist->must);
3416 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003417 if (c_ftrs) {
3418 llist->features = calloc(c_ftrs, sizeof *llist->features);
3419 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003420
Radek Krejci73adb602015-07-02 18:07:40 +02003421 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003423 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 if (r) {
3425 goto error;
3426 }
Michal Vasko0d204592015-10-07 09:50:04 +02003427 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003428 goto error;
3429 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003430 } else if (!strcmp(sub->name, "if-feature")) {
3431 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003432 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003433 goto error;
3434 }
3435 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
3436 LOGLINE(sub));
3437 lydict_remove(module->ctx, value);
3438 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003439 goto error;
3440 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003442 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003445
3446error:
3447
Radek Krejci1d82ef62015-08-07 14:44:40 +02003448 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003451}
3452
Michal Vasko0d343d12015-08-24 14:57:36 +02003453/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003454static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003455read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3456 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003457{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003458 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003459 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003460 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003461 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003462 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003464 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 char *auxs;
3466 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 /* init */
3469 memset(&root, 0, sizeof root);
3470 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003473 list->nodetype = LYS_LIST;
3474 list->prev = (struct lys_node *)list;
3475 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003476
Michal Vaskoe0c59842015-09-24 13:52:20 +02003477 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3478 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003479 goto error;
3480 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003481
Radek Krejcia9544502015-08-14 08:24:29 +02003482 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 /* process list's specific children */
3485 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003486 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3487 /* garbage */
3488 lyxml_free_elem(module->ctx, sub);
3489 continue;
3490 }
3491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 /* data statements */
3493 if (!strcmp(sub->name, "container") ||
3494 !strcmp(sub->name, "leaf-list") ||
3495 !strcmp(sub->name, "leaf") ||
3496 !strcmp(sub->name, "list") ||
3497 !strcmp(sub->name, "choice") ||
3498 !strcmp(sub->name, "uses") ||
3499 !strcmp(sub->name, "grouping") ||
3500 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003501 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003502 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 /* array counters */
3505 } else if (!strcmp(sub->name, "key")) {
3506 /* check cardinality 0..1 */
3507 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003508 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 goto error;
3510 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 /* count the number of keys */
3513 GETVAL(value, sub, "value");
3514 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003515 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003516 while ((value = strpbrk(value, " \t\n"))) {
3517 list->keys_size++;
3518 while (isspace(*value)) {
3519 value++;
3520 }
3521 }
3522 list->keys_size++;
3523 list->keys = calloc(list->keys_size, sizeof *list->keys);
3524 } else if (!strcmp(sub->name, "unique")) {
3525 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003526 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003527 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 } else if (!strcmp(sub->name, "typedef")) {
3529 c_tpdf++;
3530 } else if (!strcmp(sub->name, "must")) {
3531 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003532 } else if (!strcmp(sub->name, "if-feature")) {
3533 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 /* optional stetments */
3536 } else if (!strcmp(sub->name, "ordered-by")) {
3537 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003538 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 goto error;
3540 }
3541 /* just checking the flags in llist is not sufficient, we would
3542 * allow multiple ordered-by statements with the "system" value
3543 */
3544 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003545
Radek Krejci1574a8d2015-08-03 14:16:52 +02003546 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3548 * state data
3549 */
3550 lyxml_free_elem(module->ctx, sub);
3551 continue;
3552 }
Radek Krejci345ad742015-06-03 11:04:18 +02003553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 GETVAL(value, sub, "value");
3555 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003556 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003558 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 goto error;
3560 }
3561 /* else system is the default value, so we can ignore it */
3562 lyxml_free_elem(module->ctx, sub);
3563 } else if (!strcmp(sub->name, "min-elements")) {
3564 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003565 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003566 goto error;
3567 }
3568 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003569
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003570 GETVAL(value, sub, "value");
3571 while (isspace(value[0])) {
3572 value++;
3573 }
Radek Krejci345ad742015-06-03 11:04:18 +02003574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003575 /* convert it to uint32_t */
3576 errno = 0;
3577 auxs = NULL;
3578 val = strtoul(value, &auxs, 10);
3579 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003580 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 goto error;
3582 }
3583 list->min = (uint32_t) val;
3584 lyxml_free_elem(module->ctx, sub);
3585 } else if (!strcmp(sub->name, "max-elements")) {
3586 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003587 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 goto error;
3589 }
3590 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 GETVAL(value, sub, "value");
3593 while (isspace(value[0])) {
3594 value++;
3595 }
Radek Krejci345ad742015-06-03 11:04:18 +02003596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003597 /* convert it to uint32_t */
3598 errno = 0;
3599 auxs = NULL;
3600 val = strtoul(value, &auxs, 10);
3601 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003602 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 goto error;
3604 }
3605 list->max = (uint32_t) val;
3606 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003607 } else if (!strcmp(sub->name, "when")) {
3608 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003609 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003610 goto error;
3611 }
3612
3613 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003614 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003615 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003616 goto error;
3617 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003618 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003619 goto error;
3620 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003621 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003622 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003623 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003624 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 }
3626 }
Radek Krejci345ad742015-06-03 11:04:18 +02003627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003629 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003630 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 goto error;
3632 }
3633 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003634 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 goto error;
3636 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003638 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3639 if (c_tpdf) {
3640 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3641 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003642 if (c_must) {
3643 list->must = calloc(c_must, sizeof *list->must);
3644 }
3645 if (c_ftrs) {
3646 list->features = calloc(c_ftrs, sizeof *list->features);
3647 }
Radek Krejci73adb602015-07-02 18:07:40 +02003648 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003650 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003651
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003652 if (r) {
3653 goto error;
3654 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003655 } else if (!strcmp(sub->name, "if-feature")) {
3656 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003657 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003658 goto error;
3659 }
3660 r = unres_schema_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value,
3661 LOGLINE(sub));
3662 lydict_remove(module->ctx, value);
3663 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003664 goto error;
3665 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003666 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003667 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003668 if (r) {
3669 goto error;
3670 }
Michal Vasko0d204592015-10-07 09:50:04 +02003671 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003672 goto error;
3673 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003674 }
3675 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003676
Radek Krejci10c760e2015-08-14 14:45:43 +02003677 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003678 goto error;
3679 }
3680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 /* last part - process data nodes */
3682 LY_TREE_FOR_SAFE(root.child, next, sub) {
3683 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003684 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003686 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003688 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003690 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003691 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003692 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003694 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003696 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003698 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003699 } else {
3700 LOGINT;
3701 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003703 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 goto error;
3705 }
Radek Krejci73adb602015-07-02 18:07:40 +02003706
3707 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 if (!key_str) {
3711 /* config false list without a key */
3712 return retval;
3713 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003714 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003715 goto error;
3716 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003717
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 /* process unique statements */
3719 if (c_uniq) {
3720 list->unique = calloc(c_uniq, sizeof *list->unique);
3721 }
3722 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003723 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003724 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003725 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003726 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003727 LOGLINE(sub)) == -1) {
3728 goto error;
3729 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 lyxml_free_elem(module->ctx, sub);
3732 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003735
3736error:
3737
Radek Krejci1d82ef62015-08-07 14:44:40 +02003738 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 while (root.child) {
3740 lyxml_free_elem(module->ctx, root.child);
3741 }
3742 while (uniq.child) {
3743 lyxml_free_elem(module->ctx, uniq.child);
3744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003747}
3748
Michal Vasko0d343d12015-08-24 14:57:36 +02003749/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003750static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003751read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3752 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003753{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003755 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003756 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003757 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 const char *value;
3759 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003760 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 /* init */
3763 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003764
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003766 cont->nodetype = LYS_CONTAINER;
3767 cont->prev = (struct lys_node *)cont;
3768 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Michal Vaskoe0c59842015-09-24 13:52:20 +02003770 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3771 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003774
Radek Krejcia9544502015-08-14 08:24:29 +02003775 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 /* process container's specific children */
3778 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003779 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003780 /* garbage */
3781 lyxml_free_elem(module->ctx, sub);
3782 continue;
3783 }
3784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 if (!strcmp(sub->name, "presence")) {
3786 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003787 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003788 goto error;
3789 }
3790 GETVAL(value, sub, "value");
3791 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003794 } else if (!strcmp(sub->name, "when")) {
3795 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003796 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003797 goto error;
3798 }
3799
3800 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003801 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003802 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003803 goto error;
3804 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003805 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003806 goto error;
3807 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003808 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 /* data statements */
3811 } else if (!strcmp(sub->name, "container") ||
3812 !strcmp(sub->name, "leaf-list") ||
3813 !strcmp(sub->name, "leaf") ||
3814 !strcmp(sub->name, "list") ||
3815 !strcmp(sub->name, "choice") ||
3816 !strcmp(sub->name, "uses") ||
3817 !strcmp(sub->name, "grouping") ||
3818 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003819 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003820 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 /* array counters */
3823 } else if (!strcmp(sub->name, "typedef")) {
3824 c_tpdf++;
3825 } else if (!strcmp(sub->name, "must")) {
3826 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003827 } else if (!strcmp(sub->name, "if-feature")) {
3828 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003830 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003831 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 }
3833 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3836 if (c_tpdf) {
3837 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3838 }
3839 if (c_must) {
3840 cont->must = calloc(c_must, sizeof *cont->must);
3841 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003842 if (c_ftrs) {
3843 cont->features = calloc(c_ftrs, sizeof *cont->features);
3844 }
Radek Krejci800af702015-06-02 13:46:01 +02003845
Radek Krejci73adb602015-07-02 18:07:40 +02003846 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003848 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 if (r) {
3850 goto error;
3851 }
3852 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003853 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 if (r) {
3855 goto error;
3856 }
Michal Vasko0d204592015-10-07 09:50:04 +02003857 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003858 goto error;
3859 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003860 } else if (!strcmp(sub->name, "if-feature")) {
3861 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003862 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003863 goto error;
3864 }
3865 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
3866 LOGLINE(sub));
3867 lydict_remove(module->ctx, value);
3868 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003869 goto error;
3870 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003871 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003872 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003873
Radek Krejci10c760e2015-08-14 14:45:43 +02003874 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003875 goto error;
3876 }
3877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003878 /* last part - process data nodes */
3879 LY_TREE_FOR_SAFE(root.child, next, sub) {
3880 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003881 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003882 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003883 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003884 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003885 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003887 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003888 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003889 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003890 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003891 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003892 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003893 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003894 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003895 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003897 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003898 goto error;
3899 }
Radek Krejci73adb602015-07-02 18:07:40 +02003900
3901 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003902 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003904 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003905
3906error:
3907
Radek Krejci1d82ef62015-08-07 14:44:40 +02003908 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003909 while (root.child) {
3910 lyxml_free_elem(module->ctx, root.child);
3911 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003914}
3915
Michal Vasko0d343d12015-08-24 14:57:36 +02003916/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003917static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003918read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003919 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003920{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003922 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003923 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003924 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 int r;
3926 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003928 /* init */
3929 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003931 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003932 grp->nodetype = LYS_GROUPING;
3933 grp->prev = (struct lys_node *)grp;
3934 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003935
Michal Vasko71e1aa82015-08-12 12:17:51 +02003936 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003937 goto error;
3938 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003939
Radek Krejcia9544502015-08-14 08:24:29 +02003940 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3941
Radek Krejci1d82ef62015-08-07 14:44:40 +02003942 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003943 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3944 /* garbage */
3945 lyxml_free_elem(module->ctx, sub);
3946 continue;
3947 }
3948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003949 /* data statements */
3950 if (!strcmp(sub->name, "container") ||
3951 !strcmp(sub->name, "leaf-list") ||
3952 !strcmp(sub->name, "leaf") ||
3953 !strcmp(sub->name, "list") ||
3954 !strcmp(sub->name, "choice") ||
3955 !strcmp(sub->name, "uses") ||
3956 !strcmp(sub->name, "grouping") ||
3957 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003958 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003959 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003961 /* array counters */
3962 } else if (!strcmp(sub->name, "typedef")) {
3963 c_tpdf++;
3964 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003965 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 goto error;
3967 }
3968 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003970 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3971 if (c_tpdf) {
3972 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3973 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003974 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003975 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003976
Radek Krejci73adb602015-07-02 18:07:40 +02003977 if (r) {
3978 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003979 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003981
Radek Krejci10c760e2015-08-14 14:45:43 +02003982 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003983 goto error;
3984 }
3985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003986 /* last part - process data nodes */
3987 LY_TREE_FOR_SAFE(root.child, next, sub) {
3988 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003989 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003990 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003991 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003992 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003993 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003994 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003995 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003997 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003998 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003999 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004000 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004001 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004002 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004003 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004005 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004006 goto error;
4007 }
Radek Krejci73adb602015-07-02 18:07:40 +02004008
4009 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004010 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004011
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004012 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004013
4014error:
4015
Radek Krejci1d82ef62015-08-07 14:44:40 +02004016 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004017 while (root.child) {
4018 lyxml_free_elem(module->ctx, root.child);
4019 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004021 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004022}
4023
Michal Vasko0d343d12015-08-24 14:57:36 +02004024/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004025static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004026read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4027 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004028{
Radek Krejcie0674f82015-06-15 13:58:51 +02004029 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004030 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004031 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004032 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004033 int r;
4034 int c_tpdf = 0;
4035
Radek Krejcie0674f82015-06-15 13:58:51 +02004036 /* init */
4037 memset(&root, 0, sizeof root);
4038
Michal Vasko38d01f72015-06-15 09:41:06 +02004039 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02004040 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004041
4042 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004043 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004044 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004045 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004046 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004047 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004048 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004049 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004050 }
4051
Radek Krejci76512572015-08-04 09:47:08 +02004052 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004053
Radek Krejci6a113852015-07-03 16:04:20 +02004054 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004055 goto error;
4056 }
4057
Radek Krejcia9544502015-08-14 08:24:29 +02004058 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4059
Michal Vasko38d01f72015-06-15 09:41:06 +02004060 /* data statements */
4061 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004062 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4063 /* garbage */
4064 lyxml_free_elem(module->ctx, sub);
4065 continue;
4066 }
4067
Michal Vasko38d01f72015-06-15 09:41:06 +02004068 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004069 !strcmp(sub->name, "leaf-list") ||
4070 !strcmp(sub->name, "leaf") ||
4071 !strcmp(sub->name, "list") ||
4072 !strcmp(sub->name, "choice") ||
4073 !strcmp(sub->name, "uses") ||
4074 !strcmp(sub->name, "grouping") ||
4075 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004076 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004077 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004079 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004080 } else if (!strcmp(sub->name, "typedef")) {
4081 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004082
Michal Vasko38d01f72015-06-15 09:41:06 +02004083 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004084 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004085 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004086 }
4087 }
4088
4089 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4090 if (c_tpdf) {
4091 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
4092 }
4093
Radek Krejci73adb602015-07-02 18:07:40 +02004094 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004095 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004096
Radek Krejci73adb602015-07-02 18:07:40 +02004097 if (r) {
4098 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004099 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004100 }
4101
Radek Krejci10c760e2015-08-14 14:45:43 +02004102 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004103 goto error;
4104 }
4105
Michal Vasko38d01f72015-06-15 09:41:06 +02004106 /* last part - process data nodes */
4107 LY_TREE_FOR_SAFE(root.child, next, sub) {
4108 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004109 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004110 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004111 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004112 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004113 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004114 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004115 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004116 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004117 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004118 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004119 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004120 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004121 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004122 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004123 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004124 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004125 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 goto error;
4127 }
Radek Krejci73adb602015-07-02 18:07:40 +02004128
4129 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004130 }
4131
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 return retval;
4133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004134error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004135
Radek Krejci1d82ef62015-08-07 14:44:40 +02004136 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004137 while (root.child) {
4138 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004139 }
4140
4141 return NULL;
4142}
4143
Michal Vasko0d343d12015-08-24 14:57:36 +02004144/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004145static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004146read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4147 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004148{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004149 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004150 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004151 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004152 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004153 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004154 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004155 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004156
Michal Vaskoc6551b32015-06-16 10:51:43 +02004157 memset(&root, 0, sizeof root);
4158
Michal Vasko0ea41032015-06-16 08:53:55 +02004159 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004160 notif->nodetype = LYS_NOTIF;
4161 notif->prev = (struct lys_node *)notif;
4162 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004163
Radek Krejci6a113852015-07-03 16:04:20 +02004164 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004165 goto error;
4166 }
4167
Radek Krejcia9544502015-08-14 08:24:29 +02004168 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4169
Michal Vasko0ea41032015-06-16 08:53:55 +02004170 /* process rpc's specific children */
4171 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004172 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4173 /* garbage */
4174 lyxml_free_elem(module->ctx, sub);
4175 continue;
4176 }
4177
Michal Vasko0ea41032015-06-16 08:53:55 +02004178 /* data statements */
4179 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004180 !strcmp(sub->name, "leaf-list") ||
4181 !strcmp(sub->name, "leaf") ||
4182 !strcmp(sub->name, "list") ||
4183 !strcmp(sub->name, "choice") ||
4184 !strcmp(sub->name, "uses") ||
4185 !strcmp(sub->name, "grouping") ||
4186 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004187 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004188 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004190 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004191 } else if (!strcmp(sub->name, "typedef")) {
4192 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004193 } else if (!strcmp(sub->name, "if-feature")) {
4194 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004195 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004196 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004197 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004198 }
4199 }
4200
4201 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4202 if (c_tpdf) {
4203 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4204 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004205 if (c_ftrs) {
4206 notif->features = calloc(c_ftrs, sizeof *notif->features);
4207 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004208
Radek Krejci73adb602015-07-02 18:07:40 +02004209 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004210 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004211 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004212
4213 if (r) {
4214 goto error;
4215 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004216 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004217 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004218 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004219 goto error;
4220 }
4221 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
4222 LOGLINE(sub));
4223 lydict_remove(module->ctx, value);
4224 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004225 goto error;
4226 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004227 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004228 }
4229
Radek Krejci10c760e2015-08-14 14:45:43 +02004230 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004231 goto error;
4232 }
4233
Michal Vasko0ea41032015-06-16 08:53:55 +02004234 /* last part - process data nodes */
4235 LY_TREE_FOR_SAFE(root.child, next, sub) {
4236 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004237 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004238 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004239 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004240 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004241 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004243 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004244 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004245 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004246 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004247 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004248 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004249 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004250 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004251 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004252 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004253 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004254 goto error;
4255 }
Radek Krejci73adb602015-07-02 18:07:40 +02004256
4257 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004258 }
4259
Michal Vasko0ea41032015-06-16 08:53:55 +02004260 return retval;
4261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004262error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004263
Radek Krejci1d82ef62015-08-07 14:44:40 +02004264 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004265 while (root.child) {
4266 lyxml_free_elem(module->ctx, root.child);
4267 }
4268
4269 return NULL;
4270}
4271
Michal Vasko0d343d12015-08-24 14:57:36 +02004272/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004273static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004274read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4275 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004276{
Radek Krejcie0674f82015-06-15 13:58:51 +02004277 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004278 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004279 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004280 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004281 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004282 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004283 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004284
Radek Krejcie0674f82015-06-15 13:58:51 +02004285 /* init */
4286 memset(&root, 0, sizeof root);
4287
Michal Vasko38d01f72015-06-15 09:41:06 +02004288 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004289 rpc->nodetype = LYS_RPC;
4290 rpc->prev = (struct lys_node *)rpc;
4291 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004292
Radek Krejci6a113852015-07-03 16:04:20 +02004293 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004294 goto error;
4295 }
4296
Radek Krejcia9544502015-08-14 08:24:29 +02004297 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4298
Michal Vasko38d01f72015-06-15 09:41:06 +02004299 /* process rpc's specific children */
4300 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004301 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4302 /* garbage */
4303 lyxml_free_elem(module->ctx, sub);
4304 continue;
4305 }
4306
Michal Vasko38d01f72015-06-15 09:41:06 +02004307 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004309 && (rpc->child->nodetype == LYS_INPUT
4310 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004311 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004312 goto error;
4313 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004314 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004315 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004316 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004318 && (rpc->child->nodetype == LYS_INPUT
4319 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004320 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004321 goto error;
4322 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004323 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004324 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004327 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004328 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004329 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004331 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004332 } else if (!strcmp(sub->name, "typedef")) {
4333 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004334 } else if (!strcmp(sub->name, "if-feature")) {
4335 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004336 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004337 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004338 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004339 }
4340 }
4341
4342 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4343 if (c_tpdf) {
4344 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4345 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004346 if (c_ftrs) {
4347 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4348 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004349
Radek Krejci73adb602015-07-02 18:07:40 +02004350 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004351 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004352 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004353
4354 if (r) {
4355 goto error;
4356 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004357 } else if (!strcmp(sub->name, "if-feature")) {
4358 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004359 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004360 goto error;
4361 }
4362 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
4363 LOGLINE(sub));
4364 lydict_remove(module->ctx, value);
4365 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004366 goto error;
4367 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004368 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004369 }
4370
Radek Krejci10c760e2015-08-14 14:45:43 +02004371 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004372 goto error;
4373 }
4374
Michal Vasko38d01f72015-06-15 09:41:06 +02004375 /* last part - process data nodes */
4376 LY_TREE_FOR_SAFE(root.child, next, sub) {
4377 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004378 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004379 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004380 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004381 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004382 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004383 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004384 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004385 goto error;
4386 }
Radek Krejci73adb602015-07-02 18:07:40 +02004387
4388 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004389 }
4390
Michal Vasko38d01f72015-06-15 09:41:06 +02004391 return retval;
4392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004394
Radek Krejci1d82ef62015-08-07 14:44:40 +02004395 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004396 while (root.child) {
4397 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004398 }
4399
4400 return NULL;
4401}
4402
Michal Vasko0d343d12015-08-24 14:57:36 +02004403/* logs directly
4404 *
Radek Krejci74705112015-06-05 10:25:44 +02004405 * resolve - referenced grouping should be bounded to the namespace (resolved)
4406 * only when uses does not appear in grouping. In a case of grouping's uses,
4407 * we just get information but we do not apply augment or refine to it.
4408 */
Radek Krejci76512572015-08-04 09:47:08 +02004409static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004410read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004411 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004412{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004414 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004415 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004417 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004421 uses->nodetype = LYS_USES;
4422 uses->prev = (struct lys_node *)uses;
4423 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004424
Radek Krejcia9544502015-08-14 08:24:29 +02004425 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004427
Michal Vaskoe0c59842015-09-24 13:52:20 +02004428 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4429 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004430 goto error;
4431 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004432
Radek Krejcia9544502015-08-14 08:24:29 +02004433 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004436 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004437 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4438 /* garbage */
4439 lyxml_free_elem(module->ctx, sub);
4440 continue;
4441 }
4442
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004443 if (!strcmp(sub->name, "refine")) {
4444 c_ref++;
4445 } else if (!strcmp(sub->name, "augment")) {
4446 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004447 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004448 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004449 } else if (!strcmp(sub->name, "when")) {
4450 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004451 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004452 goto error;
4453 }
4454
4455 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004456 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004457 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004458 goto error;
4459 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004460 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004461 goto error;
4462 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004463 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004465 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 }
4468 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 /* process properties with cardinality 0..n */
4471 if (c_ref) {
4472 uses->refine = calloc(c_ref, sizeof *uses->refine);
4473 }
4474 if (c_aug) {
4475 uses->augment = calloc(c_aug, sizeof *uses->augment);
4476 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004477 if (c_ftrs) {
4478 uses->features = calloc(c_ftrs, sizeof *uses->features);
4479 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004480
Radek Krejci10c760e2015-08-14 14:45:43 +02004481 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004482 goto error;
4483 }
4484
Radek Krejcia9544502015-08-14 08:24:29 +02004485 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 if (!strcmp(sub->name, "refine")) {
Michal Vasko0d204592015-10-07 09:50:04 +02004487 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004488 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004489 goto error;
4490 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004491 } else if (!strcmp(sub->name, "augment")) {
4492 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4493 if (r) {
4494 goto error;
4495 }
4496 } else if (!strcmp(sub->name, "if-feature")) {
4497 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004498 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004499 goto error;
4500 }
4501 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
4502 LOGLINE(sub));
4503 lydict_remove(module->ctx, value);
4504 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004505 goto error;
4506 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 }
4508 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004509
Michal Vasko0bd29d12015-08-19 11:45:49 +02004510 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004511 goto error;
4512 }
Radek Krejci74705112015-06-05 10:25:44 +02004513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 if (resolve) {
4515 /* inherit config flag */
4516 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004517 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 } else {
4519 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004520 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 }
4522 }
Radek Krejcib388c152015-06-04 17:03:03 +02004523
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004525
4526error:
4527
Radek Krejci1d82ef62015-08-07 14:44:40 +02004528 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004529
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004531}
4532
Michal Vasko0d343d12015-08-24 14:57:36 +02004533/* logs directly
4534 *
4535 * common code for yin_read_module() and yin_read_submodule()
4536 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004538read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004539{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004541 struct lys_submodule *submodule = (struct lys_submodule *)module;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004542 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004543 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004545 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004547 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004548 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 +02004549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 /* init */
4551 memset(&root, 0, sizeof root);
4552 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004553 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004555 /*
4556 * in the first run, we process elements with cardinality of 1 or 0..1 and
4557 * count elements with cardinality 0..n. Data elements (choices, containers,
4558 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4559 * need have all top-level and groupings already prepared at that time. In
4560 * the middle loop, we process other elements with carinality of 0..n since
4561 * we need to allocate arrays to store them.
4562 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004563 LY_TREE_FOR_SAFE(yin->child, next, child) {
4564 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004565 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004566 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 continue;
4568 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004569
Radek Krejci1d82ef62015-08-07 14:44:40 +02004570 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004572 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 goto error;
4574 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004575 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004577 lyxml_free_elem(ctx, child);
4578 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004580 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 goto error;
4582 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004583 GETVAL(value, child, "value");
4584 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 goto error;
4586 }
4587 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004588 lyxml_free_elem(ctx, child);
4589 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004590 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004591 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 goto error;
4593 }
4594 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004595 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004597 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004598 }
4599 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004600 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 goto error;
4602 }
Radek Krejcif3886932015-06-04 17:36:06 +02004603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004605 if (!child->child) {
4606 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 } else if (strcmp(child->child->name, "prefix")) {
4609 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 } else if (child->child->next) {
4612 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 goto error;
4614 }
4615 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004616 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004617 /* check here differs from a generic prefix check, since this prefix
4618 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004619 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004620 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004621 goto error;
4622 }
4623 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004626 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004627
4628 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004631 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004635 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004637 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004640 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004641 /* keep augments separated, processed last */
Michal Vaskof3930de2015-10-22 12:03:59 +02004642 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004643 lyxml_add_child(module->ctx, &augs, child);
4644
Radek Krejci1d82ef62015-08-07 14:44:40 +02004645 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004646 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004647 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004648 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 } else if (!strcmp(child->name, "container") ||
4652 !strcmp(child->name, "leaf-list") ||
4653 !strcmp(child->name, "leaf") ||
4654 !strcmp(child->name, "list") ||
4655 !strcmp(child->name, "choice") ||
4656 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004657 !strcmp(child->name, "anyxml") ||
4658 !strcmp(child->name, "rpc") ||
4659 !strcmp(child->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004660 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004661 lyxml_add_child(module->ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004662
Radek Krejci1d82ef62015-08-07 14:44:40 +02004663 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 /* keep groupings separated and process them before other data statements */
Michal Vaskof3930de2015-10-22 12:03:59 +02004665 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004666 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004669 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004670 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 goto error;
4673 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 module->dsc = read_yin_subnode(ctx, child, "text");
4675 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 if (!module->dsc) {
4677 goto error;
4678 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004679 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004680 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004681 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 goto error;
4683 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004684 module->ref = read_yin_subnode(ctx, child, "text");
4685 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004686 if (!module->ref) {
4687 goto error;
4688 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004689 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004691 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 goto error;
4693 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004694 module->org = read_yin_subnode(ctx, child, "text");
4695 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 if (!module->org) {
4697 goto error;
4698 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004699 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 goto error;
4703 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004704 module->contact = read_yin_subnode(ctx, child, "text");
4705 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 if (!module->contact) {
4707 goto error;
4708 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004709 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 /* TODO: support YANG 1.1 ? */
4711 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 goto error;
4714 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004715 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004717 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
4719 }
4720 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004721 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004722
Radek Krejci1d82ef62015-08-07 14:44:40 +02004723 } else if (!strcmp(child->name, "extension")) {
4724 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004725
Radek Krejci3d468122015-10-02 13:36:12 +02004726 /* we have the following supported (hardcoded) extensions: */
4727 /* ietf-netconf's get-filter-element-attributes */
4728 if (!strcmp(module->ns, LY_NSNC) &&
4729 !strcmp(value, "get-filter-element-attributes")) {
4730 LOGDBG("NETCONF filter extension found");
4731 /* NACM's default-deny-write and default-deny-all */
4732 } else if (!strcmp(module->ns, LY_NSNACM) &&
4733 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4734 LOGDBG("NACM extension found");
4735 /* other extensions are not supported, so inform about such an extension */
4736 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004737 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004738 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004741 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004743 }
4744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 if (!submodule) {
4747 /* check for mandatory statements */
4748 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004749 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 goto error;
4751 }
4752 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004753 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 goto error;
4755 }
4756 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 /* allocate arrays for elements with cardinality of 0..n */
4759 if (c_imp) {
4760 module->imp = calloc(c_imp, sizeof *module->imp);
4761 }
4762 if (c_rev) {
4763 module->rev = calloc(c_rev, sizeof *module->rev);
4764 }
4765 if (c_tpdf) {
4766 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4767 }
4768 if (c_ident) {
4769 module->ident = calloc(c_ident, sizeof *module->ident);
4770 }
4771 if (c_inc) {
4772 module->inc = calloc(c_inc, sizeof *module->inc);
4773 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004774 if (c_aug) {
4775 module->augment = calloc(c_aug, sizeof *module->augment);
4776 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004777 if (c_ftrs) {
4778 module->features = calloc(c_ftrs, sizeof *module->features);
4779 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004780 if (c_dev) {
4781 module->deviation = calloc(c_dev, sizeof *module->deviation);
4782 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004783
Michal Vasko2f7925f2015-10-21 15:06:56 +02004784 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4785 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004786 if (!strcmp(child->name, "import")) {
4787 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004788 module->imp_size++;
4789 if (r) {
4790 goto error;
4791 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004793 /* check duplicities in imported modules */
4794 for (i = 0; i < module->imp_size - 1; i++) {
4795 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004796 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 goto error;
4798 }
4799 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004800
Radek Krejci1d82ef62015-08-07 14:44:40 +02004801 } else if (!strcmp(child->name, "include")) {
4802 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004803 module->inc_size++;
4804 if (r) {
4805 goto error;
4806 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004807
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004808 /* check duplications in include submodules */
4809 for (i = 0; i < module->inc_size - 1; i++) {
4810 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004811 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 module->inc[i].submodule->name);
4813 goto error;
4814 }
4815 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004816
Radek Krejci1d82ef62015-08-07 14:44:40 +02004817 } else if (!strcmp(child->name, "revision")) {
4818 GETVAL(value, child, "date");
4819 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004820 goto error;
4821 }
4822 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4823 /* check uniqueness of the revision date - not required by RFC */
4824 for (i = 0; i < module->rev_size; i++) {
4825 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004826 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004827 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004828 }
4829 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004830
Radek Krejci1d82ef62015-08-07 14:44:40 +02004831 LY_TREE_FOR(child->child, child2) {
4832 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004834 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 goto error;
4836 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004837 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 if (!module->rev[module->rev_size].dsc) {
4839 goto error;
4840 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004841 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004843 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 goto error;
4845 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004846 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 if (!module->rev[module->rev_size].ref) {
4848 goto error;
4849 }
4850 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004851 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 goto error;
4853 }
4854 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004856 /* keep the latest revision at position 0 */
4857 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4858 /* switch their position */
4859 value = strdup(module->rev[0].date);
4860 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4861 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4862 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4865 value = module->rev[0].dsc;
4866 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4867 module->rev[module->rev_size].dsc = value;
4868 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4871 value = module->rev[0].ref;
4872 module->rev[0].ref = module->rev[module->rev_size].ref;
4873 module->rev[module->rev_size].ref = value;
4874 }
4875 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 module->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004878
Radek Krejci1d82ef62015-08-07 14:44:40 +02004879 } else if (!strcmp(child->name, "typedef")) {
4880 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004882
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 if (r) {
4884 goto error;
4885 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004886
Radek Krejci1d82ef62015-08-07 14:44:40 +02004887 } else if (!strcmp(child->name, "identity")) {
4888 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 if (r) {
4892 goto error;
4893 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004894
Radek Krejci1d82ef62015-08-07 14:44:40 +02004895 } else if (!strcmp(child->name, "feature")) {
4896 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004897 module->features_size++;
4898
4899 if (r) {
4900 goto error;
4901 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004902
Radek Krejci1d82ef62015-08-07 14:44:40 +02004903 } else if (!strcmp(child->name, "deviation")) {
4904 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004905 module->deviation_size++;
4906
4907 if (r) {
4908 goto error;
4909 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004913
Radek Krejcif5be10f2015-06-16 13:29:36 +02004914 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 * refer to them
4916 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004917 LY_TREE_FOR_SAFE(grps.child, next, child) {
4918 node = read_yin_grouping(module, NULL, child, 0, unres);
4919 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 goto error;
4921 }
Radek Krejci74705112015-06-05 10:25:44 +02004922
Radek Krejci1d82ef62015-08-07 14:44:40 +02004923 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 }
Radek Krejci74705112015-06-05 10:25:44 +02004925
Radek Krejcif5be10f2015-06-16 13:29:36 +02004926 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004927 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004928
Radek Krejci1d82ef62015-08-07 14:44:40 +02004929 if (!strcmp(child->name, "container")) {
4930 node = read_yin_container(module, NULL, child, 1, unres);
4931 } else if (!strcmp(child->name, "leaf-list")) {
4932 node = read_yin_leaflist(module, NULL, child, 1, unres);
4933 } else if (!strcmp(child->name, "leaf")) {
4934 node = read_yin_leaf(module, NULL, child, 1, unres);
4935 } else if (!strcmp(child->name, "list")) {
4936 node = read_yin_list(module, NULL, child, 1, unres);
4937 } else if (!strcmp(child->name, "choice")) {
4938 node = read_yin_choice(module, NULL, child, 1, unres);
4939 } else if (!strcmp(child->name, "uses")) {
4940 node = read_yin_uses(module, NULL, child, 1, unres);
4941 } else if (!strcmp(child->name, "anyxml")) {
4942 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004943 } else if (!strcmp(child->name, "rpc")) {
4944 node = read_yin_rpc(module, NULL, child, 0, unres);
4945 } else if (!strcmp(child->name, "notification")) {
4946 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004948 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004949 goto error;
4950 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004951
Radek Krejci1d82ef62015-08-07 14:44:40 +02004952 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004954
Michal Vasko2f7925f2015-10-21 15:06:56 +02004955 /* ... and finally augments (last, so we can augment our data, for instance) */
4956 LY_TREE_FOR_SAFE(augs.child, next, child) {
4957 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
4958 module->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004959
Michal Vasko2f7925f2015-10-21 15:06:56 +02004960 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004961 goto error;
4962 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004963 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004964 }
4965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004966 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004967
4968error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004969 /* cleanup */
4970 while (root.child) {
4971 lyxml_free_elem(module->ctx, root.child);
4972 }
4973 while (grps.child) {
4974 lyxml_free_elem(module->ctx, grps.child);
4975 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004976 while (augs.child) {
4977 lyxml_free_elem(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004978 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004979
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004980 free(unres->item);
4981 unres->item = NULL;
4982 free(unres->type);
4983 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004984 free(unres->str_snode);
4985 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004986#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004987 free(unres->line);
4988 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004989#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004990 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004992 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004993}
4994
Michal Vasko0d343d12015-08-24 14:57:36 +02004995/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004996struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004997yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004998{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004999 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005000 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005001 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005002
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005003 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005004
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005005 yin = lyxml_read(module->ctx, data, 0);
5006 if (!yin) {
5007 return NULL;
5008 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005009
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005010 /* check root element */
5011 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005012 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 goto error;
5014 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 GETVAL(value, yin, "name");
5017 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
5018 goto error;
5019 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005021 submodule = calloc(1, sizeof *submodule);
5022 if (!submodule) {
5023 LOGMEM;
5024 goto error;
5025 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005027 submodule->ctx = module->ctx;
5028 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5029 submodule->type = 1;
5030 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005031 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005032
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005033 LOGVRB("Reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02005034 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005035 goto error;
5036 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005038 /* cleanup */
5039 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005040
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005041 LOGVRB("Submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005042
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005043 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005044
5045error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005046 /* cleanup */
5047 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005048 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005050 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005051}
5052
Michal Vasko0d343d12015-08-24 14:57:36 +02005053/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005054struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02005055yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005056{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005057 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005058 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005059 const char *value;
5060 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005062 yin = lyxml_read(ctx, data, 0);
5063 if (!yin) {
5064 return NULL;
5065 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005067 /* check root element */
5068 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005069 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005070 goto error;
5071 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005073 GETVAL(value, yin, "name");
5074 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
5075 goto error;
5076 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005078 module = calloc(1, sizeof *module);
5079 if (!module) {
5080 LOGMEM;
5081 goto error;
5082 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005083
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005084 module->ctx = ctx;
5085 module->name = lydict_insert(ctx, value, strlen(value));
5086 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005087 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005088
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005089 LOGVRB("Reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005090 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005091 goto error;
5092 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005094 /* add to the context's list of modules */
5095 if (ctx->models.used == ctx->models.size) {
5096 newlist = realloc(ctx->models.list, ctx->models.size * 2);
5097 if (!newlist) {
5098 LOGMEM;
5099 goto error;
5100 }
5101 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5102 newlist[i] = NULL;
5103 }
5104 ctx->models.size *= 2;
5105 ctx->models.list = newlist;
5106 }
5107 for (i = 0; ctx->models.list[i]; i++) {
5108 /* check name (name/revision) and namespace uniqueness */
5109 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005110 if (ctx->models.list[i]->rev_size == module->rev_size) {
5111 /* both have the same number of revisions */
5112 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5113 /* both have the same revision -> we already have the same module */
5114 /* so free the new one and update the old one's implement flag if needed */
5115 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005116 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02005117 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02005118
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005119 LOGVRB("Module %s already in context", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005120
5121 if (implement && !ctx->models.list[i]->implemented) {
5122 lyp_set_implemented(ctx->models.list[i]);
5123 }
5124 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005125 }
5126 }
Radek Krejcif647e612015-07-30 11:36:07 +02005127 /* else (both elses) keep searching, for now the caller is just adding
5128 * another revision of an already present schema
5129 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005130 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
5131 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
5132 ctx->models.list[i]->name, module->name, module->ns);
5133 goto error;
5134 }
5135 }
5136 ctx->models.list[i] = module;
5137 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005138 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005140 /* cleanup */
5141 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005142
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005143 LOGVRB("Module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005145 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005146
5147error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005148 /* cleanup */
5149 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005150 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005152 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005153}