blob: 12e74b0faa1449184ac61500fed41bd00a8bc5df [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) {
Michal Vasko5b64da22015-11-23 15:22:30 +01001015 GETVAL(value, node, "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 */
Michal Vasko5b64da22015-11-23 15:22:30 +01001029 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], node)) {
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
Radek Krejci581ce772015-11-10 17:22:40 +01001257static int
1258fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique, struct unres_schema *unres)
1259{
1260 int i, j;
1261 const char *value, *vaux;
1262
1263 /* get unique value (list of leafs supposed to be unique */
1264 GETVAL(value, yin, "tag");
1265
1266 /* count the number of unique leafs in the value */
1267 vaux = value;
1268 while ((vaux = strpbrk(vaux, " \t\n"))) {
1269 unique->expr_size++;
1270 while (isspace(*vaux)) {
1271 vaux++;
1272 }
1273 }
1274 unique->expr_size++;
1275 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
1276
1277 for (i = 0; i < unique->expr_size; i++) {
1278 vaux = strpbrk(value, " \t\n");
1279 if (!vaux) {
1280 /* the last token, lydict_insert() will count its size on its own */
1281 vaux = value;
1282 }
1283
1284 /* store token into unique structure */
1285 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
1286
1287 /* check that the expression does not repeat */
1288 for (j = 0; j < i; j++) {
1289 if (unique->expr[j] == unique->expr[i]) {
1290 LOGVAL(LYE_INARG, LOGLINE(yin), unique->expr[i], "unique");
1291 LOGVAL(LYE_SPEC, 0, "The identifier is not unique");
1292 goto error;
1293 }
1294 }
1295
1296 /* try to resolve leaf */
1297 if (unres) {
1298 unres_schema_add_str(module, unres, parent, UNRES_LIST_UNIQ, unique->expr[i], LOGLINE(yin));
1299 } else {
1300 if (resolve_unique(parent, value, 0, LOGLINE(yin))) {
1301 goto error;
1302 }
1303 }
1304
1305 /* move to next token */
1306 value = vaux;
1307 while(isspace(*value)) {
1308 value++;
1309 }
1310 }
1311
1312 return EXIT_SUCCESS;
1313
1314error:
1315 return EXIT_FAILURE;
1316}
1317
Michal Vasko0d343d12015-08-24 14:57:36 +02001318/* logs directly
1319 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001320 * type: 0 - min, 1 - max
1321 */
1322static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001323deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001324{
1325 const char *value;
1326 char *endptr;
1327 unsigned long val;
1328 uint32_t *ui32val;
1329
1330 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001331 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001332 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001333 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001334 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001335 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001336 }
Radek Krejci76512572015-08-04 09:47:08 +02001337 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001338 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001339 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001340 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001341 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001342 }
1343 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001344 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1345 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001346 goto error;
1347 }
1348
1349 GETVAL(value, node, "value");
1350 while (isspace(value[0])) {
1351 value++;
1352 }
1353
1354 /* convert it to uint32_t */
1355 errno = 0;
1356 endptr = NULL;
1357 val = strtoul(value, &endptr, 10);
1358 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001359 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001360 goto error;
1361 }
1362 if (type) {
1363 d->max = (uint32_t)val;
1364 } else {
1365 d->min = (uint32_t)val;
1366 }
1367
1368 if (d->mod == LY_DEVIATE_ADD) {
1369 /* check that there is no current value */
1370 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001371 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1372 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 goto error;
1374 }
1375 }
1376
1377 if (d->mod == LY_DEVIATE_DEL) {
1378 /* check values */
1379 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001380 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1381 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001382 goto error;
1383 }
1384 /* remove current min-elements value of the target */
1385 *ui32val = 0;
1386 } else { /* add (already checked) and replace */
1387 /* set new value specified in deviation */
1388 *ui32val = (uint32_t)val;
1389 }
1390
1391 return EXIT_SUCCESS;
1392
1393error:
1394
1395 return EXIT_FAILURE;
1396}
1397
Michal Vasko0d343d12015-08-24 14:57:36 +02001398/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001399static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001400fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001401{
1402 const char *value, **stritem;
1403 struct lyxml_elem *next, *child, *develem;
1404 int c_dev = 0, c_must, c_uniq;
1405 int f_min = 0; /* flags */
Radek Krejci581ce772015-11-10 17:22:40 +01001406 int i, j, k, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001407 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001408 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001409 struct lys_node_choice *choice = NULL;
1410 struct lys_node_leaf *leaf = NULL;
1411 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001412 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001413 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001414 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415
1416 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02001417 dev->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02001418 if (!dev->target_name) {
1419 goto error;
1420 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001421
1422 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001423 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1424 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001425 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001426 goto error;
1427 }
1428 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001429 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001430 goto error;
1431 }
1432 /* mark the target module as deviated */
1433 dev->target->module->deviated = 1;
1434
1435 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001436 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1437 /* garbage */
1438 lyxml_free_elem(module->ctx, child);
1439 continue;
1440 }
1441
Radek Krejcieb00f512015-07-01 16:44:58 +02001442 if (!strcmp(child->name, "description")) {
1443 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001444 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001445 goto error;
1446 }
1447 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1448 if (!dev->dsc) {
1449 goto error;
1450 }
1451 } else if (!strcmp(child->name, "reference")) {
1452 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001453 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 goto error;
1455 }
1456 dev->ref = read_yin_subnode(module->ctx, child, "text");
1457 if (!dev->ref) {
1458 goto error;
1459 }
1460 } else if (!strcmp(child->name, "deviate")) {
1461 c_dev++;
1462
1463 /* skip lyxml_free_elem() at the end of the loop, node will be
1464 * further processed later
1465 */
1466 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001467
Radek Krejcieb00f512015-07-01 16:44:58 +02001468 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001469 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001470 goto error;
1471 }
1472
1473 lyxml_free_elem(module->ctx, child);
1474 }
1475
1476 if (c_dev) {
1477 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1478 }
1479
1480 LY_TREE_FOR(yin->child, develem) {
1481 /* init */
1482 f_min = 0;
1483 c_must = 0;
1484 c_uniq = 0;
1485
1486 /* get deviation type */
1487 GETVAL(value, develem, "value");
1488 if (!strcmp(value, "not-supported")) {
1489 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1490 /* no property expected in this case */
1491 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001492 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001493 goto error;
1494 }
1495
Radek Krejci5b917642015-07-02 09:03:13 +02001496 /* and neither any other deviate statement is expected,
1497 * not-supported deviation must be the only deviation of the target
1498 */
1499 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001500 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1501 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001502 goto error;
1503 }
1504
1505
Radek Krejcieb00f512015-07-01 16:44:58 +02001506 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001507 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001508 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001509
Radek Krejci5b917642015-07-02 09:03:13 +02001510 dev->deviate_size = 1;
1511 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 } else if (!strcmp(value, "add")) {
1513 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1514 } else if (!strcmp(value, "replace")) {
1515 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1516 } else if (!strcmp(value, "delete")) {
1517 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1518 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001519 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001520 goto error;
1521 }
1522 d = &dev->deviate[dev->deviate_size];
1523
1524 /* process deviation properties */
1525 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001526 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1527 /* garbage */
1528 lyxml_free_elem(module->ctx, child);
1529 continue;
1530 }
1531
Radek Krejcieb00f512015-07-01 16:44:58 +02001532 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001533 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001534 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001535 goto error;
1536 }
1537
1538 /* for we deviate from RFC 6020 and allow config property even it is/is not
1539 * specified in the target explicitly since config property inherits. So we expect
1540 * that config is specified in every node. But for delete, we check that the value
1541 * is the same as here in deviation
1542 */
1543 GETVAL(value, child, "value");
1544 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001545 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001546 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001547 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001548 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001549 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 goto error;
1551 }
1552
1553 if (d->mod == LY_DEVIATE_DEL) {
1554 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001555 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001556 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1557 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001558 goto error;
1559 }
1560 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001561 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001562
1563 /* ... and inherit config value from the target's parent */
1564 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001565 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001566 } else {
1567 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001568 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 }
1570 } else { /* add and replace are the same in this case */
1571 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001572 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001573
1574 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001575 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 }
1577 } else if (!strcmp(child->name, "default")) {
1578 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001579 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001580 goto error;
1581 }
1582 GETVAL(value, child, "value");
1583 d->dflt = lydict_insert(module->ctx, value, 0);
1584
Radek Krejci76512572015-08-04 09:47:08 +02001585 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001586 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001587
1588 if (d->mod == LY_DEVIATE_ADD) {
1589 /* check that there is no current value */
1590 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001591 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1592 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001593 goto error;
1594 }
1595 }
1596
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001597 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1598 if (rc) {
1599 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1600 goto error;
1601 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001602 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001603 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001604 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1605 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001606 goto error;
1607 }
1608 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001609 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001610 if (!choice->dflt) {
1611 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001612 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 goto error;
1614 }
1615 }
Radek Krejci76512572015-08-04 09:47:08 +02001616 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001617 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001618
1619 if (d->mod == LY_DEVIATE_ADD) {
1620 /* check that there is no current value */
1621 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001622 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1623 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 goto error;
1625 }
1626 }
1627
1628 if (d->mod == LY_DEVIATE_DEL) {
1629 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001630 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1631 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001632 goto error;
1633 }
1634 /* remove value */
1635 lydict_remove(leaf->module->ctx, leaf->dflt);
1636 leaf->dflt = NULL;
1637 } else { /* add (already checked) and replace */
1638 /* remove value */
1639 lydict_remove(leaf->module->ctx, leaf->dflt);
1640
1641 /* set new value */
1642 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1643 }
1644 } else {
1645 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001646 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1647 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001648 goto error;
1649 }
1650 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001651 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001652 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 goto error;
1654 }
1655
1656 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001657 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001658 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1659 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 goto error;
1661 }
1662
1663 GETVAL(value, child, "value");
1664 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001665 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001667 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001668 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001669 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001670 goto error;
1671 }
1672
1673 if (d->mod == LY_DEVIATE_ADD) {
1674 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001675 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001676 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1677 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001678 goto error;
1679 }
1680 }
1681
1682 if (d->mod == LY_DEVIATE_DEL) {
1683 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001684 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001685 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1686 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001687 goto error;
1688 }
1689 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001690 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001691 } else { /* add (already checked) and replace */
1692 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001693 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001694
1695 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001696 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001697 }
1698 } else if (!strcmp(child->name, "min-elements")) {
1699 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001700 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001701 goto error;
1702 }
1703 f_min = 1;
1704
1705 if (deviate_minmax(dev->target, child, d, 0)) {
1706 goto error;
1707 }
1708 } else if (!strcmp(child->name, "max-elements")) {
1709 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001710 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001711 goto error;
1712 }
1713
1714 if (deviate_minmax(dev->target, child, d, 1)) {
1715 goto error;
1716 }
1717 } else if (!strcmp(child->name, "must")) {
1718 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001719 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1720 continue;
1721 } else if (!strcmp(child->name, "type")) {
1722 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001723 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 goto error;
1725 }
1726
1727 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001728 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001729 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001730 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001731 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001732 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001733 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1734 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001735 goto error;
1736 }
1737
1738 if (d->mod == LY_DEVIATE_ADD) {
1739 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001740 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1741 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001742 goto error;
1743 } else if (d->mod == LY_DEVIATE_DEL) {
1744 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001745 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1746 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 goto error;
1748 }
1749
1750 /* replace */
1751 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001752 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001753
1754 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001755 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 goto error;
1757 }
1758 d->type = t;
1759 } else if (!strcmp(child->name, "unique")) {
1760 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1762 continue;
1763 } else if (!strcmp(child->name, "units")) {
1764 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001765 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001766 goto error;
1767 }
1768
1769 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001770 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001771 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001772 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001773 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001774 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001775 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1776 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001777 goto error;
1778 }
1779
1780 /* get units value */
1781 GETVAL(value, child, "name");
1782 d->units = lydict_insert(module->ctx, value, 0);
1783
1784 /* apply to target */
1785 if (d->mod == LY_DEVIATE_ADD) {
1786 /* check that there is no current value */
1787 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001788 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1789 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 goto error;
1791 }
1792 }
1793
1794 if (d->mod == LY_DEVIATE_DEL) {
1795 /* check values */
1796 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001797 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1798 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001799 goto error;
1800 }
1801 /* remove current units value of the target */
1802 lydict_remove(dev->target->module->ctx, *stritem);
1803 } else { /* add (already checked) and replace */
1804 /* remove current units value of the target ... */
1805 lydict_remove(dev->target->module->ctx, *stritem);
1806
1807 /* ... and replace it with the value specified in deviation */
1808 *stritem = lydict_insert(module->ctx, value, 0);
1809 }
1810 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001811 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001812 goto error;
1813 }
1814
1815 lyxml_free_elem(module->ctx, child);
1816 }
1817
1818 if (c_must) {
1819 /* check target node type */
1820 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001821 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001822 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1823 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001824 break;
Radek Krejci76512572015-08-04 09:47:08 +02001825 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001826 trg_must = &((struct lys_node_container *)dev->target)->must;
1827 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001828 break;
Radek Krejci76512572015-08-04 09:47:08 +02001829 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001830 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1831 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001832 break;
Radek Krejci76512572015-08-04 09:47:08 +02001833 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001834 trg_must = &((struct lys_node_list *)dev->target)->must;
1835 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001836 break;
Radek Krejci76512572015-08-04 09:47:08 +02001837 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001838 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1839 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001840 break;
1841 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001842 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1843 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001844 goto error;
1845 }
1846
1847 if (d->mod == LY_DEVIATE_RPL) {
1848 /* remove target's musts and allocate new array for it */
1849 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001850 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1851 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 goto error;
1853 }
1854
1855 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001856 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 }
1858 free(*trg_must);
1859 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1860 d->must_size = c_must;
1861 *trg_must_size = 0;
1862 } else if (d->mod == LY_DEVIATE_ADD) {
1863 /* reallocate the must array of the target */
1864 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1865 *trg_must = d->must;
Michal Vasko979ad5b2015-10-23 10:12:55 +02001866 d->must = &((*trg_must)[*trg_must_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001867 d->must_size = c_must;
1868 } else { /* LY_DEVIATE_DEL */
1869 d->must = calloc(c_must, sizeof *d->must);
1870 }
1871 }
1872 if (c_uniq) {
1873 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001874 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001875 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1876 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001877 goto error;
1878 }
1879
Radek Krejcib8048692015-08-05 13:36:34 +02001880 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001881 if (d->mod == LY_DEVIATE_RPL) {
1882 /* remove target's unique and allocate new array for it */
1883 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001884 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1885 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001886 goto error;
1887 }
1888
1889 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001890 for (j = 0; j < list->unique[i].expr_size; j++) {
1891 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1892 }
1893 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001894 }
1895 free(list->unique);
1896 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1897 d->unique_size = c_uniq;
1898 list->unique_size = 0;
1899 } else if (d->mod == LY_DEVIATE_ADD) {
1900 /* reallocate the unique array of the target */
1901 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1902 list->unique = d->unique;
1903 d->unique = &list->unique[list->unique_size];
1904 d->unique_size = c_uniq;
1905 } else { /* LY_DEVIATE_DEL */
1906 d->unique = calloc(c_uniq, sizeof *d->unique);
1907 }
1908 }
1909
1910 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001911 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 if (!strcmp(child->name, "must")) {
1913 if (d->mod == LY_DEVIATE_DEL) {
1914 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1915 goto error;
1916 }
1917
1918 /* find must to delete, we are ok with just matching conditions */
1919 for (i = 0; i < *trg_must_size; i++) {
1920 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1921 /* we have a match, free the must structure ... */
Michal Vasko5e7d9ca2015-10-23 10:37:28 +02001922 lys_restr_free(dev->target->module->ctx, &((*trg_must)[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001923 /* ... and maintain the array */
1924 (*trg_must_size)--;
1925 if (i != *trg_must_size) {
1926 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1927 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1928 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1929 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1930 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1931 }
1932 if (!(*trg_must_size)) {
1933 free(*trg_must);
1934 *trg_must = NULL;
1935 } else {
1936 (*trg_must)[*trg_must_size].expr = NULL;
1937 (*trg_must)[*trg_must_size].dsc = NULL;
1938 (*trg_must)[*trg_must_size].ref = NULL;
1939 (*trg_must)[*trg_must_size].eapptag = NULL;
1940 (*trg_must)[*trg_must_size].emsg = NULL;
1941 }
1942
1943 i = -1; /* set match flag */
1944 break;
1945 }
1946 }
1947 d->must_size++;
1948 if (i != -1) {
1949 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001950 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1951 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001952 goto error;
1953 }
1954 } else { /* replace or add */
1955 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1956 goto error;
1957 }
1958 (*trg_must_size)++;
1959 }
1960 } else if (!strcmp(child->name, "unique")) {
1961 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci581ce772015-11-10 17:22:40 +01001962 if (fill_yin_unique(module, dev->target, child, &d->unique[d->unique_size], NULL)) {
1963 d->unique_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001964 goto error;
1965 }
1966
1967 /* find unique structures to delete */
1968 for (i = 0; i < list->unique_size; i++) {
Radek Krejci581ce772015-11-10 17:22:40 +01001969 if (list->unique[i].expr_size != d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001970 continue;
1971 }
1972
Radek Krejci581ce772015-11-10 17:22:40 +01001973 for (j = 0; j < d->unique[d->unique_size].expr_size; j++) {
1974 if (list->unique[i].expr[j] != d->unique[d->unique_size].expr[j]) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001975 break;
1976 }
1977 }
1978
Radek Krejci581ce772015-11-10 17:22:40 +01001979 if (j == d->unique[d->unique_size].expr_size) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001980 /* we have a match, free the unique structure ... */
Radek Krejci581ce772015-11-10 17:22:40 +01001981 for (j = 0; j < list->unique[i].expr_size; j++) {
1982 lydict_remove(list->module->ctx, list->unique[i].expr[j]);
1983 }
1984 free(list->unique[i].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02001985 /* ... and maintain the array */
1986 list->unique_size--;
1987 if (i != list->unique_size) {
Radek Krejci581ce772015-11-10 17:22:40 +01001988 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1989 list->unique[i].expr = list->unique[list->unique_size].expr;
Radek Krejcieb00f512015-07-01 16:44:58 +02001990 }
1991
1992 if (!list->unique_size) {
1993 free(list->unique);
1994 list->unique = NULL;
1995 } else {
Radek Krejci581ce772015-11-10 17:22:40 +01001996 list->unique[list->unique_size].expr_size = 0;
1997 list->unique[list->unique_size].expr = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001998 }
1999
2000 i = -1; /* set match flag */
2001 break;
2002 }
2003 }
2004
2005 d->unique_size++;
2006 if (i != -1) {
2007 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002008 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
2009 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002010 goto error;
2011 }
2012 } else { /* replace or add */
Radek Krejci581ce772015-11-10 17:22:40 +01002013 if (fill_yin_unique(module, dev->target, child, &list->unique[list->unique_size++], NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 goto error;
2015 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002016 }
2017 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002018 }
Radek Krejci5b917642015-07-02 09:03:13 +02002019
2020 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002021 }
2022
Radek Krejcieb00f512015-07-01 16:44:58 +02002023 return EXIT_SUCCESS;
2024
2025error:
2026
2027 if (dev->deviate) {
2028 for (i = 0; i < dev->deviate_size; i++) {
2029 lydict_remove(module->ctx, dev->deviate[i].dflt);
2030 lydict_remove(module->ctx, dev->deviate[i].units);
2031
2032 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2033 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002034 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02002035 }
2036 free(dev->deviate[i].must);
2037
2038 for (j = 0; j < dev->deviate[i].unique_size; j++) {
Radek Krejci581ce772015-11-10 17:22:40 +01002039 for (k = 0; k < dev->deviate[i].unique[i].expr_size; k++) {
2040 lydict_remove(module->ctx, dev->deviate[i].unique[j].expr[k]);
2041 }
2042 free(dev->deviate[i].unique[j].expr);
Radek Krejcieb00f512015-07-01 16:44:58 +02002043 }
2044 free(dev->deviate[i].unique);
2045 }
2046 }
2047 free(dev->deviate);
2048 }
2049
2050 return EXIT_FAILURE;
2051}
2052
Michal Vasko0d343d12015-08-24 14:57:36 +02002053/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02002054static int
Radek Krejcib8048692015-08-05 13:36:34 +02002055fill_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 +02002056 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002057{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002058 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002059 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002060 struct lys_node *node;
Michal Vasko2d851a92015-10-20 16:16:36 +02002061 int c = 0, ret;
Radek Krejci106efc02015-06-10 14:36:27 +02002062
Michal Vasko591e0b22015-08-13 13:53:43 +02002063 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002065 aug->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vasko488c19e2015-10-20 15:21:00 +02002066 if (!aug->target_name) {
2067 goto error;
2068 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002069 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002070
Michal Vasko1d87a922015-08-21 12:57:16 +02002071 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002072 goto error;
2073 }
2074
2075 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002076 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2077 /* garbage */
2078 lyxml_free_elem(module->ctx, child);
2079 continue;
2080 }
2081
Radek Krejci3cf9e222015-06-18 11:37:50 +02002082 if (!strcmp(child->name, "if-feature")) {
2083 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002084 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002085 } else if (!strcmp(child->name, "when")) {
2086 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002087 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002088 goto error;
2089 }
2090
2091 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002092 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002093 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002094 goto error;
2095 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002096 if (lyxp_syntax_check(aug->when->cond, LOGLINE(child))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002097 goto error;
2098 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002099 lyxml_free_elem(module->ctx, child);
2100 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002101
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002102 /* check allowed data sub-statements */
2103 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002104 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002105 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002106 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002107 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002108 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002109 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002110 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002111 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002112 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002113 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002114 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002115 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002116 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002117 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002118 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002119 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002120 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002121 goto error;
2122 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002123
Radek Krejci1d82ef62015-08-07 14:44:40 +02002124 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002125 goto error;
2126 }
2127
2128 /* check for mandatory nodes - if the target node is in another module
2129 * the added nodes cannot be mandatory
2130 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002131 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002132 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002133 goto error;
2134 }
2135
Radek Krejci1d82ef62015-08-07 14:44:40 +02002136 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002137 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002138 }
2139
2140 if (c) {
2141 aug->features = calloc(c, sizeof *aug->features);
2142 }
2143
2144 LY_TREE_FOR_SAFE(yin->child, next, child) {
2145 if (!strcmp(child->name, "if-feature")) {
2146 GETVAL(value, child, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002147 if (!(value = transform_schema2json(module, value, LOGLINE(child)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002148 goto error;
2149 }
2150 ret = unres_schema_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value,
2151 LOGLINE(child));
2152 lydict_remove(module->ctx, value);
2153 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002154 goto error;
2155 }
Radek Krejci73adb602015-07-02 18:07:40 +02002156 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002157 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002158 }
2159
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002160 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002161 * connected to the tree and adjusted (if possible right now).
2162 * However, if this is augment in a uses, it gets resolved
2163 * when the uses does and cannot be resolved now for sure
2164 * (the grouping was not yet copied into uses).
2165 */
2166 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02002167 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002168 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2169 goto error;
2170 }
Michal Vasko49291b32015-08-06 09:49:41 +02002171 }
Radek Krejci106efc02015-06-10 14:36:27 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002174
2175error:
2176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002178}
2179
Michal Vasko0d343d12015-08-24 14:57:36 +02002180/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002181static int
Michal Vasko0d204592015-10-07 09:50:04 +02002182fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002183{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002184 struct lyxml_elem *sub, *next;
2185 const char *value;
2186 char *endptr;
2187 int f_mand = 0, f_min = 0, f_max = 0;
2188 int c_must = 0;
2189 int r;
2190 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002191
Radek Krejci76512572015-08-04 09:47:08 +02002192 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 goto error;
2194 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002195
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002196 GETVAL(value, yin, "target-node");
Michal Vaskofba15262015-10-21 12:10:28 +02002197 rfn->target_name = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskoa8b25952015-10-20 15:30:25 +02002198 if (!rfn->target_name) {
2199 goto error;
2200 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002203 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2204 /* garbage */
2205 lyxml_free_elem(module->ctx, sub);
2206 continue;
2207 }
2208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 /* limited applicability */
2210 if (!strcmp(sub->name, "default")) {
2211 /* leaf or choice */
2212 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002213 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 goto error;
2215 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 /* check possibility of statements combination */
2218 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002219 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002221 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 goto error;
2223 }
2224 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002225 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 GETVAL(value, sub, "value");
2229 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2230 } else if (!strcmp(sub->name, "mandatory")) {
2231 /* leaf, choice or anyxml */
2232 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002233 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 goto error;
2235 }
2236 /* just checking the flags in leaf is not sufficient, we would allow
2237 * multiple mandatory statements with the "false" value
2238 */
2239 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002241 /* check possibility of statements combination */
2242 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002243 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002245 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 goto error;
2247 }
2248 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002249 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002252 GETVAL(value, sub, "value");
2253 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002254 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002256 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002257 } else {
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 } else if (!strcmp(sub->name, "min-elements")) {
2262 /* list or leaf-list */
2263 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002264 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 goto error;
2266 }
2267 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002268
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 /* check possibility of statements combination */
2270 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002271 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002273 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 goto error;
2275 }
2276 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002277 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002278 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 GETVAL(value, sub, "value");
2281 while (isspace(value[0])) {
2282 value++;
2283 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 /* convert it to uint32_t */
2286 errno = 0;
2287 endptr = NULL;
2288 val = strtoul(value, &endptr, 10);
2289 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002290 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 goto error;
2292 }
2293 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 /* magic - bit 3 in flags means min set */
2296 rfn->flags |= 0x04;
2297 } else if (!strcmp(sub->name, "max-elements")) {
2298 /* list or leaf-list */
2299 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002300 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 goto error;
2302 }
2303 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 /* check possibility of statements combination */
2306 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002307 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002309 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 goto error;
2311 }
2312 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002313 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 GETVAL(value, sub, "value");
2317 while (isspace(value[0])) {
2318 value++;
2319 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 /* convert it to uint32_t */
2322 errno = 0;
2323 endptr = NULL;
2324 val = strtoul(value, &endptr, 10);
2325 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002326 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 goto error;
2328 }
2329 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 /* magic - bit 4 in flags means min set */
2332 rfn->flags |= 0x08;
2333 } else if (!strcmp(sub->name, "presence")) {
2334 /* container */
2335 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002336 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 goto error;
2338 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 /* check possibility of statements combination */
2341 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002342 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002343 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002344 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345 goto error;
2346 }
2347 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002348 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002349 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 GETVAL(value, sub, "value");
2352 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2353 } else if (!strcmp(sub->name, "must")) {
2354 /* leaf-list, list, container or anyxml */
2355 /* check possibility of statements combination */
2356 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002357 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002359 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002360 goto error;
2361 }
2362 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002363 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002367 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002370 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 goto error;
2372 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 lyxml_free_elem(module->ctx, sub);
2375 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 /* process nodes with cardinality of 0..n */
2378 if (c_must) {
2379 rfn->must = calloc(c_must, sizeof *rfn->must);
2380 }
Radek Krejci73adb602015-07-02 18:07:40 +02002381 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002382 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002383 if (r) {
2384 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002385 }
Michal Vasko0d204592015-10-07 09:50:04 +02002386 if (lyxp_syntax_check(rfn->must[rfn->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002387 goto error;
2388 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002392
2393error:
2394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002395 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002396}
2397
Michal Vasko0d343d12015-08-24 14:57:36 +02002398/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002399static int
Radek Krejcib8048692015-08-05 13:36:34 +02002400fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002401{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 struct lyxml_elem *child;
2403 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002404 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002407 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2408 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002409 continue;
2410 }
2411
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 if (!strcmp(child->name, "prefix")) {
2413 GETVAL(value, child, "value");
2414 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2415 goto error;
2416 }
2417 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2418 } else if (!strcmp(child->name, "revision-date")) {
2419 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002420 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 goto error;
2422 }
2423 GETVAL(value, child, "date");
2424 if (check_date(value, LOGLINE(child))) {
2425 goto error;
2426 }
2427 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2428 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002429 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 goto error;
2431 }
2432 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434 /* check mandatory information */
2435 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002436 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 goto error;
2438 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002440 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002441
2442 /* check for circular import, store it if passed */
2443 if (!module->ctx->models.parsing) {
2444 count = 0;
2445 } else {
2446 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2447 if (value == module->ctx->models.parsing[count]) {
2448 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
2449 goto error;
2450 }
2451 }
2452 }
2453 ++count;
2454 module->ctx->models.parsing =
2455 realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2456 module->ctx->models.parsing[count - 1] = value;
2457 module->ctx->models.parsing[count] = NULL;
2458
2459 /* try to load the module */
Radek Krejci63a91a92015-07-29 13:31:04 +02002460 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002461 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002462 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
Michal Vasko1b882eb2015-10-22 11:43:14 +02002463 }
2464
2465 /* remove the new module name now that its parsing is finished (even if failed) */
2466 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2467 LOGINT;
2468 }
2469 --count;
2470 if (count) {
2471 module->ctx->models.parsing[count] = NULL;
2472 } else {
2473 free(module->ctx->models.parsing);
2474 module->ctx->models.parsing = NULL;
2475 }
2476
2477 /* check the result */
2478 if (!imp->module) {
2479 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2480 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
2481 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002485
2486error:
2487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002488 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002489}
2490
Michal Vasko0d343d12015-08-24 14:57:36 +02002491/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492static int
Radek Krejcib8048692015-08-05 13:36:34 +02002493fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002494{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002495 struct lyxml_elem *child;
2496 const char *value;
Michal Vasko1b882eb2015-10-22 11:43:14 +02002497 int count;
Radek Krejciefaeba32015-05-27 14:30:57 +02002498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002500 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2501 /* garbage */
2502 continue;
2503 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 if (!strcmp(child->name, "revision-date")) {
2505 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002506 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002507 goto error;
2508 }
2509 GETVAL(value, child, "date");
2510 if (check_date(value, LOGLINE(child))) {
2511 goto error;
2512 }
2513 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2514 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002515 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 goto error;
2517 }
2518 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002520 GETVAL(value, yin, "module");
Michal Vasko1b882eb2015-10-22 11:43:14 +02002521
2522 /* check for circular include, store it if passed */
2523 if (!module->ctx->models.parsing) {
2524 count = 0;
2525 } else {
2526 for (count = 0; module->ctx->models.parsing[count]; ++count) {
2527 if (value == module->ctx->models.parsing[count]) {
2528 LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
2529 goto error;
2530 }
2531 }
2532 }
2533 ++count;
2534 module->ctx->models.parsing =
2535 realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
2536 module->ctx->models.parsing[count - 1] = value;
2537 module->ctx->models.parsing[count] = NULL;
2538
2539 /* try to load the submodule */
Radek Krejci63a91a92015-07-29 13:31:04 +02002540 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 if (!inc->submodule) {
Michal Vasko1b882eb2015-10-22 11:43:14 +02002542 inc->submodule = (struct lys_submodule *)lyp_search_file(module->ctx, module, value, inc->rev[0] ? inc->rev : NULL);
2543 }
2544
2545 /* remove the new submodule name now that its parsing is finished (even if failed) */
2546 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
2547 LOGINT;
2548 }
2549 --count;
2550 if (count) {
2551 module->ctx->models.parsing[count] = NULL;
2552 } else {
2553 free(module->ctx->models.parsing);
2554 module->ctx->models.parsing = NULL;
2555 }
2556
2557 /* check the result */
2558 if (!inc->submodule) {
2559 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2560 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2561 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002562 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 /* check that belongs-to corresponds */
2565 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002566 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002567 }
2568 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002569 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Michal Vasko105aa752015-10-22 11:40:11 +02002570 LOGERR(LY_EVALID, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 goto error;
2572 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002574 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002575
2576error:
2577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002578 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002579}
2580
Michal Vasko0d343d12015-08-24 14:57:36 +02002581/* logs directly
2582 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002583 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002584 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002585 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002586 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002587static int
Radek Krejcib8048692015-08-05 13:36:34 +02002588read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002589 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002590{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 const char *value;
2592 struct lyxml_elem *sub, *next;
2593 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002596 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002598
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002599 if (opt & OPT_IDENT) {
2600 GETVAL(value, xmlnode, "name");
2601 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2602 goto error;
2603 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002604 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002606
Radek Krejci6764bb32015-07-03 15:16:04 +02002607 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002608 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002609 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002610 }
2611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002612 /* process local parameters */
2613 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002614 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002615 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002616 lyxml_free_elem(ctx, sub);
2617 continue;
2618 }
2619 if (strcmp(sub->ns->value, LY_NSYIN)) {
2620 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002621 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002622 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002624 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002625 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002626 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002627 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002628 goto error;
2629 }
2630 }
2631
2632 /* else garbage */
2633 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002634 continue;
2635 }
2636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002637 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002638 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002639 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 goto error;
2641 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002642 node->dsc = read_yin_subnode(ctx, sub, "text");
2643 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002644 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 }
2646 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002647 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002648 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 goto error;
2650 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002651 node->ref = read_yin_subnode(ctx, sub, "text");
2652 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002653 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002654 }
2655 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002656 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002657 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 goto error;
2659 }
2660 GETVAL(value, sub, "value");
2661 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002662 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002664 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002666 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002668 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002669 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002670 }
2671 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002672 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002673 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 goto error;
2675 }
2676 GETVAL(value, sub, "value");
2677 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002678 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002679 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002680 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002682 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002683 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 }
2685 } else {
2686 /* skip the lyxml_free_elem */
2687 continue;
2688 }
2689 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002691
Radek Krejci1d82ef62015-08-07 14:44:40 +02002692 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 /* get config flag from parent */
2694 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002695 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 } else {
2697 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002698 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 }
2700 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002703
2704error:
2705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002706 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002707}
2708
Michal Vasko0d343d12015-08-24 14:57:36 +02002709/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002710static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002711read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002712{
Radek Krejci76512572015-08-04 09:47:08 +02002713 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002714 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002715 const char *value;
2716
2717 retval = calloc(1, sizeof *retval);
2718
2719 GETVAL(value, yin, "condition");
Michal Vaskofba15262015-10-21 12:10:28 +02002720 retval->cond = transform_schema2json(module, value, LOGLINE(yin));
Michal Vaskof9893382015-10-09 14:03:04 +02002721 if (!retval->cond) {
2722 goto error;
2723 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002724
Radek Krejci73adb602015-07-02 18:07:40 +02002725 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002726 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2727 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002728 continue;
2729 }
2730
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002731 if (!strcmp(child->name, "description")) {
2732 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002733 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002734 goto error;
2735 }
2736 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2737 if (!retval->dsc) {
2738 goto error;
2739 }
2740 } else if (!strcmp(child->name, "reference")) {
2741 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002742 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002743 goto error;
2744 }
2745 retval->ref = read_yin_subnode(module->ctx, child, "text");
2746 if (!retval->ref) {
2747 goto error;
2748 }
2749 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002750 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002751 goto error;
2752 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002753 }
2754
2755 return retval;
2756
2757error:
2758
Michal Vasko0308dd62015-10-07 09:14:40 +02002759 lys_when_free(module->ctx, retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002760 return NULL;
2761}
2762
Michal Vasko0d343d12015-08-24 14:57:36 +02002763/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002764static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002765read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2766 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002767{
Michal Vasko29fc0182015-08-24 15:02:39 +02002768 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002769 struct lys_node_case *cs;
2770 struct lys_node *retval, *node = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002771 int c_ftrs = 0, ret;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002772 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002773
Radek Krejcie867c852015-08-27 09:52:34 +02002774 /* init */
2775 memset(&root, 0, sizeof root);
2776
Radek Krejci1d82ef62015-08-07 14:44:40 +02002777 cs = calloc(1, sizeof *cs);
2778 cs->nodetype = LYS_CASE;
2779 cs->prev = (struct lys_node *)cs;
2780 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002781
Radek Krejci6a113852015-07-03 16:04:20 +02002782 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 goto error;
2784 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002785
Radek Krejcia9544502015-08-14 08:24:29 +02002786 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2787
Michal Vasko3a0043f2015-08-12 12:11:30 +02002788 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002789 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002790 goto error;
2791 }
2792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 /* process choice's specific children */
2794 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002795 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2796 /* garbage */
2797 lyxml_free_elem(module->ctx, sub);
2798 continue;
2799 }
2800
Michal Vasko29fc0182015-08-24 15:02:39 +02002801 if (!strcmp(sub->name, "container") ||
2802 !strcmp(sub->name, "leaf-list") ||
2803 !strcmp(sub->name, "leaf") ||
2804 !strcmp(sub->name, "list") ||
2805 !strcmp(sub->name, "uses") ||
2806 !strcmp(sub->name, "choice") ||
2807 !strcmp(sub->name, "anyxml")) {
2808
Michal Vaskof3930de2015-10-22 12:03:59 +02002809 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vasko29fc0182015-08-24 15:02:39 +02002810 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002811 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002812 c_ftrs++;
2813 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2814 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002815 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002816 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002817 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002818 goto error;
2819 }
2820
Radek Krejci1d82ef62015-08-07 14:44:40 +02002821 cs->when = read_yin_when(module, sub);
2822 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002823 goto error;
2824 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002825 if (lyxp_syntax_check(cs->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002826 goto error;
2827 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002828
2829 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002831 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002835
Radek Krejci3cf9e222015-06-18 11:37:50 +02002836 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002837 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002838 }
Radek Krejci73adb602015-07-02 18:07:40 +02002839 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002840 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02002841 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02002842 goto error;
2843 }
2844 ret = unres_schema_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value,
2845 LOGLINE(sub));
2846 lydict_remove(module->ctx, value);
2847 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002848 goto error;
2849 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002850 }
Radek Krejcib388c152015-06-04 17:03:03 +02002851
Michal Vasko29fc0182015-08-24 15:02:39 +02002852 /* last part - process data nodes */
2853 LY_TREE_FOR_SAFE(root.child, next, sub) {
2854 if (!strcmp(sub->name, "container")) {
2855 node = read_yin_container(module, retval, sub, resolve, unres);
2856 } else if (!strcmp(sub->name, "leaf-list")) {
2857 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2858 } else if (!strcmp(sub->name, "leaf")) {
2859 node = read_yin_leaf(module, retval, sub, resolve, unres);
2860 } else if (!strcmp(sub->name, "list")) {
2861 node = read_yin_list(module, retval, sub, resolve, unres);
2862 } else if (!strcmp(sub->name, "choice")) {
2863 node = read_yin_choice(module, retval, sub, resolve, unres);
2864 } else if (!strcmp(sub->name, "uses")) {
2865 node = read_yin_uses(module, retval, sub, resolve, unres);
2866 } else if (!strcmp(sub->name, "anyxml")) {
2867 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2868 }
2869 if (!node) {
2870 goto error;
2871 }
2872
2873 lyxml_free_elem(module->ctx, sub);
2874 }
2875
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002876 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002877
2878error:
2879
Michal Vasko29fc0182015-08-24 15:02:39 +02002880 while (root.child) {
2881 lyxml_free_elem(module->ctx, root.child);
2882 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002883 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002885 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002886}
2887
Michal Vasko0d343d12015-08-24 14:57:36 +02002888/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002889static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002890read_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 +02002891{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 struct lyxml_elem *sub, *next;
2893 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002894 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002895 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002896 const char *value, *dflt_str = NULL;
Michal Vasko2d851a92015-10-20 16:16:36 +02002897 int f_mand = 0, c_ftrs = 0, ret;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002899 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002900 choice->nodetype = LYS_CHOICE;
2901 choice->prev = (struct lys_node *)choice;
2902 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002903
Michal Vaskoe0c59842015-09-24 13:52:20 +02002904 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
2905 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 goto error;
2907 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002908
Radek Krejcia9544502015-08-14 08:24:29 +02002909 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2910
Michal Vasko3a0043f2015-08-12 12:11:30 +02002911 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002912 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002913 goto error;
2914 }
2915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002916 /* process choice's specific children */
2917 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002918 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2919 /* garbage */
2920 lyxml_free_elem(module->ctx, sub);
2921 continue;
2922 }
2923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002925 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002926 goto error;
2927 }
2928 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002929 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002930 goto error;
2931 }
2932 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002933 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 goto error;
2935 }
2936 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002937 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002938 goto error;
2939 }
2940 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002941 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002942 goto error;
2943 }
2944 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002945 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 goto error;
2947 }
2948 } else if (!strcmp(sub->name, "default")) {
2949 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002950 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002951 goto error;
2952 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002953 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002954 } else if (!strcmp(sub->name, "mandatory")) {
2955 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002956 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002957 goto error;
2958 }
2959 /* just checking the flags in leaf is not sufficient, we would allow
2960 * multiple mandatory statements with the "false" value
2961 */
2962 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 GETVAL(value, sub, "value");
2965 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002966 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002967 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002968 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002969 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002970 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 goto error;
2972 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002973 } else if (!strcmp(sub->name, "when")) {
2974 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002975 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002976 goto error;
2977 }
2978
2979 choice->when = read_yin_when(module, sub);
2980 if (!choice->when) {
2981 goto error;
2982 }
Michal Vaskofcdac172015-10-07 09:35:05 +02002983 if (lyxp_syntax_check(choice->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002984 goto error;
2985 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002986 } else if (!strcmp(sub->name, "if-feature")) {
2987 c_ftrs++;
2988
2989 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2990 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002991 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002992 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002995
Radek Krejci1d82ef62015-08-07 14:44:40 +02002996 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 lyxml_free_elem(ctx, sub);
2998 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002999
Radek Krejci3cf9e222015-06-18 11:37:50 +02003000 if (c_ftrs) {
3001 choice->features = calloc(c_ftrs, sizeof *choice->features);
3002 }
3003
Radek Krejci73adb602015-07-02 18:07:40 +02003004 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003005 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003006 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003007 goto error;
3008 }
3009 ret = unres_schema_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value,
3010 LOGLINE(sub));
3011 lydict_remove(module->ctx, value);
3012 if (ret == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003013 goto error;
3014 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003015 }
3016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003018 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003019 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
3021 goto error;
3022 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02003023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 /* link default with the case */
3025 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003026 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003027 goto error;
3028 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003029 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003032
3033error:
3034
Radek Krejci1d82ef62015-08-07 14:44:40 +02003035 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003038}
3039
Michal Vasko0d343d12015-08-24 14:57:36 +02003040/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003041static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003042read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003043 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02003044{
Radek Krejci76512572015-08-04 09:47:08 +02003045 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003046 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 struct lyxml_elem *sub, *next;
3048 const char *value;
3049 int r;
3050 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003051 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02003052
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02003054 anyxml->nodetype = LYS_ANYXML;
3055 anyxml->prev = (struct lys_node *)anyxml;
3056 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02003057
Michal Vaskoe0c59842015-09-24 13:52:20 +02003058 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3059 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 goto error;
3061 }
Radek Krejci863c2852015-06-03 15:47:11 +02003062
Radek Krejcia9544502015-08-14 08:24:29 +02003063 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003064
3065 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003066 goto error;
3067 }
3068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003070 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3071 /* garbage */
3072 lyxml_free_elem(module->ctx, sub);
3073 continue;
3074 }
3075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 if (!strcmp(sub->name, "mandatory")) {
3077 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003078 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003079 goto error;
3080 }
3081 /* just checking the flags in leaf is not sufficient, we would allow
3082 * multiple mandatory statements with the "false" value
3083 */
3084 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02003085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 GETVAL(value, sub, "value");
3087 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003088 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003089 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003090 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003091 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003092 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 goto error;
3094 }
3095 /* else false is the default value, so we can ignore it */
3096 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003097 } else if (!strcmp(sub->name, "when")) {
3098 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003099 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003100 goto error;
3101 }
3102
3103 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003104 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003105 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003106 goto error;
3107 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003108 if (lyxp_syntax_check(anyxml->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003109 goto error;
3110 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003111 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 } else if (!strcmp(sub->name, "must")) {
3113 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003114 } else if (!strcmp(sub->name, "if-feature")) {
3115 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003116
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003118 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003119 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003120 }
3121 }
Radek Krejci863c2852015-06-03 15:47:11 +02003122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 /* middle part - process nodes with cardinality of 0..n */
3124 if (c_must) {
3125 anyxml->must = calloc(c_must, sizeof *anyxml->must);
3126 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003127 if (c_ftrs) {
3128 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
3129 }
Radek Krejci863c2852015-06-03 15:47:11 +02003130
Radek Krejci73adb602015-07-02 18:07:40 +02003131 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003133 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 if (r) {
3135 goto error;
3136 }
Michal Vasko0d204592015-10-07 09:50:04 +02003137 if (lyxp_syntax_check(anyxml->must[anyxml->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003138 goto error;
3139 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003140 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003141 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003142 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003143 goto error;
3144 }
3145 r = unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value,
3146 LOGLINE(sub));
3147 lydict_remove(module->ctx, value);
3148 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003149 goto error;
3150 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 }
Radek Krejci863c2852015-06-03 15:47:11 +02003153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003154 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003155
3156error:
3157
Radek Krejci1d82ef62015-08-07 14:44:40 +02003158 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02003159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003161}
3162
Michal Vasko0d343d12015-08-24 14:57:36 +02003163/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003164static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003165read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003166 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003167{
Radek Krejci76512572015-08-04 09:47:08 +02003168 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003169 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 struct lyxml_elem *sub, *next;
3171 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003172 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003173 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003176 leaf->nodetype = LYS_LEAF;
3177 leaf->prev = (struct lys_node *)leaf;
3178 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003179
Michal Vaskoe0c59842015-09-24 13:52:20 +02003180 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3181 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 goto error;
3183 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003184
Radek Krejcia9544502015-08-14 08:24:29 +02003185 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003186
3187 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003188 goto error;
3189 }
3190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003192 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3193 /* garbage */
3194 lyxml_free_elem(module->ctx, sub);
3195 continue;
3196 }
3197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003199 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003200 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 goto error;
3202 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003203 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 goto error;
3205 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003206 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 } else if (!strcmp(sub->name, "default")) {
3208 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003209 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 goto error;
3211 }
3212 GETVAL(value, sub, "value");
3213 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003214 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 } else if (!strcmp(sub->name, "units")) {
3216 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003217 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 goto error;
3219 }
3220 GETVAL(value, sub, "name");
3221 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3222 } else if (!strcmp(sub->name, "mandatory")) {
3223 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003224 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
3227 /* just checking the flags in leaf is not sufficient, we would allow
3228 * multiple mandatory statements with the "false" value
3229 */
3230 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 GETVAL(value, sub, "value");
3233 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003234 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003235 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003236 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003237 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003238 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 goto error;
3240 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003241 } else if (!strcmp(sub->name, "when")) {
3242 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003243 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003244 goto error;
3245 }
3246
3247 leaf->when = read_yin_when(module, sub);
3248 if (!leaf->when) {
3249 goto error;
3250 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003251 if (lyxp_syntax_check(leaf->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003252 goto error;
3253 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003256 c_must++;
3257 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003258 } else if (!strcmp(sub->name, "if-feature")) {
3259 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003263 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 lyxml_free_elem(module->ctx, sub);
3268 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003271 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003272 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003273 goto error;
3274 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003275 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003276 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003277 goto error;
3278 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 /* middle part - process nodes with cardinality of 0..n */
3282 if (c_must) {
3283 leaf->must = calloc(c_must, sizeof *leaf->must);
3284 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003285 if (c_ftrs) {
3286 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3287 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003288
Radek Krejci73adb602015-07-02 18:07:40 +02003289 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003290 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003291 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 if (r) {
3293 goto error;
3294 }
Michal Vasko0d204592015-10-07 09:50:04 +02003295 if (lyxp_syntax_check(leaf->must[leaf->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003296 goto error;
3297 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003298 } else if (!strcmp(sub->name, "if-feature")) {
3299 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003300 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003301 goto error;
3302 }
3303 r = unres_schema_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value,
3304 LOGLINE(sub));
3305 lydict_remove(module->ctx, value);
3306 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003307 goto error;
3308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003309 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003313
3314error:
3315
Radek Krejci1d82ef62015-08-07 14:44:40 +02003316 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003319}
3320
Michal Vasko0d343d12015-08-24 14:57:36 +02003321/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003322static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003323read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003324 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003325{
Radek Krejci76512572015-08-04 09:47:08 +02003326 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003327 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 struct lyxml_elem *sub, *next;
3329 const char *value;
3330 char *endptr;
3331 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003332 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003333 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003337 llist->nodetype = LYS_LEAFLIST;
3338 llist->prev = (struct lys_node *)llist;
3339 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003340
Michal Vaskoe0c59842015-09-24 13:52:20 +02003341 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3342 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003345
Radek Krejcia9544502015-08-14 08:24:29 +02003346 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003347
3348 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003349 goto error;
3350 }
3351
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003352 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003353 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3354 /* garbage */
3355 lyxml_free_elem(module->ctx, sub);
3356 continue;
3357 }
3358
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003359 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003360 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003361 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003364 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 goto error;
3366 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003367 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 } else if (!strcmp(sub->name, "units")) {
3369 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003370 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003371 goto error;
3372 }
3373 GETVAL(value, sub, "name");
3374 llist->units = lydict_insert(module->ctx, value, strlen(value));
3375 } else if (!strcmp(sub->name, "ordered-by")) {
3376 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003377 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003378 goto error;
3379 }
3380 /* just checking the flags in llist is not sufficient, we would
3381 * allow multiple ordered-by statements with the "system" value
3382 */
3383 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003384
Radek Krejci1574a8d2015-08-03 14:16:52 +02003385 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3387 * state data
3388 */
3389 lyxml_free_elem(module->ctx, sub);
3390 continue;
3391 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 GETVAL(value, sub, "value");
3394 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003395 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003396 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003397 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003399 } /* else system is the default value, so we can ignore it */
3400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 } else if (!strcmp(sub->name, "must")) {
3402 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003403 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003404 } else if (!strcmp(sub->name, "if-feature")) {
3405 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003408 } else if (!strcmp(sub->name, "min-elements")) {
3409 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003410 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 goto error;
3412 }
3413 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 GETVAL(value, sub, "value");
3416 while (isspace(value[0])) {
3417 value++;
3418 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003420 /* convert it to uint32_t */
3421 errno = 0;
3422 endptr = NULL;
3423 val = strtoul(value, &endptr, 10);
3424 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003425 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 goto error;
3427 }
3428 llist->min = (uint32_t) val;
3429 } else if (!strcmp(sub->name, "max-elements")) {
3430 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003431 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 goto error;
3433 }
3434 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 GETVAL(value, sub, "value");
3437 while (isspace(value[0])) {
3438 value++;
3439 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003440
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 /* convert it to uint32_t */
3442 errno = 0;
3443 endptr = NULL;
3444 val = strtoul(value, &endptr, 10);
3445 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003446 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 goto error;
3448 }
3449 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003450 } else if (!strcmp(sub->name, "when")) {
3451 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003452 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003453 goto error;
3454 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003455
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003456 llist->when = read_yin_when(module, sub);
3457 if (!llist->when) {
3458 goto error;
3459 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003460 if (lyxp_syntax_check(llist->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003461 goto error;
3462 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003464 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003466 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003467
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003468 lyxml_free_elem(module->ctx, sub);
3469 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003472 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003473 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 goto error;
3475 }
3476 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003477 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 goto error;
3479 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 /* middle part - process nodes with cardinality of 0..n */
3482 if (c_must) {
3483 llist->must = calloc(c_must, sizeof *llist->must);
3484 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003485 if (c_ftrs) {
3486 llist->features = calloc(c_ftrs, sizeof *llist->features);
3487 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003488
Radek Krejci73adb602015-07-02 18:07:40 +02003489 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003491 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 if (r) {
3493 goto error;
3494 }
Michal Vasko0d204592015-10-07 09:50:04 +02003495 if (lyxp_syntax_check(llist->must[llist->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003496 goto error;
3497 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003498 } else if (!strcmp(sub->name, "if-feature")) {
3499 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003500 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003501 goto error;
3502 }
3503 r = unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
3504 LOGLINE(sub));
3505 lydict_remove(module->ctx, value);
3506 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003507 goto error;
3508 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003510 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003513
3514error:
3515
Radek Krejci1d82ef62015-08-07 14:44:40 +02003516 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003518 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003519}
3520
Michal Vasko0d343d12015-08-24 14:57:36 +02003521/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003522static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003523read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3524 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003525{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003526 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003527 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003529 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003530 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003532 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 char *auxs;
3534 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 /* init */
3537 memset(&root, 0, sizeof root);
3538 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003539
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003541 list->nodetype = LYS_LIST;
3542 list->prev = (struct lys_node *)list;
3543 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003544
Michal Vaskoe0c59842015-09-24 13:52:20 +02003545 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3546 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 goto error;
3548 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003549
Radek Krejcia9544502015-08-14 08:24:29 +02003550 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3551
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 /* process list's specific children */
3553 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003554 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3555 /* garbage */
3556 lyxml_free_elem(module->ctx, sub);
3557 continue;
3558 }
3559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 /* data statements */
3561 if (!strcmp(sub->name, "container") ||
3562 !strcmp(sub->name, "leaf-list") ||
3563 !strcmp(sub->name, "leaf") ||
3564 !strcmp(sub->name, "list") ||
3565 !strcmp(sub->name, "choice") ||
3566 !strcmp(sub->name, "uses") ||
3567 !strcmp(sub->name, "grouping") ||
3568 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003569 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003570 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003572 /* array counters */
3573 } else if (!strcmp(sub->name, "key")) {
3574 /* check cardinality 0..1 */
3575 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003576 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 goto error;
3578 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 /* count the number of keys */
3581 GETVAL(value, sub, "value");
3582 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003583 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 while ((value = strpbrk(value, " \t\n"))) {
3585 list->keys_size++;
3586 while (isspace(*value)) {
3587 value++;
3588 }
3589 }
3590 list->keys_size++;
3591 list->keys = calloc(list->keys_size, sizeof *list->keys);
3592 } else if (!strcmp(sub->name, "unique")) {
3593 c_uniq++;
Michal Vaskof3930de2015-10-22 12:03:59 +02003594 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003595 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 } else if (!strcmp(sub->name, "typedef")) {
3597 c_tpdf++;
3598 } else if (!strcmp(sub->name, "must")) {
3599 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003600 } else if (!strcmp(sub->name, "if-feature")) {
3601 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003603 /* optional stetments */
3604 } else if (!strcmp(sub->name, "ordered-by")) {
3605 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003606 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 goto error;
3608 }
3609 /* just checking the flags in llist is not sufficient, we would
3610 * allow multiple ordered-by statements with the "system" value
3611 */
3612 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003613
Radek Krejci1574a8d2015-08-03 14:16:52 +02003614 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3616 * state data
3617 */
3618 lyxml_free_elem(module->ctx, sub);
3619 continue;
3620 }
Radek Krejci345ad742015-06-03 11:04:18 +02003621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 GETVAL(value, sub, "value");
3623 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003624 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003626 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 goto error;
3628 }
3629 /* else system is the default value, so we can ignore it */
3630 lyxml_free_elem(module->ctx, sub);
3631 } else if (!strcmp(sub->name, "min-elements")) {
3632 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003633 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 goto error;
3635 }
3636 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003638 GETVAL(value, sub, "value");
3639 while (isspace(value[0])) {
3640 value++;
3641 }
Radek Krejci345ad742015-06-03 11:04:18 +02003642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 /* convert it to uint32_t */
3644 errno = 0;
3645 auxs = NULL;
3646 val = strtoul(value, &auxs, 10);
3647 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003648 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 goto error;
3650 }
3651 list->min = (uint32_t) val;
3652 lyxml_free_elem(module->ctx, sub);
3653 } else if (!strcmp(sub->name, "max-elements")) {
3654 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003655 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 goto error;
3657 }
3658 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 GETVAL(value, sub, "value");
3661 while (isspace(value[0])) {
3662 value++;
3663 }
Radek Krejci345ad742015-06-03 11:04:18 +02003664
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003665 /* convert it to uint32_t */
3666 errno = 0;
3667 auxs = NULL;
3668 val = strtoul(value, &auxs, 10);
3669 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003670 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 goto error;
3672 }
3673 list->max = (uint32_t) val;
3674 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003675 } else if (!strcmp(sub->name, "when")) {
3676 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003677 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003678 goto error;
3679 }
3680
3681 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003682 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003683 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003684 goto error;
3685 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003686 if (lyxp_syntax_check(list->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003687 goto error;
3688 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003689 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003690 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003691 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003692 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 }
3694 }
Radek Krejci345ad742015-06-03 11:04:18 +02003695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003697 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003698 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 goto error;
3700 }
3701 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003702 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003703 goto error;
3704 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3707 if (c_tpdf) {
3708 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3709 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003710 if (c_must) {
3711 list->must = calloc(c_must, sizeof *list->must);
3712 }
3713 if (c_ftrs) {
3714 list->features = calloc(c_ftrs, sizeof *list->features);
3715 }
Radek Krejci73adb602015-07-02 18:07:40 +02003716 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003718 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 if (r) {
3721 goto error;
3722 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003723 } else if (!strcmp(sub->name, "if-feature")) {
3724 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003725 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003726 goto error;
3727 }
3728 r = unres_schema_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value,
3729 LOGLINE(sub));
3730 lydict_remove(module->ctx, value);
3731 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003732 goto error;
3733 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003734 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003735 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003736 if (r) {
3737 goto error;
3738 }
Michal Vasko0d204592015-10-07 09:50:04 +02003739 if (lyxp_syntax_check(list->must[list->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003740 goto error;
3741 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
3743 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003744
Radek Krejci10c760e2015-08-14 14:45:43 +02003745 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003746 goto error;
3747 }
3748
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 /* last part - process data nodes */
3750 LY_TREE_FOR_SAFE(root.child, next, sub) {
3751 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003752 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003754 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003756 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003757 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003758 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003760 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003762 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003764 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003765 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003767 } else {
3768 LOGINT;
3769 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003772 goto error;
3773 }
Radek Krejci73adb602015-07-02 18:07:40 +02003774
3775 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003778 if (!key_str) {
3779 /* config false list without a key */
3780 return retval;
3781 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003782 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003783 goto error;
3784 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 /* process unique statements */
3787 if (c_uniq) {
3788 list->unique = calloc(c_uniq, sizeof *list->unique);
3789 }
3790 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Radek Krejci581ce772015-11-10 17:22:40 +01003791 if (fill_yin_unique(module, retval, sub, &list->unique[list->unique_size++], unres)) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003792 goto error;
3793 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 lyxml_free_elem(module->ctx, sub);
3796 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003798 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003799
3800error:
3801
Radek Krejci1d82ef62015-08-07 14:44:40 +02003802 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 while (root.child) {
3804 lyxml_free_elem(module->ctx, root.child);
3805 }
3806 while (uniq.child) {
3807 lyxml_free_elem(module->ctx, uniq.child);
3808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003811}
3812
Michal Vasko0d343d12015-08-24 14:57:36 +02003813/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003814static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003815read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3816 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003817{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003819 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003820 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003821 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 const char *value;
3823 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003824 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 /* init */
3827 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003830 cont->nodetype = LYS_CONTAINER;
3831 cont->prev = (struct lys_node *)cont;
3832 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003833
Michal Vaskoe0c59842015-09-24 13:52:20 +02003834 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG
3835 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 goto error;
3837 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003838
Radek Krejcia9544502015-08-14 08:24:29 +02003839 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 /* process container's specific children */
3842 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003843 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003844 /* garbage */
3845 lyxml_free_elem(module->ctx, sub);
3846 continue;
3847 }
3848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 if (!strcmp(sub->name, "presence")) {
3850 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003851 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 goto error;
3853 }
3854 GETVAL(value, sub, "value");
3855 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003857 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003858 } else if (!strcmp(sub->name, "when")) {
3859 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003860 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003861 goto error;
3862 }
3863
3864 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003865 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003866 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003867 goto error;
3868 }
Michal Vaskofcdac172015-10-07 09:35:05 +02003869 if (lyxp_syntax_check(cont->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003870 goto error;
3871 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003872 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003874 /* data statements */
3875 } else if (!strcmp(sub->name, "container") ||
3876 !strcmp(sub->name, "leaf-list") ||
3877 !strcmp(sub->name, "leaf") ||
3878 !strcmp(sub->name, "list") ||
3879 !strcmp(sub->name, "choice") ||
3880 !strcmp(sub->name, "uses") ||
3881 !strcmp(sub->name, "grouping") ||
3882 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02003883 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02003884 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003886 /* array counters */
3887 } else if (!strcmp(sub->name, "typedef")) {
3888 c_tpdf++;
3889 } else if (!strcmp(sub->name, "must")) {
3890 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003891 } else if (!strcmp(sub->name, "if-feature")) {
3892 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003894 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003896 }
3897 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003898
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003899 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3900 if (c_tpdf) {
3901 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3902 }
3903 if (c_must) {
3904 cont->must = calloc(c_must, sizeof *cont->must);
3905 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003906 if (c_ftrs) {
3907 cont->features = calloc(c_ftrs, sizeof *cont->features);
3908 }
Radek Krejci800af702015-06-02 13:46:01 +02003909
Radek Krejci73adb602015-07-02 18:07:40 +02003910 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003912 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003913 if (r) {
3914 goto error;
3915 }
3916 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003917 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003918 if (r) {
3919 goto error;
3920 }
Michal Vasko0d204592015-10-07 09:50:04 +02003921 if (lyxp_syntax_check(cont->must[cont->must_size-1].expr, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003922 goto error;
3923 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003924 } else if (!strcmp(sub->name, "if-feature")) {
3925 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02003926 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02003927 goto error;
3928 }
3929 r = unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
3930 LOGLINE(sub));
3931 lydict_remove(module->ctx, value);
3932 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003933 goto error;
3934 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003935 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003936 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003937
Radek Krejci10c760e2015-08-14 14:45:43 +02003938 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003939 goto error;
3940 }
3941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003942 /* last part - process data nodes */
3943 LY_TREE_FOR_SAFE(root.child, next, sub) {
3944 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003945 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003946 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003947 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003948 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003949 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003950 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003951 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003952 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003953 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003954 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003956 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003957 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003960 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003962 goto error;
3963 }
Radek Krejci73adb602015-07-02 18:07:40 +02003964
3965 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003966 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003968 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003969
3970error:
3971
Radek Krejci1d82ef62015-08-07 14:44:40 +02003972 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003973 while (root.child) {
3974 lyxml_free_elem(module->ctx, root.child);
3975 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003978}
3979
Michal Vasko0d343d12015-08-24 14:57:36 +02003980/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003981static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003982read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003983 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003984{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003986 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003987 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003988 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003989 int r;
3990 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003991
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003992 /* init */
3993 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003994
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003995 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003996 grp->nodetype = LYS_GROUPING;
3997 grp->prev = (struct lys_node *)grp;
3998 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003999
Michal Vasko71e1aa82015-08-12 12:17:51 +02004000 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004001 goto error;
4002 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004003
Radek Krejcia9544502015-08-14 08:24:29 +02004004 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4005
Radek Krejci1d82ef62015-08-07 14:44:40 +02004006 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004007 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4008 /* garbage */
4009 lyxml_free_elem(module->ctx, sub);
4010 continue;
4011 }
4012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004013 /* data statements */
4014 if (!strcmp(sub->name, "container") ||
4015 !strcmp(sub->name, "leaf-list") ||
4016 !strcmp(sub->name, "leaf") ||
4017 !strcmp(sub->name, "list") ||
4018 !strcmp(sub->name, "choice") ||
4019 !strcmp(sub->name, "uses") ||
4020 !strcmp(sub->name, "grouping") ||
4021 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004022 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004023 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004025 /* array counters */
4026 } else if (!strcmp(sub->name, "typedef")) {
4027 c_tpdf++;
4028 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004029 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004030 goto error;
4031 }
4032 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004034 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4035 if (c_tpdf) {
4036 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
4037 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004038 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004039 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02004040
Radek Krejci73adb602015-07-02 18:07:40 +02004041 if (r) {
4042 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004043 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004044 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004045
Radek Krejci10c760e2015-08-14 14:45:43 +02004046 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004047 goto error;
4048 }
4049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004050 /* last part - process data nodes */
4051 LY_TREE_FOR_SAFE(root.child, next, sub) {
4052 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004053 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004054 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004055 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004056 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004057 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004058 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004059 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004060 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004061 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004063 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004064 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004065 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004066 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004067 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004068 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004069 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004070 goto error;
4071 }
Radek Krejci73adb602015-07-02 18:07:40 +02004072
4073 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004074 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004076 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004077
4078error:
4079
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081 while (root.child) {
4082 lyxml_free_elem(module->ctx, root.child);
4083 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004085 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004086}
4087
Michal Vasko0d343d12015-08-24 14:57:36 +02004088/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004089static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004090read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4091 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004092{
Radek Krejcie0674f82015-06-15 13:58:51 +02004093 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004094 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02004095 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02004096 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004097 int r;
4098 int c_tpdf = 0;
4099
Radek Krejcie0674f82015-06-15 13:58:51 +02004100 /* init */
4101 memset(&root, 0, sizeof root);
4102
Michal Vasko38d01f72015-06-15 09:41:06 +02004103 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02004104 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004105
4106 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02004107 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004108 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02004109 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02004110 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02004111 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02004112 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02004113 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004114 }
4115
Radek Krejci76512572015-08-04 09:47:08 +02004116 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02004117
Radek Krejci6a113852015-07-03 16:04:20 +02004118 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02004119 goto error;
4120 }
4121
Radek Krejcia9544502015-08-14 08:24:29 +02004122 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4123
Michal Vasko38d01f72015-06-15 09:41:06 +02004124 /* data statements */
4125 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004126 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4127 /* garbage */
4128 lyxml_free_elem(module->ctx, sub);
4129 continue;
4130 }
4131
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004133 !strcmp(sub->name, "leaf-list") ||
4134 !strcmp(sub->name, "leaf") ||
4135 !strcmp(sub->name, "list") ||
4136 !strcmp(sub->name, "choice") ||
4137 !strcmp(sub->name, "uses") ||
4138 !strcmp(sub->name, "grouping") ||
4139 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004140 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004141 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004143 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004144 } else if (!strcmp(sub->name, "typedef")) {
4145 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02004146
Michal Vasko38d01f72015-06-15 09:41:06 +02004147 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004148 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004150 }
4151 }
4152
4153 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4154 if (c_tpdf) {
4155 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
4156 }
4157
Radek Krejci73adb602015-07-02 18:07:40 +02004158 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004159 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004160
Radek Krejci73adb602015-07-02 18:07:40 +02004161 if (r) {
4162 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004164 }
4165
Radek Krejci10c760e2015-08-14 14:45:43 +02004166 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004167 goto error;
4168 }
4169
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 /* last part - process data nodes */
4171 LY_TREE_FOR_SAFE(root.child, next, sub) {
4172 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004173 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004174 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004175 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004176 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004177 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004178 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004180 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004181 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004182 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004183 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004184 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004185 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004186 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004187 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004188 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004189 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004190 goto error;
4191 }
Radek Krejci73adb602015-07-02 18:07:40 +02004192
4193 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004194 }
4195
Michal Vasko38d01f72015-06-15 09:41:06 +02004196 return retval;
4197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004198error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004199
Radek Krejci1d82ef62015-08-07 14:44:40 +02004200 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004201 while (root.child) {
4202 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004203 }
4204
4205 return NULL;
4206}
4207
Michal Vasko0d343d12015-08-24 14:57:36 +02004208/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004209static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004210read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4211 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004212{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004213 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004215 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004216 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004217 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004218 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004219 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004220
Michal Vaskoc6551b32015-06-16 10:51:43 +02004221 memset(&root, 0, sizeof root);
4222
Michal Vasko0ea41032015-06-16 08:53:55 +02004223 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004224 notif->nodetype = LYS_NOTIF;
4225 notif->prev = (struct lys_node *)notif;
4226 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004227
Radek Krejci6a113852015-07-03 16:04:20 +02004228 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004229 goto error;
4230 }
4231
Radek Krejcia9544502015-08-14 08:24:29 +02004232 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4233
Michal Vasko0ea41032015-06-16 08:53:55 +02004234 /* process rpc's specific children */
4235 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004236 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4237 /* garbage */
4238 lyxml_free_elem(module->ctx, sub);
4239 continue;
4240 }
4241
Michal Vasko0ea41032015-06-16 08:53:55 +02004242 /* data statements */
4243 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 !strcmp(sub->name, "leaf-list") ||
4245 !strcmp(sub->name, "leaf") ||
4246 !strcmp(sub->name, "list") ||
4247 !strcmp(sub->name, "choice") ||
4248 !strcmp(sub->name, "uses") ||
4249 !strcmp(sub->name, "grouping") ||
4250 !strcmp(sub->name, "anyxml")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004251 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004252 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004255 } else if (!strcmp(sub->name, "typedef")) {
4256 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004257 } else if (!strcmp(sub->name, "if-feature")) {
4258 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004259 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004260 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004261 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004262 }
4263 }
4264
4265 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4266 if (c_tpdf) {
4267 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4268 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004269 if (c_ftrs) {
4270 notif->features = calloc(c_ftrs, sizeof *notif->features);
4271 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004272
Radek Krejci73adb602015-07-02 18:07:40 +02004273 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004274 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004275 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004276
4277 if (r) {
4278 goto error;
4279 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004280 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004281 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004282 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004283 goto error;
4284 }
4285 r = unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
4286 LOGLINE(sub));
4287 lydict_remove(module->ctx, value);
4288 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004289 goto error;
4290 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004291 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004292 }
4293
Radek Krejci10c760e2015-08-14 14:45:43 +02004294 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004295 goto error;
4296 }
4297
Michal Vasko0ea41032015-06-16 08:53:55 +02004298 /* last part - process data nodes */
4299 LY_TREE_FOR_SAFE(root.child, next, sub) {
4300 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004301 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004302 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004303 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004304 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004305 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004306 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004307 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004308 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004309 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004310 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004311 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004312 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004313 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004314 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004315 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004316 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004317 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004318 goto error;
4319 }
Radek Krejci73adb602015-07-02 18:07:40 +02004320
4321 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004322 }
4323
Michal Vasko0ea41032015-06-16 08:53:55 +02004324 return retval;
4325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004327
Radek Krejci1d82ef62015-08-07 14:44:40 +02004328 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004329 while (root.child) {
4330 lyxml_free_elem(module->ctx, root.child);
4331 }
4332
4333 return NULL;
4334}
4335
Michal Vasko0d343d12015-08-24 14:57:36 +02004336/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004337static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004338read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4339 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004340{
Radek Krejcie0674f82015-06-15 13:58:51 +02004341 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004342 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004343 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004344 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004345 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004346 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004347 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004348
Radek Krejcie0674f82015-06-15 13:58:51 +02004349 /* init */
4350 memset(&root, 0, sizeof root);
4351
Michal Vasko38d01f72015-06-15 09:41:06 +02004352 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004353 rpc->nodetype = LYS_RPC;
4354 rpc->prev = (struct lys_node *)rpc;
4355 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004356
Radek Krejci6a113852015-07-03 16:04:20 +02004357 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004358 goto error;
4359 }
4360
Radek Krejcia9544502015-08-14 08:24:29 +02004361 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4362
Michal Vasko38d01f72015-06-15 09:41:06 +02004363 /* process rpc's specific children */
4364 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004365 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4366 /* garbage */
4367 lyxml_free_elem(module->ctx, sub);
4368 continue;
4369 }
4370
Michal Vasko38d01f72015-06-15 09:41:06 +02004371 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004372 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004373 && (rpc->child->nodetype == LYS_INPUT
4374 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004375 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004376 goto error;
4377 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004378 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004379 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004380 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004381 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004382 && (rpc->child->nodetype == LYS_INPUT
4383 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004384 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004385 goto error;
4386 }
Michal Vaskof3930de2015-10-22 12:03:59 +02004387 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004388 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004389
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004391 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004392 lyxml_unlink_elem(module->ctx, sub, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004393 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004394
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004396 } else if (!strcmp(sub->name, "typedef")) {
4397 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004398 } else if (!strcmp(sub->name, "if-feature")) {
4399 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004400 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004401 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004402 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004403 }
4404 }
4405
4406 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4407 if (c_tpdf) {
4408 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4409 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004410 if (c_ftrs) {
4411 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4412 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004413
Radek Krejci73adb602015-07-02 18:07:40 +02004414 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004415 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004416 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004417
4418 if (r) {
4419 goto error;
4420 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004421 } else if (!strcmp(sub->name, "if-feature")) {
4422 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004423 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004424 goto error;
4425 }
4426 r = unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
4427 LOGLINE(sub));
4428 lydict_remove(module->ctx, value);
4429 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004430 goto error;
4431 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004432 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004433 }
4434
Radek Krejci10c760e2015-08-14 14:45:43 +02004435 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004436 goto error;
4437 }
4438
Michal Vasko38d01f72015-06-15 09:41:06 +02004439 /* last part - process data nodes */
4440 LY_TREE_FOR_SAFE(root.child, next, sub) {
4441 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004442 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004443 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004444 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004445 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004446 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004447 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004448 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004449 goto error;
4450 }
Radek Krejci73adb602015-07-02 18:07:40 +02004451
4452 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004453 }
4454
Michal Vasko38d01f72015-06-15 09:41:06 +02004455 return retval;
4456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004458
Radek Krejci1d82ef62015-08-07 14:44:40 +02004459 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004460 while (root.child) {
4461 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004462 }
4463
4464 return NULL;
4465}
4466
Michal Vasko0d343d12015-08-24 14:57:36 +02004467/* logs directly
4468 *
Radek Krejci74705112015-06-05 10:25:44 +02004469 * resolve - referenced grouping should be bounded to the namespace (resolved)
4470 * only when uses does not appear in grouping. In a case of grouping's uses,
4471 * we just get information but we do not apply augment or refine to it.
4472 */
Radek Krejci76512572015-08-04 09:47:08 +02004473static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004474read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004475 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004476{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004478 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004479 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004480 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004481 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004485 uses->nodetype = LYS_USES;
4486 uses->prev = (struct lys_node *)uses;
4487 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004488
Radek Krejcia9544502015-08-14 08:24:29 +02004489 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004491
Michal Vaskoe0c59842015-09-24 13:52:20 +02004492 if (read_yin_common(module, parent, retval, yin, OPT_MODULE
4493 | (parent && (parent->nodetype == LYS_GROUPING) ? 0 : OPT_NACMEXT) | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 goto error;
4495 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004496
Radek Krejcia9544502015-08-14 08:24:29 +02004497 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004500 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004501 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4502 /* garbage */
4503 lyxml_free_elem(module->ctx, sub);
4504 continue;
4505 }
4506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 if (!strcmp(sub->name, "refine")) {
4508 c_ref++;
4509 } else if (!strcmp(sub->name, "augment")) {
4510 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004511 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004512 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004513 } else if (!strcmp(sub->name, "when")) {
4514 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004515 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004516 goto error;
4517 }
4518
4519 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004520 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004521 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004522 goto error;
4523 }
Michal Vaskofcdac172015-10-07 09:35:05 +02004524 if (lyxp_syntax_check(uses->when->cond, LOGLINE(sub))) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004525 goto error;
4526 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004527 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004529 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 }
4532 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 /* process properties with cardinality 0..n */
4535 if (c_ref) {
4536 uses->refine = calloc(c_ref, sizeof *uses->refine);
4537 }
4538 if (c_aug) {
4539 uses->augment = calloc(c_aug, sizeof *uses->augment);
4540 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004541 if (c_ftrs) {
4542 uses->features = calloc(c_ftrs, sizeof *uses->features);
4543 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004544
Radek Krejci10c760e2015-08-14 14:45:43 +02004545 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004546 goto error;
4547 }
4548
Radek Krejcia9544502015-08-14 08:24:29 +02004549 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 if (!strcmp(sub->name, "refine")) {
Michal Vasko0d204592015-10-07 09:50:04 +02004551 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++]);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004552 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004553 goto error;
4554 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004555 } else if (!strcmp(sub->name, "augment")) {
4556 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4557 if (r) {
4558 goto error;
4559 }
4560 } else if (!strcmp(sub->name, "if-feature")) {
4561 GETVAL(value, sub, "name");
Michal Vaskofba15262015-10-21 12:10:28 +02004562 if (!(value = transform_schema2json(module, value, LOGLINE(sub)))) {
Michal Vasko2d851a92015-10-20 16:16:36 +02004563 goto error;
4564 }
4565 r = unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
4566 LOGLINE(sub));
4567 lydict_remove(module->ctx, value);
4568 if (r == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004569 goto error;
4570 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 }
4572 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004573
Michal Vasko0bd29d12015-08-19 11:45:49 +02004574 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004575 goto error;
4576 }
Radek Krejci74705112015-06-05 10:25:44 +02004577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 if (resolve) {
4579 /* inherit config flag */
4580 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004581 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004582 } else {
4583 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004584 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 }
4586 }
Radek Krejcib388c152015-06-04 17:03:03 +02004587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004589
4590error:
4591
Radek Krejci1d82ef62015-08-07 14:44:40 +02004592 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004594 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004595}
4596
Michal Vasko0d343d12015-08-24 14:57:36 +02004597/* logs directly
4598 *
4599 * common code for yin_read_module() and yin_read_submodule()
4600 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004602read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004603{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004604 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004605 struct lys_submodule *submodule = (struct lys_submodule *)module;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004606 struct lyxml_elem *next, *child, *child2, root, grps, augs;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004608 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004609 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004611 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004612 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 +02004613
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 /* init */
4615 memset(&root, 0, sizeof root);
4616 memset(&grps, 0, sizeof grps);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004617 memset(&augs, 0, sizeof augs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 /*
4620 * in the first run, we process elements with cardinality of 1 or 0..1 and
4621 * count elements with cardinality 0..n. Data elements (choices, containers,
4622 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4623 * need have all top-level and groupings already prepared at that time. In
4624 * the middle loop, we process other elements with carinality of 0..n since
4625 * we need to allocate arrays to store them.
4626 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004627 LY_TREE_FOR_SAFE(yin->child, next, child) {
4628 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004629 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004630 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004631 continue;
4632 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004633
Radek Krejci1d82ef62015-08-07 14:44:40 +02004634 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004636 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637 goto error;
4638 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 lyxml_free_elem(ctx, child);
4642 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004643 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004644 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 goto error;
4646 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004647 GETVAL(value, child, "value");
4648 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 goto error;
4650 }
4651 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004652 lyxml_free_elem(ctx, child);
4653 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004655 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 goto error;
4657 }
4658 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004659 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004660 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004661 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 }
4663 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004664 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 goto error;
4666 }
Radek Krejcif3886932015-06-04 17:36:06 +02004667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004669 if (!child->child) {
4670 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004672 } else if (strcmp(child->child->name, "prefix")) {
4673 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004674 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004675 } else if (child->child->next) {
4676 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 goto error;
4678 }
4679 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004681 /* check here differs from a generic prefix check, since this prefix
4682 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004683 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004684 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 goto error;
4686 }
4687 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004688
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004691
4692 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004693 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004695 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004696 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004697 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004699 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004703 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004704 c_aug++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004705 /* keep augments separated, processed last */
Michal Vaskof3930de2015-10-22 12:03:59 +02004706 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vasko2f7925f2015-10-21 15:06:56 +02004707 lyxml_add_child(module->ctx, &augs, child);
4708
Radek Krejci1d82ef62015-08-07 14:44:40 +02004709 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004710 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004711 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004712 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004715 } else if (!strcmp(child->name, "container") ||
4716 !strcmp(child->name, "leaf-list") ||
4717 !strcmp(child->name, "leaf") ||
4718 !strcmp(child->name, "list") ||
4719 !strcmp(child->name, "choice") ||
4720 !strcmp(child->name, "uses") ||
Michal Vasko7ffc3052015-10-21 15:05:56 +02004721 !strcmp(child->name, "anyxml") ||
4722 !strcmp(child->name, "rpc") ||
4723 !strcmp(child->name, "notification")) {
Michal Vaskof3930de2015-10-22 12:03:59 +02004724 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004725 lyxml_add_child(module->ctx, &root, child);
Michal Vasko7ffc3052015-10-21 15:05:56 +02004726
Radek Krejci1d82ef62015-08-07 14:44:40 +02004727 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004728 /* keep groupings separated and process them before other data statements */
Michal Vaskof3930de2015-10-22 12:03:59 +02004729 lyxml_unlink_elem(module->ctx, child, 2);
Michal Vaskof8879c22015-08-21 09:07:36 +02004730 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004733 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004735 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 goto error;
4737 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004738 module->dsc = read_yin_subnode(ctx, child, "text");
4739 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 if (!module->dsc) {
4741 goto error;
4742 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004745 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 goto error;
4747 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 module->ref = read_yin_subnode(ctx, child, "text");
4749 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 if (!module->ref) {
4751 goto error;
4752 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004753 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004755 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 goto error;
4757 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004758 module->org = read_yin_subnode(ctx, child, "text");
4759 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004760 if (!module->org) {
4761 goto error;
4762 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004763 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004764 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004765 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 goto error;
4767 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004768 module->contact = read_yin_subnode(ctx, child, "text");
4769 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 if (!module->contact) {
4771 goto error;
4772 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004773 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 /* TODO: support YANG 1.1 ? */
4775 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004776 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 goto error;
4778 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004779 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004781 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 goto error;
4783 }
4784 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004785 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004786
Radek Krejci1d82ef62015-08-07 14:44:40 +02004787 } else if (!strcmp(child->name, "extension")) {
4788 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004789
Radek Krejci3d468122015-10-02 13:36:12 +02004790 /* we have the following supported (hardcoded) extensions: */
4791 /* ietf-netconf's get-filter-element-attributes */
4792 if (!strcmp(module->ns, LY_NSNC) &&
4793 !strcmp(value, "get-filter-element-attributes")) {
4794 LOGDBG("NETCONF filter extension found");
4795 /* NACM's default-deny-write and default-deny-all */
4796 } else if (!strcmp(module->ns, LY_NSNACM) &&
4797 (!strcmp(value, "default-deny-write") || !strcmp(value, "default-deny-all"))) {
4798 LOGDBG("NACM extension found");
4799 /* other extensions are not supported, so inform about such an extension */
4800 } else {
Radek Krejci6764bb32015-07-03 15:16:04 +02004801 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004802 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004803 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004805 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004806 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004807 }
4808 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 if (!submodule) {
4811 /* check for mandatory statements */
4812 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004813 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004814 goto error;
4815 }
4816 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004817 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 goto error;
4819 }
4820 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 /* allocate arrays for elements with cardinality of 0..n */
4823 if (c_imp) {
4824 module->imp = calloc(c_imp, sizeof *module->imp);
4825 }
4826 if (c_rev) {
4827 module->rev = calloc(c_rev, sizeof *module->rev);
4828 }
4829 if (c_tpdf) {
4830 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4831 }
4832 if (c_ident) {
4833 module->ident = calloc(c_ident, sizeof *module->ident);
4834 }
4835 if (c_inc) {
4836 module->inc = calloc(c_inc, sizeof *module->inc);
4837 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004838 if (c_aug) {
4839 module->augment = calloc(c_aug, sizeof *module->augment);
4840 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004841 if (c_ftrs) {
4842 module->features = calloc(c_ftrs, sizeof *module->features);
4843 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004844 if (c_dev) {
4845 module->deviation = calloc(c_dev, sizeof *module->deviation);
4846 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004847
Michal Vasko2f7925f2015-10-21 15:06:56 +02004848 /* middle part - process nodes with cardinality of 0..n except the data nodes and augments */
4849 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004850 if (!strcmp(child->name, "import")) {
4851 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 module->imp_size++;
4853 if (r) {
4854 goto error;
4855 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 /* check duplicities in imported modules */
4858 for (i = 0; i < module->imp_size - 1; i++) {
4859 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004860 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 goto error;
4862 }
4863 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004864
Radek Krejci1d82ef62015-08-07 14:44:40 +02004865 } else if (!strcmp(child->name, "include")) {
4866 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004867 module->inc_size++;
4868 if (r) {
4869 goto error;
4870 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 /* check duplications in include submodules */
4873 for (i = 0; i < module->inc_size - 1; i++) {
4874 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004875 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 module->inc[i].submodule->name);
4877 goto error;
4878 }
4879 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004880
Radek Krejci1d82ef62015-08-07 14:44:40 +02004881 } else if (!strcmp(child->name, "revision")) {
4882 GETVAL(value, child, "date");
4883 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 goto error;
4885 }
4886 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4887 /* check uniqueness of the revision date - not required by RFC */
4888 for (i = 0; i < module->rev_size; i++) {
4889 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004890 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004891 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 }
4893 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004894
Radek Krejci1d82ef62015-08-07 14:44:40 +02004895 LY_TREE_FOR(child->child, child2) {
4896 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004898 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004899 goto error;
4900 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004901 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004902 if (!module->rev[module->rev_size].dsc) {
4903 goto error;
4904 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004905 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004907 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 goto error;
4909 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004910 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 if (!module->rev[module->rev_size].ref) {
4912 goto error;
4913 }
4914 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004915 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 goto error;
4917 }
4918 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 /* keep the latest revision at position 0 */
4921 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4922 /* switch their position */
4923 value = strdup(module->rev[0].date);
4924 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4925 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4926 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4929 value = module->rev[0].dsc;
4930 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4931 module->rev[module->rev_size].dsc = value;
4932 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004934 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4935 value = module->rev[0].ref;
4936 module->rev[0].ref = module->rev[module->rev_size].ref;
4937 module->rev[module->rev_size].ref = value;
4938 }
4939 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004940
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004941 module->rev_size++;
Michal Vasko2f7925f2015-10-21 15:06:56 +02004942
Radek Krejci1d82ef62015-08-07 14:44:40 +02004943 } else if (!strcmp(child->name, "typedef")) {
4944 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004945 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 if (r) {
4948 goto error;
4949 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004950
Radek Krejci1d82ef62015-08-07 14:44:40 +02004951 } else if (!strcmp(child->name, "identity")) {
4952 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 if (r) {
4956 goto error;
4957 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004958
Radek Krejci1d82ef62015-08-07 14:44:40 +02004959 } else if (!strcmp(child->name, "feature")) {
4960 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004961 module->features_size++;
4962
4963 if (r) {
4964 goto error;
4965 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004966
Radek Krejci1d82ef62015-08-07 14:44:40 +02004967 } else if (!strcmp(child->name, "deviation")) {
4968 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004969 module->deviation_size++;
4970
4971 if (r) {
4972 goto error;
4973 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02004974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004977
Radek Krejcif5be10f2015-06-16 13:29:36 +02004978 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 * refer to them
4980 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004981 LY_TREE_FOR_SAFE(grps.child, next, child) {
4982 node = read_yin_grouping(module, NULL, child, 0, unres);
4983 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004984 goto error;
4985 }
Radek Krejci74705112015-06-05 10:25:44 +02004986
Radek Krejci1d82ef62015-08-07 14:44:40 +02004987 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004988 }
Radek Krejci74705112015-06-05 10:25:44 +02004989
Radek Krejcif5be10f2015-06-16 13:29:36 +02004990 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004991 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004992
Radek Krejci1d82ef62015-08-07 14:44:40 +02004993 if (!strcmp(child->name, "container")) {
4994 node = read_yin_container(module, NULL, child, 1, unres);
4995 } else if (!strcmp(child->name, "leaf-list")) {
4996 node = read_yin_leaflist(module, NULL, child, 1, unres);
4997 } else if (!strcmp(child->name, "leaf")) {
4998 node = read_yin_leaf(module, NULL, child, 1, unres);
4999 } else if (!strcmp(child->name, "list")) {
5000 node = read_yin_list(module, NULL, child, 1, unres);
5001 } else if (!strcmp(child->name, "choice")) {
5002 node = read_yin_choice(module, NULL, child, 1, unres);
5003 } else if (!strcmp(child->name, "uses")) {
5004 node = read_yin_uses(module, NULL, child, 1, unres);
5005 } else if (!strcmp(child->name, "anyxml")) {
5006 node = read_yin_anyxml(module, NULL, child, 1, unres);
Michal Vasko7ffc3052015-10-21 15:05:56 +02005007 } else if (!strcmp(child->name, "rpc")) {
5008 node = read_yin_rpc(module, NULL, child, 0, unres);
5009 } else if (!strcmp(child->name, "notification")) {
5010 node = read_yin_notif(module, NULL, child, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005012 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 goto error;
5014 }
Radek Krejci25d782a2015-05-22 15:03:23 +02005015
Radek Krejci1d82ef62015-08-07 14:44:40 +02005016 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005017 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02005018
Michal Vasko2f7925f2015-10-21 15:06:56 +02005019 /* ... and finally augments (last, so we can augment our data, for instance) */
5020 LY_TREE_FOR_SAFE(augs.child, next, child) {
5021 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
5022 module->augment_size++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02005023
Michal Vasko2f7925f2015-10-21 15:06:56 +02005024 if (r) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02005025 goto error;
5026 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02005027 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02005028 }
5029
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005030 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02005031
5032error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005033 /* cleanup */
5034 while (root.child) {
5035 lyxml_free_elem(module->ctx, root.child);
5036 }
5037 while (grps.child) {
5038 lyxml_free_elem(module->ctx, grps.child);
5039 }
Michal Vasko2f7925f2015-10-21 15:06:56 +02005040 while (augs.child) {
5041 lyxml_free_elem(module->ctx, augs.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02005042 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005043
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005044 free(unres->item);
5045 unres->item = NULL;
5046 free(unres->type);
5047 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02005048 free(unres->str_snode);
5049 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02005050#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005051 free(unres->line);
5052 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02005053#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005054 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02005055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005056 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02005057}
5058
Michal Vasko0d343d12015-08-24 14:57:36 +02005059/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005060struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02005061yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005062{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005063 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005064 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005065 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02005066
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005067 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02005068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005069 yin = lyxml_read(module->ctx, data, 0);
5070 if (!yin) {
5071 return NULL;
5072 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005074 /* check root element */
5075 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005076 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005077 goto error;
5078 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005080 GETVAL(value, yin, "name");
5081 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
5082 goto error;
5083 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005084
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005085 submodule = calloc(1, sizeof *submodule);
5086 if (!submodule) {
5087 LOGMEM;
5088 goto error;
5089 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005091 submodule->ctx = module->ctx;
5092 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
5093 submodule->type = 1;
5094 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005095 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005096
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005097 LOGVRB("Reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02005098 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005099 goto error;
5100 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005102 /* cleanup */
5103 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02005104
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005105 LOGVRB("Submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02005106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005107 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02005108
5109error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005110 /* cleanup */
5111 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005112 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005113
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005114 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02005115}
5116
Michal Vasko0d343d12015-08-24 14:57:36 +02005117/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02005118struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02005119yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02005120{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005121 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02005122 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005123 const char *value;
5124 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02005125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005126 yin = lyxml_read(ctx, data, 0);
5127 if (!yin) {
5128 return NULL;
5129 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005131 /* check root element */
5132 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02005133 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005134 goto error;
5135 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005137 GETVAL(value, yin, "name");
5138 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
5139 goto error;
5140 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005142 module = calloc(1, sizeof *module);
5143 if (!module) {
5144 LOGMEM;
5145 goto error;
5146 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005148 module->ctx = ctx;
5149 module->name = lydict_insert(ctx, value, strlen(value));
5150 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02005151 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02005152
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005153 LOGVRB("Reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02005154 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005155 goto error;
5156 }
Radek Krejciefaeba32015-05-27 14:30:57 +02005157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005158 /* add to the context's list of modules */
5159 if (ctx->models.used == ctx->models.size) {
Michal Vaskof2e1a992015-11-09 09:54:47 +01005160 newlist = realloc(ctx->models.list, (2 * ctx->models.size) * sizeof *newlist);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005161 if (!newlist) {
5162 LOGMEM;
5163 goto error;
5164 }
5165 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
5166 newlist[i] = NULL;
5167 }
5168 ctx->models.size *= 2;
5169 ctx->models.list = newlist;
5170 }
5171 for (i = 0; ctx->models.list[i]; i++) {
5172 /* check name (name/revision) and namespace uniqueness */
5173 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02005174 if (ctx->models.list[i]->rev_size == module->rev_size) {
5175 /* both have the same number of revisions */
5176 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
5177 /* both have the same revision -> we already have the same module */
5178 /* so free the new one and update the old one's implement flag if needed */
5179 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005180 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02005181 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02005182
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005183 LOGVRB("Module %s already in context", ctx->models.list[i]->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02005184
5185 if (implement && !ctx->models.list[i]->implemented) {
5186 lyp_set_implemented(ctx->models.list[i]);
5187 }
5188 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005189 }
5190 }
Radek Krejcif647e612015-07-30 11:36:07 +02005191 /* else (both elses) keep searching, for now the caller is just adding
5192 * another revision of an already present schema
5193 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005194 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
5195 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
5196 ctx->models.list[i]->name, module->name, module->ns);
5197 goto error;
5198 }
5199 }
5200 ctx->models.list[i] = module;
5201 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005202 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005204 /* cleanup */
5205 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005206
Michal Vaskoe0b627e2015-10-21 15:08:32 +02005207 LOGVRB("Module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005209 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005210
5211error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005212 /* cleanup */
5213 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02005214 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005216 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005217}