blob: 980fd69240fd4866a36efe3a41c9e772cc740682 [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"
36#include "dict.h"
37#include "parser.h"
Radek Krejci998a0b82015-08-17 13:14:36 +020038#include "resolve.h"
39#include "tree_internal.h"
40#include "xml.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020041
Radek Krejcice7fb782015-05-29 16:52:34 +020042enum LY_IDENT {
Radek Krejci994b6f62015-06-18 16:47:27 +020043 LY_IDENT_SIMPLE, /* only syntax rules */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020044 LY_IDENT_FEATURE,
45 LY_IDENT_IDENTITY,
46 LY_IDENT_TYPE,
47 LY_IDENT_NODE,
Radek Krejci994b6f62015-06-18 16:47:27 +020048 LY_IDENT_NAME, /* uniqueness across the siblings */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020049 LY_IDENT_PREFIX
Radek Krejcice7fb782015-05-29 16:52:34 +020050};
51
Radek Krejciefdd0ce2015-05-26 16:48:29 +020052#define LY_NSYIN "urn:ietf:params:xml:ns:yang:yin:1"
Radek Krejci6764bb32015-07-03 15:16:04 +020053#define LY_NSNACM "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
Radek Krejcida04f4a2015-05-21 12:54:09 +020054
Radek Krejcice7fb782015-05-29 16:52:34 +020055#define GETVAL(value, node, arg) \
56 value = lyxml_get_attr(node, arg, NULL); \
57 if (!value) { \
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020058 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
Radek Krejcice7fb782015-05-29 16:52:34 +020059 goto error; \
60 }
61
Radek Krejcib388c152015-06-04 17:03:03 +020062#define OPT_IDENT 0x01
63#define OPT_CONFIG 0x02
64#define OPT_MODULE 0x04
65#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020066#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020067static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020068
Radek Krejcib8048692015-08-05 13:36:34 +020069static 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 +020070 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020071static 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 +020072 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020073static 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 +020074 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020075static 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 +020076 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020077static 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 +020078 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020079static 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 +020080 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020081static 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 +020082 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020083static 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 +020084 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020085static 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 +020086 int resolve, struct unres_schema *unres);
87static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020088
Michal Vasko0d343d12015-08-24 14:57:36 +020089/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020090static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020091dup_typedef_check(const char *type, struct lys_tpdf *tpdf, int size)
Radek Krejcieac35532015-05-31 19:09:15 +020092{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020093 int i;
Radek Krejcieac35532015-05-31 19:09:15 +020094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020095 for (i = 0; i < size; i++) {
96 if (!strcmp(type, tpdf[i].name)) {
97 /* name collision */
98 return EXIT_FAILURE;
99 }
100 }
Radek Krejcieac35532015-05-31 19:09:15 +0200101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200102 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200103}
104
Michal Vasko0d343d12015-08-24 14:57:36 +0200105/* does not log */
Radek Krejcib05774c2015-06-18 13:52:59 +0200106static int
Radek Krejcib8048692015-08-05 13:36:34 +0200107dup_feature_check(const char *id, struct lys_module *module)
Radek Krejcib05774c2015-06-18 13:52:59 +0200108{
109 int i;
110
111 for (i = 0; i < module->features_size; i++) {
112 if (!strcmp(id, module->features[i].name)) {
113 return EXIT_FAILURE;
114 }
115 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200116
117 return EXIT_SUCCESS;
Radek Krejcib05774c2015-06-18 13:52:59 +0200118}
119
Michal Vasko0d343d12015-08-24 14:57:36 +0200120/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200121static int
Radek Krejcib8048692015-08-05 13:36:34 +0200122dup_prefix_check(const char *prefix, struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200123{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200124 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200126 if (!module->type && module->prefix && !strcmp(module->prefix, prefix)) {
127 return EXIT_FAILURE;
128 }
129 for (i = 0; i < module->imp_size; i++) {
130 if (!strcmp(module->imp[i].prefix, prefix)) {
131 return EXIT_FAILURE;
132 }
133 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200135 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200136}
137
Michal Vasko0d343d12015-08-24 14:57:36 +0200138/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200139static int
140check_identifier(const char *id, enum LY_IDENT type, unsigned int line,
Radek Krejcib8048692015-08-05 13:36:34 +0200141 struct lys_module *module, struct lys_node *parent)
Radek Krejcice7fb782015-05-29 16:52:34 +0200142{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200143 int i;
144 int size;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200145 struct lys_tpdf *tpdf;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200146 struct lys_node *node;
Radek Krejcice7fb782015-05-29 16:52:34 +0200147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200148 assert(id);
Radek Krejcice7fb782015-05-29 16:52:34 +0200149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200150 /* check id syntax */
151 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200152 LOGVAL(LYE_INID, line, id, "invalid start character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200153 return EXIT_FAILURE;
154 }
155 for (i = 1; id[i]; i++) {
156 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
157 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200158 LOGVAL(LYE_INID, line, id, "invalid character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200159 return EXIT_FAILURE;
160 }
161 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200163 if (i > 64) {
164 LOGWRN("Identifier \"%s\" is long, you should use something shorter.", id);
165 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200167 switch (type) {
168 case LY_IDENT_NAME:
169 /* check uniqueness of the node within its siblings */
170 if (!parent) {
171 break;
172 }
Radek Krejcib4cf2022015-06-03 14:40:05 +0200173
Radek Krejci1d82ef62015-08-07 14:44:40 +0200174 LY_TREE_FOR(parent->child, node) {
175 if (node->name == id) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200176 LOGVAL(LYE_INID, line, id, "name duplication");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200177 return EXIT_FAILURE;
178 }
179 }
180 break;
181 case LY_IDENT_TYPE:
182 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200183
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200184 /* check collision with the built-in types */
185 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
186 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
187 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
188 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
189 !strcmp(id, "int8") || !strcmp(id, "int16") ||
190 !strcmp(id, "int32") || !strcmp(id, "int64") ||
191 !strcmp(id, "leafref") || !strcmp(id, "string") ||
192 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
193 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200194 LOGVAL(LYE_SPEC, line, "Typedef name duplicates built-in type.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200195 return EXIT_FAILURE;
196 }
Radek Krejcieac35532015-05-31 19:09:15 +0200197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200198 /* check locally scoped typedefs (avoid name shadowing) */
199 for (; parent; parent = parent->parent) {
200 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200201 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +0200202 size = ((struct lys_node_container *)parent)->tpdf_size;
203 tpdf = ((struct lys_node_container *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200204 break;
Radek Krejci76512572015-08-04 09:47:08 +0200205 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +0200206 size = ((struct lys_node_list *)parent)->tpdf_size;
207 tpdf = ((struct lys_node_list *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200208 break;
Radek Krejci76512572015-08-04 09:47:08 +0200209 case LYS_GROUPING:
Radek Krejcib8048692015-08-05 13:36:34 +0200210 size = ((struct lys_node_grp *)parent)->tpdf_size;
211 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200212 break;
213 default:
214 continue;
215 }
Radek Krejcieac35532015-05-31 19:09:15 +0200216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200217 if (dup_typedef_check(id, tpdf, size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200218 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200219 return EXIT_FAILURE;
220 }
221 }
Radek Krejcieac35532015-05-31 19:09:15 +0200222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200223 /* check top-level names */
224 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200225 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200226 return EXIT_FAILURE;
227 }
Radek Krejcieac35532015-05-31 19:09:15 +0200228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200229 /* check submodule's top-level names */
230 for (i = 0; i < module->inc_size; i++) {
231 if (dup_typedef_check(id, module->inc[i].submodule->tpdf, module->inc[i].submodule->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200232 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200233 return EXIT_FAILURE;
234 }
235 }
Radek Krejcieac35532015-05-31 19:09:15 +0200236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200237 /* check top-level names in the main module */
238 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +0200239 if (dup_typedef_check(id, ((struct lys_submodule *)module)->belongsto->tpdf,
240 ((struct lys_submodule *)module)->belongsto->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200241 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200242 return EXIT_FAILURE;
243 }
244 }
Radek Krejcieac35532015-05-31 19:09:15 +0200245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200246 break;
247 case LY_IDENT_PREFIX:
248 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200250 if (module->type) {
251 /* go to the main module */
Radek Krejcib8048692015-08-05 13:36:34 +0200252 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200253 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200255 /* check the main module itself */
256 if (dup_prefix_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200257 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200258 return EXIT_FAILURE;
259 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200261 /* and all its submodules */
262 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200263 if (dup_prefix_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200264 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200265 return EXIT_FAILURE;
266 }
267 }
268 break;
Radek Krejcib05774c2015-06-18 13:52:59 +0200269 case LY_IDENT_FEATURE:
270 assert(module);
271
272 /* check feature name uniqness*/
Radek Krejci49babf32015-06-18 13:56:17 +0200273 /* check features in the current module */
Radek Krejcib05774c2015-06-18 13:52:59 +0200274 if (dup_feature_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200275 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200276 return EXIT_FAILURE;
277 }
278
279 /* and all its submodules */
280 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200281 if (dup_feature_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200282 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200283 return EXIT_FAILURE;
284 }
285 }
286 break;
287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200288 default:
289 /* no check required */
290 break;
291 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200293 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200294}
295
Michal Vasko0d343d12015-08-24 14:57:36 +0200296/* does not log */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200297static int
Radek Krejci1d82ef62015-08-07 14:44:40 +0200298check_mandatory(struct lys_node *node)
Radek Krejci3de29a72015-06-16 15:23:03 +0200299{
Radek Krejci76512572015-08-04 09:47:08 +0200300 struct lys_node *child;
Radek Krejci3de29a72015-06-16 15:23:03 +0200301
Radek Krejci1d82ef62015-08-07 14:44:40 +0200302 assert(node);
Radek Krejci3de29a72015-06-16 15:23:03 +0200303
Radek Krejci1d82ef62015-08-07 14:44:40 +0200304 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci3de29a72015-06-16 15:23:03 +0200305 return EXIT_FAILURE;
306 }
307
Radek Krejci1d82ef62015-08-07 14:44:40 +0200308 if (node->nodetype == LYS_CASE || node->nodetype == LYS_CHOICE) {
309 LY_TREE_FOR(node->child, child) {
Radek Krejcifd0bb0a2015-06-18 13:18:24 +0200310 if (check_mandatory(child)) {
311 return EXIT_FAILURE;
312 }
Radek Krejci3de29a72015-06-16 15:23:03 +0200313 }
314 }
315
316 return EXIT_SUCCESS;
317}
318
Michal Vasko0d343d12015-08-24 14:57:36 +0200319/* logs directly */
Radek Krejci3de29a72015-06-16 15:23:03 +0200320static int
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321check_date(const char *date, unsigned int line)
Radek Krejcice7fb782015-05-29 16:52:34 +0200322{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200323 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200325 assert(date);
Radek Krejcice7fb782015-05-29 16:52:34 +0200326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200327 if (strlen(date) != LY_REV_SIZE - 1) {
328 goto error;
329 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200330
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200331 for (i = 0; i < LY_REV_SIZE - 1; i++) {
332 if (i == 4 || i == 7) {
333 if (date[i] != '-') {
334 goto error;
335 }
336 } else if (!isdigit(date[i])) {
337 goto error;
338 }
339 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200342
343error:
344
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200345 LOGVAL(LYE_INDATE, line, date);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 return EXIT_FAILURE;
Radek Krejcice7fb782015-05-29 16:52:34 +0200347}
348
Michal Vasko0d343d12015-08-24 14:57:36 +0200349/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200350static const char *
351read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200352{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200353 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200355 /* there should be <text> child */
356 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
357 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
358 } else if (node->child->content) {
359 len = strlen(node->child->content);
360 return lydict_insert(ctx, node->child->content, len);
361 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200362
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200363 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200364 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200365}
366
Michal Vasko0d343d12015-08-24 14:57:36 +0200367/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200368static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200369fill_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 +0200370{
Radek Krejci73adb602015-07-02 18:07:40 +0200371 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200372 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200373
Michal Vasko4cfcd252015-08-03 14:31:10 +0200374 GETVAL(value, yin, "name");
375 ident->name = lydict_insert(module->ctx, value, 0);
376
Radek Krejci76512572015-08-04 09:47:08 +0200377 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200378 return EXIT_FAILURE;
379 }
Radek Krejci04581c62015-05-22 21:24:00 +0200380
Radek Krejci73adb602015-07-02 18:07:40 +0200381 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200382 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
383 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200384 continue;
385 }
386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200387 if (!strcmp(node->name, "base")) {
388 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200389 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200390 return EXIT_FAILURE;
391 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200392 GETVAL(value, node, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200393 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200394 return EXIT_FAILURE;
395 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200396 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200397 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398 return EXIT_FAILURE;
399 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200400 }
Radek Krejci04581c62015-05-22 21:24:00 +0200401
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200402error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200403 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200404}
405
Michal Vasko0d343d12015-08-24 14:57:36 +0200406/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200407static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200408read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200409{
Radek Krejci73adb602015-07-02 18:07:40 +0200410 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200411 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200412
Radek Krejci73adb602015-07-02 18:07:40 +0200413 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200414 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
415 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200416 continue;
417 }
418
Radek Krejci41726f92015-06-19 13:11:05 +0200419 if (!strcmp(child->name, "description")) {
420 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200421 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200422 return EXIT_FAILURE;
423 }
424 restr->dsc = read_yin_subnode(ctx, child, "text");
425 if (!restr->dsc) {
426 return EXIT_FAILURE;
427 }
428 } else if (!strcmp(child->name, "reference")) {
429 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200430 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200431 return EXIT_FAILURE;
432 }
433 restr->ref = read_yin_subnode(ctx, child, "text");
434 if (!restr->ref) {
435 return EXIT_FAILURE;
436 }
437 } else if (!strcmp(child->name, "error-app-tag")) {
438 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200439 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200440 return EXIT_FAILURE;
441 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200442 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200443 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200444 } else if (!strcmp(child->name, "error-message")) {
445 if (restr->emsg) {
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 }
449 restr->emsg = read_yin_subnode(ctx, child, "value");
450 if (!restr->emsg) {
451 return EXIT_FAILURE;
452 }
453 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200454 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200455 return EXIT_FAILURE;
456 }
Radek Krejci41726f92015-06-19 13:11:05 +0200457 }
458
459 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200460
461error:
462 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200463}
464
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200465/* logs directly */
Radek Krejci41726f92015-06-19 13:11:05 +0200466static int
Radek Krejcib8048692015-08-05 13:36:34 +0200467fill_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 +0200468 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200469{
Michal Vasko69068852015-07-13 14:34:31 +0200470#define REGEX_ERR_LEN 128
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200471 const char *value, *delim, *name, *err_ptr;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200472 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200473 struct lys_restr **restr;
474 struct lys_type_bit bit;
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200475 pcre *precomp;
476 int i, j, rc, err_offset;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200478 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200479
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200480 GETVAL(value, yin, "name");
481
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200482 delim = strchr(value, ':');
483 if (delim) {
484 type->prefix = lydict_insert(module->ctx, value, delim - value);
485 delim++;
486 value += delim-value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200487 }
Radek Krejci667b97f2015-05-25 15:03:30 +0200488
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200489 rc = resolve_superior_type(value, type->prefix, module, parent, &type->der);
490 if (rc) {
491 if (rc == EXIT_FAILURE) {
492 /* HACK for unres */
493 type->der = (struct lys_tpdf *)parent;
Michal Vasko0bd29d12015-08-19 11:45:49 +0200494 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200495 }
496 if (rc == -1) {
497 goto error;
498 }
499
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200500 return EXIT_SUCCESS;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200501 }
502 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200504 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200505 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200506 /* RFC 6020 9.7.4 - bit */
507
508 /* get bit specifications, at least one must be present */
509 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200510 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
511 /* garbage */
512 lyxml_free_elem(module->ctx, node);
513 continue;
514 }
515
Radek Krejci994b6f62015-06-18 16:47:27 +0200516 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200517 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200518 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200519 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200520 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200521 }
522 }
Radek Krejciac781922015-07-09 15:35:14 +0200523 if (!type->der->type.der && !type->info.bits.count) {
524 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200525 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200526 goto error;
527 }
Radek Krejciac781922015-07-09 15:35:14 +0200528 if (type->der->type.der && type->info.bits.count) {
529 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200530 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200531 goto error;
532 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200533
534 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200535 p = 0;
536 i = -1;
537 LY_TREE_FOR(yin->child, next) {
538 i++;
539
540 GETVAL(value, next, "name");
541 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200542 goto error;
543 }
544 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200545 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200546 type->info.bits.count = i + 1;
547 goto error;
548 }
549
550 /* check the name uniqueness */
551 for (j = 0; j < i; j++) {
552 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200553 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200554 type->info.bits.count = i + 1;
555 goto error;
556 }
557 }
558
Radek Krejci0d70c372015-07-02 16:23:10 +0200559 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200560 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200561 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
562 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200563 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200564 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200565
Radek Krejci0d70c372015-07-02 16:23:10 +0200566 if (!strcmp(node->name, "position")) {
567 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200568 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200569
570 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200571 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200572 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200573 type->info.bits.count = i + 1;
574 goto error;
575 }
576 type->info.bits.bit[i].pos = (uint32_t)p_;
577
578 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200579 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 p = type->info.bits.bit[i].pos;
581 p++;
582 } else {
583 /* check that the value is unique */
584 for (j = 0; j < i; j++) {
585 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200586 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 +0200587 type->info.bits.count = i + 1;
588 goto error;
589 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200590 }
591 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200592 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200593 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200594 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200595 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200596 }
597 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200598 /* assign value automatically */
599 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200600 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200601 type->info.bits.count = i + 1;
602 goto error;
603 }
604 type->info.bits.bit[i].pos = (uint32_t)p;
605 p++;
606 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200607
608 /* keep them ordered by position */
609 j = i;
610 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
611 /* switch them */
612 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
613 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
614 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
615 j--;
616 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200617 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200619
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200620 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200621 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200622 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200623 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
624 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200625 continue;
626 }
627
Radek Krejcif9401c32015-06-26 16:47:36 +0200628 if (!strcmp(node->name, "range")) {
629 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200630 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200631 goto error;
632 }
633
634 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200635 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200636 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200637 goto error;
638 }
639 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
640 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
641
642 /* get possible substatements */
643 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
644 goto error;
645 }
646 } else if (!strcmp(node->name, "fraction-digits")) {
647 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200648 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200649 goto error;
650 }
651 GETVAL(value, node, "value");
652 v = strtol(value, NULL, 10);
653
654 /* range check */
655 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200656 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200657 goto error;
658 }
659 type->info.dec64.dig = (uint8_t)v;
660 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200661 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200662 goto error;
663 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200664 }
665
666 /* mandatory sub-statement(s) check */
667 if (!type->info.dec64.dig && !type->der->type.der) {
668 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200669 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200670 goto error;
671 }
Radek Krejci7511f402015-07-10 09:56:30 +0200672 if (type->info.dec64.dig && type->der->type.der) {
673 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200674 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200675 goto error;
676 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200677 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200680 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200681
Radek Krejci994b6f62015-06-18 16:47:27 +0200682 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200683 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200684 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
685 /* garbage */
686 lyxml_free_elem(module->ctx, node);
687 continue;
688 }
689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200690 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200692 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200693 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200694 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200695 }
696 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200697 if (!type->der->type.der && !type->info.enums.count) {
698 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200699 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200700 goto error;
701 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200702 if (type->der->type.der && type->info.enums.count) {
703 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200704 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200705 goto error;
706 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200707
Radek Krejci1574a8d2015-08-03 14:16:52 +0200708 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200709 v = 0;
710 i = -1;
711 LY_TREE_FOR(yin->child, next) {
712 i++;
713
714 GETVAL(value, next, "name");
715 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200716 goto error;
717 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200718 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200719 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200720 type->info.enums.count = i + 1;
721 goto error;
722 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200724 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200725 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200726 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200727 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200728 type->info.enums.count = i + 1;
729 goto error;
730 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200732 /* check the name uniqueness */
733 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200734 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200735 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200736 type->info.enums.count = i + 1;
737 goto error;
738 }
739 }
Radek Krejci04581c62015-05-22 21:24:00 +0200740
Radek Krejci0d70c372015-07-02 16:23:10 +0200741 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200742 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200743 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
744 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200745 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200746 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200747
Radek Krejci0d70c372015-07-02 16:23:10 +0200748 if (!strcmp(node->name, "value")) {
749 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200750 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200751
752 /* range check */
753 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200754 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200755 type->info.enums.count = i + 1;
756 goto error;
757 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200758 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200759
760 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200761 if (type->info.enums.enm[i].value > v) {
762 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200763 v++;
764 } else {
765 /* check that the value is unique */
766 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200767 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200768 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200769 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200770 type->info.enums.count = i + 1;
771 goto error;
772 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200773 }
774 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200775 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200776 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200777 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200778 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200779 }
780 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 /* assign value automatically */
782 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200783 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200784 type->info.enums.count = i + 1;
785 goto error;
786 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200787 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200788 v++;
789 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200790 }
791 break;
792
793 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200794 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200795
796 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200797 LY_TREE_FOR_SAFE(yin->child, next, node) {
798 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
799 /* garbage */
800 lyxml_free_elem(module->ctx, node);
801 continue;
802 }
803
804 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200805 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200806 goto error;
807 }
808 }
809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200810 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200811 if (type->der->type.der) {
812 /* this is just a derived type with no base specified/required */
813 break;
814 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200815 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816 goto error;
817 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200818 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200819 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200820 goto error;
821 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200822 GETVAL(value, yin->child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200823 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200824 goto error;
825 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200826 break;
827
828 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200829 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200830 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200831 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
832 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200833 continue;
834 }
835
Radek Krejciaf351422015-06-19 14:49:38 +0200836 if (!strcmp(node->name, "require-instance")) {
837 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200838 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200839 goto error;
840 }
841 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200842 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200843 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200844 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200845 type->info.inst.req = -1;
846 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200847 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200848 goto error;
849 }
850 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200851 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200852 goto error;
853 }
Radek Krejciaf351422015-06-19 14:49:38 +0200854 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200855
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200856 break;
857
Radek Krejcif2860132015-06-20 12:37:20 +0200858 case LY_TYPE_BINARY:
859 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200860 case LY_TYPE_INT8:
861 case LY_TYPE_INT16:
862 case LY_TYPE_INT32:
863 case LY_TYPE_INT64:
864 case LY_TYPE_UINT8:
865 case LY_TYPE_UINT16:
866 case LY_TYPE_UINT32:
867 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200868 /* RFC 6020 9.2.4 - range */
869
870 /* length and range are actually the same restriction, so process
871 * them by this common code, we just need to differ the name and
872 * structure where the information will be stored
873 */
874 if (type->base == LY_TYPE_BINARY) {
875 restr = &type->info.binary.length;
876 name = "length";
877 } else {
878 restr = &type->info.num.range;
879 name = "range";
880 }
881
Radek Krejci73adb602015-07-02 18:07:40 +0200882 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200883 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
884 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200885 continue;
886 }
887
Radek Krejcif2860132015-06-20 12:37:20 +0200888 if (!strcmp(node->name, name)) {
889 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200890 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200891 goto error;
892 }
893
894 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200895 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200896 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200897 goto error;
898 }
899 *restr = calloc(1, sizeof **restr);
900 (*restr)->expr = lydict_insert(module->ctx, value, 0);
901
902 /* get possible substatements */
903 if (read_restr_substmt(module->ctx, *restr, node)) {
904 goto error;
905 }
906 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200907 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200908 goto error;
909 }
Radek Krejcif2860132015-06-20 12:37:20 +0200910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 break;
912
913 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200914 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200915 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200916 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
917 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200918 continue;
919 }
920
Radek Krejcidc4c1412015-06-19 15:39:54 +0200921 if (!strcmp(node->name, "path")) {
922 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200923 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200924 goto error;
925 }
926
927 GETVAL(value, node, "value");
Radek Krejcidc4c1412015-06-19 15:39:54 +0200928 type->info.lref.path = lydict_insert(module->ctx, value, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +0200929 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200930 goto error;
931 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200932
Radek Krejcidc4c1412015-06-19 15:39:54 +0200933 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200934 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200935 goto error;
936 }
Radek Krejci73adb602015-07-02 18:07:40 +0200937 }
938
939 if (!type->info.lref.path) {
940 if (type->der->type.der) {
941 /* this is just a derived type with no path specified/required */
942 break;
943 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200944 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200945 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200947 break;
948
949 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200950 /* RFC 6020 9.4.4 - length */
951 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200952 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200953 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200954 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
955 /* garbage */
956 lyxml_free_elem(module->ctx, node);
957 continue;
958 }
959
Radek Krejci3733a802015-06-19 13:43:21 +0200960 if (!strcmp(node->name, "length")) {
961 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200962 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200963 goto error;
964 }
965
966 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200967 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200968 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200969 goto error;
970 }
971 type->info.str.length = calloc(1, sizeof *type->info.str.length);
972 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
973
Radek Krejci5fbc9162015-06-19 14:11:11 +0200974 /* get possible sub-statements */
975 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200976 goto error;
977 }
Radek Krejci82d971d2015-06-19 14:20:50 +0200978 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200979 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200980 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200981 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200982 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200983 goto error;
984 }
985 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200986 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200987 if (i) {
988 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
989 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +0200990 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200991
992 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200993 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
994 if (!precomp) {
995 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200996 free(type->info.str.patterns);
997 goto error;
998 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200999 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +02001000
Radek Krejci73adb602015-07-02 18:07:40 +02001001 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001002
1003 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +02001004 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +02001005 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001006 goto error;
1007 }
Radek Krejci73adb602015-07-02 18:07:40 +02001008 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001009 }
1010 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001011 break;
1012
1013 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001014 /* RFC 6020 7.4 - type */
1015 /* count number of types in union */
1016 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001017 LY_TREE_FOR_SAFE(yin->child, next, node) {
1018 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1019 /* garbage */
1020 lyxml_free_elem(module->ctx, node);
1021 continue;
1022 }
1023
Radek Krejcie4c366b2015-07-02 10:11:31 +02001024 if (!strcmp(node->name, "type")) {
1025 i++;
1026 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001027 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001028 goto error;
1029 }
1030 }
1031
1032 if (!i) {
1033 if (type->der->type.der) {
1034 /* this is just a derived type with no base specified/required */
1035 break;
1036 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001037 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001038 goto error;
1039 }
1040
1041 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001042 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001043 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001044 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001045 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001046 goto error;
1047 }
1048 type->info.uni.count++;
1049
1050 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001051 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001052 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001053 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001054 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001055 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001056 goto error;
1057 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001058 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001059 break;
1060
1061 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001062 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1064 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001065 LY_TREE_FOR(yin->child, node) {
1066 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001067 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001068 goto error;
1069 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001070 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001071 break;
1072 }
1073
1074 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001075
1076error:
1077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001078 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001079}
1080
Michal Vasko0d343d12015-08-24 14:57:36 +02001081/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001082static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001083fill_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 +02001084{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001085 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001086 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001087 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 GETVAL(value, yin, "name");
1090 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1091 goto error;
1092 }
1093 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001094
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001096 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001097 goto error;
1098 }
Radek Krejcieac35532015-05-31 19:09:15 +02001099
Radek Krejci73adb602015-07-02 18:07:40 +02001100 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001101 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1102 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001103 continue;
1104 }
1105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001107 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001108 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 goto error;
1110 }
Radek Krejci73adb602015-07-02 18:07:40 +02001111 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1112 goto error;
1113 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001114 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001115 } else if (!strcmp(node->name, "default")) {
1116 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001117 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001118 goto error;
1119 }
1120 GETVAL(value, node, "value");
1121 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001122 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001123 } else if (!strcmp(node->name, "units")) {
1124 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001125 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001126 goto error;
1127 }
1128 GETVAL(value, node, "name");
1129 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1130 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001131 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001132 goto error;
1133 }
1134 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001136 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001137 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001138 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001139 goto error;
1140 }
Radek Krejcieac35532015-05-31 19:09:15 +02001141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001142 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001143 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001144 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001145 goto error;
1146 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001147 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001149 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001150
1151error:
1152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001153 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001154}
1155
Michal Vasko0d343d12015-08-24 14:57:36 +02001156/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001157static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001158fill_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 +02001159{
1160 const char *value;
1161 struct lyxml_elem *child, *next;
1162 int c = 0;
1163
Radek Krejcib05774c2015-06-18 13:52:59 +02001164 GETVAL(value, yin, "name");
1165 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1166 goto error;
1167 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001168 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001169 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001170
Radek Krejci76512572015-08-04 09:47:08 +02001171 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001172 goto error;
1173 }
1174
1175 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001176 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1177 /* garbage */
1178 lyxml_free_elem(module->ctx, child);
1179 continue;
1180 }
1181
Radek Krejci3cf9e222015-06-18 11:37:50 +02001182 if (!strcmp(child->name, "if-feature")) {
1183 c++;
1184 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001185 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001186 goto error;
1187 }
1188 }
1189
1190 if (c) {
1191 f->features = calloc(c, sizeof *f->features);
1192 }
Radek Krejci73adb602015-07-02 18:07:40 +02001193 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001194 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02001195 if (unres_schema_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001196 goto error;
1197 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001198 }
1199
Radek Krejci3cf9e222015-06-18 11:37:50 +02001200 return EXIT_SUCCESS;
1201
1202error:
1203
1204 return EXIT_FAILURE;
1205}
1206
Michal Vasko0d343d12015-08-24 14:57:36 +02001207/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001208static int
Radek Krejcib8048692015-08-05 13:36:34 +02001209fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001210{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001211 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001213 GETVAL(value, yin, "condition");
Radek Krejci0bd5db42015-06-19 13:30:07 +02001214 must->expr = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02001215
Radek Krejci41726f92015-06-19 13:11:05 +02001216 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001217
Radek Krejci41726f92015-06-19 13:11:05 +02001218error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001220 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001221}
1222
Michal Vasko0d343d12015-08-24 14:57:36 +02001223/* logs directly
1224 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001225 * type: 0 - min, 1 - max
1226 */
1227static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001228deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001229{
1230 const char *value;
1231 char *endptr;
1232 unsigned long val;
1233 uint32_t *ui32val;
1234
1235 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001236 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001237 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001238 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001239 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001240 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001241 }
Radek Krejci76512572015-08-04 09:47:08 +02001242 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001243 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001244 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001245 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001246 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001247 }
1248 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001249 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1250 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001251 goto error;
1252 }
1253
1254 GETVAL(value, node, "value");
1255 while (isspace(value[0])) {
1256 value++;
1257 }
1258
1259 /* convert it to uint32_t */
1260 errno = 0;
1261 endptr = NULL;
1262 val = strtoul(value, &endptr, 10);
1263 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001264 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001265 goto error;
1266 }
1267 if (type) {
1268 d->max = (uint32_t)val;
1269 } else {
1270 d->min = (uint32_t)val;
1271 }
1272
1273 if (d->mod == LY_DEVIATE_ADD) {
1274 /* check that there is no current value */
1275 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001276 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1277 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001278 goto error;
1279 }
1280 }
1281
1282 if (d->mod == LY_DEVIATE_DEL) {
1283 /* check values */
1284 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001285 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1286 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001287 goto error;
1288 }
1289 /* remove current min-elements value of the target */
1290 *ui32val = 0;
1291 } else { /* add (already checked) and replace */
1292 /* set new value specified in deviation */
1293 *ui32val = (uint32_t)val;
1294 }
1295
1296 return EXIT_SUCCESS;
1297
1298error:
1299
1300 return EXIT_FAILURE;
1301}
1302
Michal Vasko0d343d12015-08-24 14:57:36 +02001303/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001304static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001305fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001306{
1307 const char *value, **stritem;
1308 struct lyxml_elem *next, *child, *develem;
1309 int c_dev = 0, c_must, c_uniq;
1310 int f_min = 0; /* flags */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001311 int i, j, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001312 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001313 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001314 struct lys_node_choice *choice = NULL;
1315 struct lys_node_leaf *leaf = NULL;
1316 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001317 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001318 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001319 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001320
1321 GETVAL(value, yin, "target-node");
1322 dev->target_name = lydict_insert(module->ctx, value, 0);
1323
1324 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001325 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1326 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001327 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001328 goto error;
1329 }
1330 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001331 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001332 goto error;
1333 }
1334 /* mark the target module as deviated */
1335 dev->target->module->deviated = 1;
1336
1337 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001338 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1339 /* garbage */
1340 lyxml_free_elem(module->ctx, child);
1341 continue;
1342 }
1343
Radek Krejcieb00f512015-07-01 16:44:58 +02001344 if (!strcmp(child->name, "description")) {
1345 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001346 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001347 goto error;
1348 }
1349 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1350 if (!dev->dsc) {
1351 goto error;
1352 }
1353 } else if (!strcmp(child->name, "reference")) {
1354 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001355 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001356 goto error;
1357 }
1358 dev->ref = read_yin_subnode(module->ctx, child, "text");
1359 if (!dev->ref) {
1360 goto error;
1361 }
1362 } else if (!strcmp(child->name, "deviate")) {
1363 c_dev++;
1364
1365 /* skip lyxml_free_elem() at the end of the loop, node will be
1366 * further processed later
1367 */
1368 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001369
Radek Krejcieb00f512015-07-01 16:44:58 +02001370 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001371 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001372 goto error;
1373 }
1374
1375 lyxml_free_elem(module->ctx, child);
1376 }
1377
1378 if (c_dev) {
1379 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1380 }
1381
1382 LY_TREE_FOR(yin->child, develem) {
1383 /* init */
1384 f_min = 0;
1385 c_must = 0;
1386 c_uniq = 0;
1387
1388 /* get deviation type */
1389 GETVAL(value, develem, "value");
1390 if (!strcmp(value, "not-supported")) {
1391 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1392 /* no property expected in this case */
1393 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001394 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001395 goto error;
1396 }
1397
Radek Krejci5b917642015-07-02 09:03:13 +02001398 /* and neither any other deviate statement is expected,
1399 * not-supported deviation must be the only deviation of the target
1400 */
1401 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001402 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1403 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001404 goto error;
1405 }
1406
1407
Radek Krejcieb00f512015-07-01 16:44:58 +02001408 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001409 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001410 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001411
Radek Krejci5b917642015-07-02 09:03:13 +02001412 dev->deviate_size = 1;
1413 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001414 } else if (!strcmp(value, "add")) {
1415 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1416 } else if (!strcmp(value, "replace")) {
1417 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1418 } else if (!strcmp(value, "delete")) {
1419 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1420 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001421 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 goto error;
1423 }
1424 d = &dev->deviate[dev->deviate_size];
1425
1426 /* process deviation properties */
1427 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001428 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1429 /* garbage */
1430 lyxml_free_elem(module->ctx, child);
1431 continue;
1432 }
1433
Radek Krejcieb00f512015-07-01 16:44:58 +02001434 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001435 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001436 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001437 goto error;
1438 }
1439
1440 /* for we deviate from RFC 6020 and allow config property even it is/is not
1441 * specified in the target explicitly since config property inherits. So we expect
1442 * that config is specified in every node. But for delete, we check that the value
1443 * is the same as here in deviation
1444 */
1445 GETVAL(value, child, "value");
1446 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001447 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001448 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001449 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001450 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001451 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001452 goto error;
1453 }
1454
1455 if (d->mod == LY_DEVIATE_DEL) {
1456 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001457 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001458 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1459 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001460 goto error;
1461 }
1462 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001463 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001464
1465 /* ... and inherit config value from the target's parent */
1466 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001467 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001468 } else {
1469 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001470 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001471 }
1472 } else { /* add and replace are the same in this case */
1473 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001474 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001475
1476 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001477 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001478 }
1479 } else if (!strcmp(child->name, "default")) {
1480 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001481 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 goto error;
1483 }
1484 GETVAL(value, child, "value");
1485 d->dflt = lydict_insert(module->ctx, value, 0);
1486
Radek Krejci76512572015-08-04 09:47:08 +02001487 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001488 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001489
1490 if (d->mod == LY_DEVIATE_ADD) {
1491 /* check that there is no current value */
1492 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001493 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1494 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001495 goto error;
1496 }
1497 }
1498
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001499 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1500 if (rc) {
1501 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1502 goto error;
1503 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001504 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001505 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001506 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1507 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001508 goto error;
1509 }
1510 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001511 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001512 if (!choice->dflt) {
1513 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001514 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001515 goto error;
1516 }
1517 }
Radek Krejci76512572015-08-04 09:47:08 +02001518 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001519 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001520
1521 if (d->mod == LY_DEVIATE_ADD) {
1522 /* check that there is no current value */
1523 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001524 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1525 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001526 goto error;
1527 }
1528 }
1529
1530 if (d->mod == LY_DEVIATE_DEL) {
1531 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001532 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1533 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001534 goto error;
1535 }
1536 /* remove value */
1537 lydict_remove(leaf->module->ctx, leaf->dflt);
1538 leaf->dflt = NULL;
1539 } else { /* add (already checked) and replace */
1540 /* remove value */
1541 lydict_remove(leaf->module->ctx, leaf->dflt);
1542
1543 /* set new value */
1544 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1545 }
1546 } else {
1547 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001548 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1549 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001550 goto error;
1551 }
1552 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001553 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001554 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 goto error;
1556 }
1557
1558 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001559 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001560 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1561 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001562 goto error;
1563 }
1564
1565 GETVAL(value, child, "value");
1566 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001567 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001568 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001569 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001570 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001571 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001572 goto error;
1573 }
1574
1575 if (d->mod == LY_DEVIATE_ADD) {
1576 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001577 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001578 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1579 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001580 goto error;
1581 }
1582 }
1583
1584 if (d->mod == LY_DEVIATE_DEL) {
1585 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001586 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001587 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1588 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 goto error;
1590 }
1591 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001592 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001593 } else { /* add (already checked) and replace */
1594 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001595 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001596
1597 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001598 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001599 }
1600 } else if (!strcmp(child->name, "min-elements")) {
1601 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001602 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001603 goto error;
1604 }
1605 f_min = 1;
1606
1607 if (deviate_minmax(dev->target, child, d, 0)) {
1608 goto error;
1609 }
1610 } else if (!strcmp(child->name, "max-elements")) {
1611 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001612 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 goto error;
1614 }
1615
1616 if (deviate_minmax(dev->target, child, d, 1)) {
1617 goto error;
1618 }
1619 } else if (!strcmp(child->name, "must")) {
1620 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001621 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1622 continue;
1623 } else if (!strcmp(child->name, "type")) {
1624 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001625 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 goto error;
1627 }
1628
1629 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001630 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001631 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001632 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001633 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001634 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001635 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1636 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 goto error;
1638 }
1639
1640 if (d->mod == LY_DEVIATE_ADD) {
1641 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001642 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1643 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 goto error;
1645 } else if (d->mod == LY_DEVIATE_DEL) {
1646 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001647 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1648 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001649 goto error;
1650 }
1651
1652 /* replace */
1653 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001654 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001655
1656 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001657 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001658 goto error;
1659 }
1660 d->type = t;
1661 } else if (!strcmp(child->name, "unique")) {
1662 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001663 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1664 continue;
1665 } else if (!strcmp(child->name, "units")) {
1666 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001667 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001668 goto error;
1669 }
1670
1671 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001672 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001673 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001674 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001675 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001676 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001677 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1678 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001679 goto error;
1680 }
1681
1682 /* get units value */
1683 GETVAL(value, child, "name");
1684 d->units = lydict_insert(module->ctx, value, 0);
1685
1686 /* apply to target */
1687 if (d->mod == LY_DEVIATE_ADD) {
1688 /* check that there is no current value */
1689 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001690 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1691 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 goto error;
1693 }
1694 }
1695
1696 if (d->mod == LY_DEVIATE_DEL) {
1697 /* check values */
1698 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001699 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1700 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001701 goto error;
1702 }
1703 /* remove current units value of the target */
1704 lydict_remove(dev->target->module->ctx, *stritem);
1705 } else { /* add (already checked) and replace */
1706 /* remove current units value of the target ... */
1707 lydict_remove(dev->target->module->ctx, *stritem);
1708
1709 /* ... and replace it with the value specified in deviation */
1710 *stritem = lydict_insert(module->ctx, value, 0);
1711 }
1712 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001713 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001714 goto error;
1715 }
1716
1717 lyxml_free_elem(module->ctx, child);
1718 }
1719
1720 if (c_must) {
1721 /* check target node type */
1722 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001723 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001724 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1725 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001726 break;
Radek Krejci76512572015-08-04 09:47:08 +02001727 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001728 trg_must = &((struct lys_node_container *)dev->target)->must;
1729 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001730 break;
Radek Krejci76512572015-08-04 09:47:08 +02001731 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001732 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1733 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001734 break;
Radek Krejci76512572015-08-04 09:47:08 +02001735 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001736 trg_must = &((struct lys_node_list *)dev->target)->must;
1737 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001738 break;
Radek Krejci76512572015-08-04 09:47:08 +02001739 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001740 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1741 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001742 break;
1743 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001744 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1745 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 goto error;
1747 }
1748
1749 if (d->mod == LY_DEVIATE_RPL) {
1750 /* remove target's musts and allocate new array for it */
1751 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001752 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1753 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001754 goto error;
1755 }
1756
1757 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001758 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001759 }
1760 free(*trg_must);
1761 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1762 d->must_size = c_must;
1763 *trg_must_size = 0;
1764 } else if (d->mod == LY_DEVIATE_ADD) {
1765 /* reallocate the must array of the target */
1766 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1767 *trg_must = d->must;
1768 d->must = &(*trg_must[*trg_must_size]);
1769 d->must_size = c_must;
1770 } else { /* LY_DEVIATE_DEL */
1771 d->must = calloc(c_must, sizeof *d->must);
1772 }
1773 }
1774 if (c_uniq) {
1775 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001776 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001777 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1778 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 goto error;
1780 }
1781
Radek Krejcib8048692015-08-05 13:36:34 +02001782 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001783 if (d->mod == LY_DEVIATE_RPL) {
1784 /* remove target's unique and allocate new array for it */
1785 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001786 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1787 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001788 goto error;
1789 }
1790
1791 for (i = 0; i < list->unique_size; i++) {
1792 free(list->unique[i].leafs);
1793 }
1794 free(list->unique);
1795 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1796 d->unique_size = c_uniq;
1797 list->unique_size = 0;
1798 } else if (d->mod == LY_DEVIATE_ADD) {
1799 /* reallocate the unique array of the target */
1800 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1801 list->unique = d->unique;
1802 d->unique = &list->unique[list->unique_size];
1803 d->unique_size = c_uniq;
1804 } else { /* LY_DEVIATE_DEL */
1805 d->unique = calloc(c_uniq, sizeof *d->unique);
1806 }
1807 }
1808
1809 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001810 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001811 if (!strcmp(child->name, "must")) {
1812 if (d->mod == LY_DEVIATE_DEL) {
1813 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1814 goto error;
1815 }
1816
1817 /* find must to delete, we are ok with just matching conditions */
1818 for (i = 0; i < *trg_must_size; i++) {
1819 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1820 /* we have a match, free the must structure ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001821 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001822 /* ... and maintain the array */
1823 (*trg_must_size)--;
1824 if (i != *trg_must_size) {
1825 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1826 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1827 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1828 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1829 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1830 }
1831 if (!(*trg_must_size)) {
1832 free(*trg_must);
1833 *trg_must = NULL;
1834 } else {
1835 (*trg_must)[*trg_must_size].expr = NULL;
1836 (*trg_must)[*trg_must_size].dsc = NULL;
1837 (*trg_must)[*trg_must_size].ref = NULL;
1838 (*trg_must)[*trg_must_size].eapptag = NULL;
1839 (*trg_must)[*trg_must_size].emsg = NULL;
1840 }
1841
1842 i = -1; /* set match flag */
1843 break;
1844 }
1845 }
1846 d->must_size++;
1847 if (i != -1) {
1848 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001849 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1850 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001851 goto error;
1852 }
1853 } else { /* replace or add */
1854 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1855 goto error;
1856 }
1857 (*trg_must_size)++;
1858 }
1859 } else if (!strcmp(child->name, "unique")) {
1860 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001861 GETVAL(value, child, "tag");
1862 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001863 goto error;
1864 }
1865
1866 /* find unique structures to delete */
1867 for (i = 0; i < list->unique_size; i++) {
1868 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1869 continue;
1870 }
1871
1872 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1873 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1874 break;
1875 }
1876 }
1877
1878 if (j == d->unique[d->unique_size].leafs_size) {
1879 /* we have a match, free the unique structure ... */
1880 free(list->unique[i].leafs);
1881 /* ... and maintain the array */
1882 list->unique_size--;
1883 if (i != list->unique_size) {
1884 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1885 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1886 }
1887
1888 if (!list->unique_size) {
1889 free(list->unique);
1890 list->unique = NULL;
1891 } else {
1892 list->unique[list->unique_size].leafs_size = 0;
1893 list->unique[list->unique_size].leafs = NULL;
1894 }
1895
1896 i = -1; /* set match flag */
1897 break;
1898 }
1899 }
1900
1901 d->unique_size++;
1902 if (i != -1) {
1903 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001904 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1905 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001906 goto error;
1907 }
1908 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001909 GETVAL(value, child, "tag");
1910 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001911 goto error;
1912 }
1913 list->unique_size++;
1914 }
1915 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001916 }
Radek Krejci5b917642015-07-02 09:03:13 +02001917
1918 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001919 }
1920
Radek Krejcieb00f512015-07-01 16:44:58 +02001921 return EXIT_SUCCESS;
1922
1923error:
1924
1925 if (dev->deviate) {
1926 for (i = 0; i < dev->deviate_size; i++) {
1927 lydict_remove(module->ctx, dev->deviate[i].dflt);
1928 lydict_remove(module->ctx, dev->deviate[i].units);
1929
1930 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1931 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001932 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001933 }
1934 free(dev->deviate[i].must);
1935
1936 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1937 free(dev->deviate[i].unique[j].leafs);
1938 }
1939 free(dev->deviate[i].unique);
1940 }
1941 }
1942 free(dev->deviate);
1943 }
1944
1945 return EXIT_FAILURE;
1946}
1947
Michal Vasko0d343d12015-08-24 14:57:36 +02001948/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001949static int
Radek Krejcib8048692015-08-05 13:36:34 +02001950fill_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 +02001951 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001952{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001953 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001954 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 struct lys_node *node;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001956 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02001957
Michal Vasko591e0b22015-08-13 13:53:43 +02001958 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001959 GETVAL(value, yin, "target-node");
1960 aug->target_name = lydict_insert(module->ctx, value, 0);
1961 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001962
Michal Vasko1d87a922015-08-21 12:57:16 +02001963 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001964 goto error;
1965 }
1966
1967 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001968 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1969 /* garbage */
1970 lyxml_free_elem(module->ctx, child);
1971 continue;
1972 }
1973
Radek Krejci3cf9e222015-06-18 11:37:50 +02001974 if (!strcmp(child->name, "if-feature")) {
1975 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001976 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001977 } else if (!strcmp(child->name, "when")) {
1978 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001979 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001980 goto error;
1981 }
1982
1983 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001984 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001985 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001986 goto error;
1987 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02001988 if (unres_schema_add_node(module, unres, aug->when, UNRES_WHEN, (struct lys_node *)aug, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001989 goto error;
1990 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991 lyxml_free_elem(module->ctx, child);
1992 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001993
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 /* check allowed data sub-statements */
1995 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001998 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001999 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002000 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002005 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002006 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002007 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002008 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002010 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002012 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002013 goto error;
2014 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015
Radek Krejci1d82ef62015-08-07 14:44:40 +02002016 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002017 goto error;
2018 }
2019
2020 /* check for mandatory nodes - if the target node is in another module
2021 * the added nodes cannot be mandatory
2022 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002023 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002024 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002025 goto error;
2026 }
2027
Radek Krejci1d82ef62015-08-07 14:44:40 +02002028 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002029 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002030 }
2031
2032 if (c) {
2033 aug->features = calloc(c, sizeof *aug->features);
2034 }
2035
2036 LY_TREE_FOR_SAFE(yin->child, next, child) {
2037 if (!strcmp(child->name, "if-feature")) {
2038 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002039 if (unres_schema_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002040 goto error;
2041 }
Radek Krejci73adb602015-07-02 18:07:40 +02002042 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002043 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002044 }
2045
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002046 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002047 * connected to the tree and adjusted (if possible right now).
2048 * However, if this is augment in a uses, it gets resolved
2049 * when the uses does and cannot be resolved now for sure
2050 * (the grouping was not yet copied into uses).
2051 */
2052 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02002053 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002054 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2055 goto error;
2056 }
Michal Vasko49291b32015-08-06 09:49:41 +02002057 }
Radek Krejci106efc02015-06-10 14:36:27 +02002058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002060
2061error:
2062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002064}
2065
Michal Vasko0d343d12015-08-24 14:57:36 +02002066/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002067static int
Radek Krejcib8048692015-08-05 13:36:34 +02002068fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02002069 struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002070{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 struct lyxml_elem *sub, *next;
2072 const char *value;
2073 char *endptr;
2074 int f_mand = 0, f_min = 0, f_max = 0;
2075 int c_must = 0;
2076 int r;
2077 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002078
Radek Krejci76512572015-08-04 09:47:08 +02002079 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 goto error;
2081 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002082
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002083 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002084 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002087 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2088 /* garbage */
2089 lyxml_free_elem(module->ctx, sub);
2090 continue;
2091 }
2092
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002093 /* limited applicability */
2094 if (!strcmp(sub->name, "default")) {
2095 /* leaf or choice */
2096 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002097 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 goto error;
2099 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 /* check possibility of statements combination */
2102 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002103 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002104 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002105 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002106 goto error;
2107 }
2108 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002109 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002111
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002112 GETVAL(value, sub, "value");
2113 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2114 } else if (!strcmp(sub->name, "mandatory")) {
2115 /* leaf, choice or anyxml */
2116 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002117 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 goto error;
2119 }
2120 /* just checking the flags in leaf is not sufficient, we would allow
2121 * multiple mandatory statements with the "false" value
2122 */
2123 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002125 /* check possibility of statements combination */
2126 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002127 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002129 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002130 goto error;
2131 }
2132 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002133 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002136 GETVAL(value, sub, "value");
2137 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002138 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002139 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002140 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002142 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 goto error;
2144 }
2145 } else if (!strcmp(sub->name, "min-elements")) {
2146 /* list or leaf-list */
2147 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002148 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 goto error;
2150 }
2151 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002152
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002153 /* check possibility of statements combination */
2154 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002155 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002157 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 goto error;
2159 }
2160 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002161 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 GETVAL(value, sub, "value");
2165 while (isspace(value[0])) {
2166 value++;
2167 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 /* convert it to uint32_t */
2170 errno = 0;
2171 endptr = NULL;
2172 val = strtoul(value, &endptr, 10);
2173 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002174 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002175 goto error;
2176 }
2177 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 /* magic - bit 3 in flags means min set */
2180 rfn->flags |= 0x04;
2181 } else if (!strcmp(sub->name, "max-elements")) {
2182 /* list or leaf-list */
2183 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002184 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 goto error;
2186 }
2187 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002188
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 /* check possibility of statements combination */
2190 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002191 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002192 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002193 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002194 goto error;
2195 }
2196 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002197 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002198 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 GETVAL(value, sub, "value");
2201 while (isspace(value[0])) {
2202 value++;
2203 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 /* convert it to uint32_t */
2206 errno = 0;
2207 endptr = NULL;
2208 val = strtoul(value, &endptr, 10);
2209 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002210 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 goto error;
2212 }
2213 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 /* magic - bit 4 in flags means min set */
2216 rfn->flags |= 0x08;
2217 } else if (!strcmp(sub->name, "presence")) {
2218 /* container */
2219 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002220 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 goto error;
2222 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002223
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002224 /* check possibility of statements combination */
2225 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002226 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002228 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 goto error;
2230 }
2231 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002232 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 GETVAL(value, sub, "value");
2236 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2237 } else if (!strcmp(sub->name, "must")) {
2238 /* leaf-list, list, container or anyxml */
2239 /* check possibility of statements combination */
2240 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002241 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002243 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002244 goto error;
2245 }
2246 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002247 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002248 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002249
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002250 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002251 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002253 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002254 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 goto error;
2256 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002258 lyxml_free_elem(module->ctx, sub);
2259 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002261 /* process nodes with cardinality of 0..n */
2262 if (c_must) {
2263 rfn->must = calloc(c_must, sizeof *rfn->must);
2264 }
Radek Krejci73adb602015-07-02 18:07:40 +02002265 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002266 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002267 if (r) {
2268 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002270 if (unres_schema_add_node(module, unres, &rfn->must[rfn->must_size-1], UNRES_MUST, (struct lys_node *)uses,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002271 LOGLINE(sub)) == -1) {
2272 goto error;
2273 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002277
2278error:
2279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002281}
2282
Michal Vasko0d343d12015-08-24 14:57:36 +02002283/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002284static int
Radek Krejcib8048692015-08-05 13:36:34 +02002285fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002286{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 struct lyxml_elem *child;
2288 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002290 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002291 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2292 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002293 continue;
2294 }
2295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002296 if (!strcmp(child->name, "prefix")) {
2297 GETVAL(value, child, "value");
2298 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2299 goto error;
2300 }
2301 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2302 } else if (!strcmp(child->name, "revision-date")) {
2303 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002304 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 goto error;
2306 }
2307 GETVAL(value, child, "date");
2308 if (check_date(value, LOGLINE(child))) {
2309 goto error;
2310 }
2311 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2312 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002313 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 goto error;
2315 }
2316 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 /* check mandatory information */
2319 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002320 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 goto error;
2322 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002325 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002326 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002327 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2328 if (!imp->module) {
2329 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2330 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002331 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002332 goto error;
2333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002334 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002336 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002337
2338error:
2339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002341}
2342
Michal Vasko0d343d12015-08-24 14:57:36 +02002343/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344static int
Radek Krejcib8048692015-08-05 13:36:34 +02002345fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002346{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 struct lyxml_elem *child;
2348 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002351 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2352 /* garbage */
2353 continue;
2354 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 if (!strcmp(child->name, "revision-date")) {
2356 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002357 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002358 goto error;
2359 }
2360 GETVAL(value, child, "date");
2361 if (check_date(value, LOGLINE(child))) {
2362 goto error;
2363 }
2364 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2365 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002366 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 goto error;
2368 }
2369 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002372 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002374 inc->submodule = (struct lys_submodule *) lyp_search_file(module->ctx, module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci63a91a92015-07-29 13:31:04 +02002375 if (!inc->submodule) {
2376 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2377 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002378 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002379 goto error;
2380 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002383 /* check that belongs-to corresponds */
2384 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002385 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002386 }
2387 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002388 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2389 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002390 goto error;
2391 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002392
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002393 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002394
2395error:
2396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002397 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002398}
2399
Michal Vasko0d343d12015-08-24 14:57:36 +02002400/* logs directly
2401 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002402 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002403 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002404 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002405 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406static int
Radek Krejcib8048692015-08-05 13:36:34 +02002407read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002408 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002409{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 const char *value;
2411 struct lyxml_elem *sub, *next;
2412 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002414 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002415 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002417
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 if (opt & OPT_IDENT) {
2419 GETVAL(value, xmlnode, "name");
2420 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2421 goto error;
2422 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002423 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002425
Radek Krejci6764bb32015-07-03 15:16:04 +02002426 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002427 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002428 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002429 }
2430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002431 /* process local parameters */
2432 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002433 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002434 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002435 lyxml_free_elem(ctx, sub);
2436 continue;
2437 }
2438 if (strcmp(sub->ns->value, LY_NSYIN)) {
2439 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002440 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002441 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002443 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002444 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002445 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002446 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002447 goto error;
2448 }
2449 }
2450
2451 /* else garbage */
2452 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002453 continue;
2454 }
2455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002457 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002458 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 goto error;
2460 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002461 node->dsc = read_yin_subnode(ctx, sub, "text");
2462 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002463 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002464 }
2465 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002466 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002467 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 goto error;
2469 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002470 node->ref = read_yin_subnode(ctx, sub, "text");
2471 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002472 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 }
2474 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002475 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002476 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002477 goto error;
2478 }
2479 GETVAL(value, sub, "value");
2480 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002481 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002483 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002484 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002485 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002486 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002487 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002488 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002489 }
2490 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002491 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002492 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002493 goto error;
2494 }
2495 GETVAL(value, sub, "value");
2496 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002497 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002498 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002499 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002501 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002502 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 }
2504 } else {
2505 /* skip the lyxml_free_elem */
2506 continue;
2507 }
2508 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002509 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002510
Radek Krejci1d82ef62015-08-07 14:44:40 +02002511 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002512 /* get config flag from parent */
2513 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002514 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002515 } else {
2516 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002517 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002518 }
2519 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002521 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002522
2523error:
2524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002525 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002526}
2527
Michal Vasko0d343d12015-08-24 14:57:36 +02002528/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002529static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002530read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002531{
Radek Krejci76512572015-08-04 09:47:08 +02002532 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002533 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002534 const char *value;
2535
2536 retval = calloc(1, sizeof *retval);
2537
2538 GETVAL(value, yin, "condition");
2539 retval->cond = lydict_insert(module->ctx, value, 0);
2540
Radek Krejci73adb602015-07-02 18:07:40 +02002541 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002542 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2543 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002544 continue;
2545 }
2546
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002547 if (!strcmp(child->name, "description")) {
2548 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002549 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002550 goto error;
2551 }
2552 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2553 if (!retval->dsc) {
2554 goto error;
2555 }
2556 } else if (!strcmp(child->name, "reference")) {
2557 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002558 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002559 goto error;
2560 }
2561 retval->ref = read_yin_subnode(module->ctx, child, "text");
2562 if (!retval->ref) {
2563 goto error;
2564 }
2565 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002566 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002567 goto error;
2568 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002569 }
2570
2571 return retval;
2572
2573error:
2574
Radek Krejci1d82ef62015-08-07 14:44:40 +02002575 lys_node_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002576 return NULL;
2577}
2578
Michal Vasko0d343d12015-08-24 14:57:36 +02002579/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002580static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002581read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2582 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002583{
Michal Vasko29fc0182015-08-24 15:02:39 +02002584 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002585 struct lys_node_case *cs;
2586 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002587 int c_ftrs = 0;
2588 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002589
Radek Krejci1d82ef62015-08-07 14:44:40 +02002590 cs = calloc(1, sizeof *cs);
2591 cs->nodetype = LYS_CASE;
2592 cs->prev = (struct lys_node *)cs;
2593 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002594
Radek Krejci6a113852015-07-03 16:04:20 +02002595 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002596 goto error;
2597 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002598
Radek Krejcia9544502015-08-14 08:24:29 +02002599 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2600
Michal Vasko3a0043f2015-08-12 12:11:30 +02002601 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002602 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002603 goto error;
2604 }
2605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002606 /* process choice's specific children */
2607 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002608 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2609 /* garbage */
2610 lyxml_free_elem(module->ctx, sub);
2611 continue;
2612 }
2613
Michal Vasko29fc0182015-08-24 15:02:39 +02002614 if (!strcmp(sub->name, "container") ||
2615 !strcmp(sub->name, "leaf-list") ||
2616 !strcmp(sub->name, "leaf") ||
2617 !strcmp(sub->name, "list") ||
2618 !strcmp(sub->name, "uses") ||
2619 !strcmp(sub->name, "choice") ||
2620 !strcmp(sub->name, "anyxml")) {
2621
2622 lyxml_unlink_elem(module->ctx, sub, 1);
2623 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002624 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002625 c_ftrs++;
2626 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2627 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002628 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002629 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002630 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002631 goto error;
2632 }
2633
Radek Krejci1d82ef62015-08-07 14:44:40 +02002634 cs->when = read_yin_when(module, sub);
2635 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002636 goto error;
2637 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002638 if (unres_schema_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002639 goto error;
2640 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002641
2642 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002643 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002644 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002648
Radek Krejci3cf9e222015-06-18 11:37:50 +02002649 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002650 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002651 }
Radek Krejci73adb602015-07-02 18:07:40 +02002652 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002653 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002654 if (unres_schema_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002655 goto error;
2656 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 }
Radek Krejcib388c152015-06-04 17:03:03 +02002658
Michal Vasko29fc0182015-08-24 15:02:39 +02002659 /* last part - process data nodes */
2660 LY_TREE_FOR_SAFE(root.child, next, sub) {
2661 if (!strcmp(sub->name, "container")) {
2662 node = read_yin_container(module, retval, sub, resolve, unres);
2663 } else if (!strcmp(sub->name, "leaf-list")) {
2664 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2665 } else if (!strcmp(sub->name, "leaf")) {
2666 node = read_yin_leaf(module, retval, sub, resolve, unres);
2667 } else if (!strcmp(sub->name, "list")) {
2668 node = read_yin_list(module, retval, sub, resolve, unres);
2669 } else if (!strcmp(sub->name, "choice")) {
2670 node = read_yin_choice(module, retval, sub, resolve, unres);
2671 } else if (!strcmp(sub->name, "uses")) {
2672 node = read_yin_uses(module, retval, sub, resolve, unres);
2673 } else if (!strcmp(sub->name, "anyxml")) {
2674 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2675 }
2676 if (!node) {
2677 goto error;
2678 }
2679
2680 lyxml_free_elem(module->ctx, sub);
2681 }
2682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002683 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002684
2685error:
2686
Michal Vasko29fc0182015-08-24 15:02:39 +02002687 while (root.child) {
2688 lyxml_free_elem(module->ctx, root.child);
2689 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002690 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002693}
2694
Michal Vasko0d343d12015-08-24 14:57:36 +02002695/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002696static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002697read_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 +02002698{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002699 struct lyxml_elem *sub, *next;
2700 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002701 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002702 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002703 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002704 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002706 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002707 choice->nodetype = LYS_CHOICE;
2708 choice->prev = (struct lys_node *)choice;
2709 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002710
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002711 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2712 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 goto error;
2714 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002715
Radek Krejcia9544502015-08-14 08:24:29 +02002716 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2717
Michal Vasko3a0043f2015-08-12 12:11:30 +02002718 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002719 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002720 goto error;
2721 }
2722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 /* process choice's specific children */
2724 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002725 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2726 /* garbage */
2727 lyxml_free_elem(module->ctx, sub);
2728 continue;
2729 }
2730
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002732 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002733 goto error;
2734 }
2735 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002736 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002737 goto error;
2738 }
2739 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002740 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 goto error;
2742 }
2743 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002744 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 }
2747 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 goto error;
2750 }
2751 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 goto error;
2754 }
2755 } else if (!strcmp(sub->name, "default")) {
2756 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002757 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 goto error;
2759 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002760 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 } else if (!strcmp(sub->name, "mandatory")) {
2762 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002763 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 goto error;
2765 }
2766 /* just checking the flags in leaf is not sufficient, we would allow
2767 * multiple mandatory statements with the "false" value
2768 */
2769 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002771 GETVAL(value, sub, "value");
2772 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002773 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002774 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002775 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002776 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002777 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002778 goto error;
2779 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002780 } else if (!strcmp(sub->name, "when")) {
2781 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002782 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002783 goto error;
2784 }
2785
2786 choice->when = read_yin_when(module, sub);
2787 if (!choice->when) {
2788 goto error;
2789 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002790 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002791 goto error;
2792 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002793 } else if (!strcmp(sub->name, "if-feature")) {
2794 c_ftrs++;
2795
2796 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2797 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002799 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002802
Radek Krejci1d82ef62015-08-07 14:44:40 +02002803 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 lyxml_free_elem(ctx, sub);
2805 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002806
Radek Krejci3cf9e222015-06-18 11:37:50 +02002807 if (c_ftrs) {
2808 choice->features = calloc(c_ftrs, sizeof *choice->features);
2809 }
2810
Radek Krejci73adb602015-07-02 18:07:40 +02002811 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002812 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002813 if (unres_schema_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002814 goto error;
2815 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002816 }
2817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002818 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002819 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002820 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2822 goto error;
2823 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002824
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 /* link default with the case */
2826 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002827 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002828 goto error;
2829 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002833
2834error:
2835
Radek Krejci1d82ef62015-08-07 14:44:40 +02002836 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002838 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002839}
2840
Michal Vasko0d343d12015-08-24 14:57:36 +02002841/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002842static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002843read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002844 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002845{
Radek Krejci76512572015-08-04 09:47:08 +02002846 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002847 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002848 struct lyxml_elem *sub, *next;
2849 const char *value;
2850 int r;
2851 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002852 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002855 anyxml->nodetype = LYS_ANYXML;
2856 anyxml->prev = (struct lys_node *)anyxml;
2857 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002858
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002859 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2860 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002861 goto error;
2862 }
Radek Krejci863c2852015-06-03 15:47:11 +02002863
Radek Krejcia9544502015-08-14 08:24:29 +02002864 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002865
2866 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002867 goto error;
2868 }
2869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002870 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002871 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2872 /* garbage */
2873 lyxml_free_elem(module->ctx, sub);
2874 continue;
2875 }
2876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002877 if (!strcmp(sub->name, "mandatory")) {
2878 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002879 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002880 goto error;
2881 }
2882 /* just checking the flags in leaf is not sufficient, we would allow
2883 * multiple mandatory statements with the "false" value
2884 */
2885 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002887 GETVAL(value, sub, "value");
2888 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002889 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002890 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002891 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002892 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002893 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002894 goto error;
2895 }
2896 /* else false is the default value, so we can ignore it */
2897 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002898 } else if (!strcmp(sub->name, "when")) {
2899 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002900 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002901 goto error;
2902 }
2903
2904 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002905 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002906 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002907 goto error;
2908 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002909 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002910 goto error;
2911 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002912 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 } else if (!strcmp(sub->name, "must")) {
2914 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002915 } else if (!strcmp(sub->name, "if-feature")) {
2916 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002918 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002919 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 }
2922 }
Radek Krejci863c2852015-06-03 15:47:11 +02002923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 /* middle part - process nodes with cardinality of 0..n */
2925 if (c_must) {
2926 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2927 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002928 if (c_ftrs) {
2929 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2930 }
Radek Krejci863c2852015-06-03 15:47:11 +02002931
Radek Krejci73adb602015-07-02 18:07:40 +02002932 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002933 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002934 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002935 if (r) {
2936 goto error;
2937 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002938 if (unres_schema_add_node(module, unres, &anyxml->must[anyxml->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002939 goto error;
2940 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002941 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002942 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002943 if (unres_schema_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002944 goto error;
2945 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 }
Radek Krejci863c2852015-06-03 15:47:11 +02002948
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002950
2951error:
2952
Radek Krejci1d82ef62015-08-07 14:44:40 +02002953 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002956}
2957
Michal Vasko0d343d12015-08-24 14:57:36 +02002958/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002959static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002960read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002961 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002962{
Radek Krejci76512572015-08-04 09:47:08 +02002963 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002964 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002965 struct lyxml_elem *sub, *next;
2966 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002967 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002968 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002970 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002971 leaf->nodetype = LYS_LEAF;
2972 leaf->prev = (struct lys_node *)leaf;
2973 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002974
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002975 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2976 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002977 goto error;
2978 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002979
Radek Krejcia9544502015-08-14 08:24:29 +02002980 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002981
2982 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002983 goto error;
2984 }
2985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002987 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2988 /* garbage */
2989 lyxml_free_elem(module->ctx, sub);
2990 continue;
2991 }
2992
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002994 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002995 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002996 goto error;
2997 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002998 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 goto error;
3000 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003001 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 } else if (!strcmp(sub->name, "default")) {
3003 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003004 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003005 goto error;
3006 }
3007 GETVAL(value, sub, "value");
3008 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003009 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 } else if (!strcmp(sub->name, "units")) {
3011 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003012 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 goto error;
3014 }
3015 GETVAL(value, sub, "name");
3016 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3017 } else if (!strcmp(sub->name, "mandatory")) {
3018 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003019 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003020 goto error;
3021 }
3022 /* just checking the flags in leaf is not sufficient, we would allow
3023 * multiple mandatory statements with the "false" value
3024 */
3025 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003026
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 GETVAL(value, sub, "value");
3028 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003029 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003030 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003031 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003032 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003033 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 goto error;
3035 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003036 } else if (!strcmp(sub->name, "when")) {
3037 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003038 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003039 goto error;
3040 }
3041
3042 leaf->when = read_yin_when(module, sub);
3043 if (!leaf->when) {
3044 goto error;
3045 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003046 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003047 goto error;
3048 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003051 c_must++;
3052 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003053 } else if (!strcmp(sub->name, "if-feature")) {
3054 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003055 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003058 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003062 lyxml_free_elem(module->ctx, sub);
3063 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003064
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003066 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003067 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 goto error;
3069 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003070 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003071 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003072 goto error;
3073 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003074 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003075
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 /* middle part - process nodes with cardinality of 0..n */
3077 if (c_must) {
3078 leaf->must = calloc(c_must, sizeof *leaf->must);
3079 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003080 if (c_ftrs) {
3081 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3082 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003083
Radek Krejci73adb602015-07-02 18:07:40 +02003084 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003085 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003086 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 if (r) {
3088 goto error;
3089 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003090 if (unres_schema_add_node(module, unres, &leaf->must[leaf->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003091 goto error;
3092 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003093 } else if (!strcmp(sub->name, "if-feature")) {
3094 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003095 if (unres_schema_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003096 goto error;
3097 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003098 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003101 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003102
3103error:
3104
Radek Krejci1d82ef62015-08-07 14:44:40 +02003105 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003108}
3109
Michal Vasko0d343d12015-08-24 14:57:36 +02003110/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003111static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003112read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003113 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003114{
Radek Krejci76512572015-08-04 09:47:08 +02003115 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003116 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 struct lyxml_elem *sub, *next;
3118 const char *value;
3119 char *endptr;
3120 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003121 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003122 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003126 llist->nodetype = LYS_LEAFLIST;
3127 llist->prev = (struct lys_node *)llist;
3128 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003129
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003130 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3131 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 goto error;
3133 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003134
Radek Krejcia9544502015-08-14 08:24:29 +02003135 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003136
3137 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003138 goto error;
3139 }
3140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003141 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003142 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3143 /* garbage */
3144 lyxml_free_elem(module->ctx, sub);
3145 continue;
3146 }
3147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003149 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003150 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 goto error;
3152 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003153 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003154 goto error;
3155 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003156 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 } else if (!strcmp(sub->name, "units")) {
3158 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003159 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003160 goto error;
3161 }
3162 GETVAL(value, sub, "name");
3163 llist->units = lydict_insert(module->ctx, value, strlen(value));
3164 } else if (!strcmp(sub->name, "ordered-by")) {
3165 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003166 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 goto error;
3168 }
3169 /* just checking the flags in llist is not sufficient, we would
3170 * allow multiple ordered-by statements with the "system" value
3171 */
3172 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003173
Radek Krejci1574a8d2015-08-03 14:16:52 +02003174 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3176 * state data
3177 */
3178 lyxml_free_elem(module->ctx, sub);
3179 continue;
3180 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 GETVAL(value, sub, "value");
3183 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003184 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003186 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003187 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003188 } /* else system is the default value, so we can ignore it */
3189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003190 } else if (!strcmp(sub->name, "must")) {
3191 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003192 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003193 } else if (!strcmp(sub->name, "if-feature")) {
3194 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 } else if (!strcmp(sub->name, "min-elements")) {
3198 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003199 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 goto error;
3201 }
3202 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 GETVAL(value, sub, "value");
3205 while (isspace(value[0])) {
3206 value++;
3207 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003209 /* convert it to uint32_t */
3210 errno = 0;
3211 endptr = NULL;
3212 val = strtoul(value, &endptr, 10);
3213 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003214 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 goto error;
3216 }
3217 llist->min = (uint32_t) val;
3218 } else if (!strcmp(sub->name, "max-elements")) {
3219 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003220 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 goto error;
3222 }
3223 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 GETVAL(value, sub, "value");
3226 while (isspace(value[0])) {
3227 value++;
3228 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003229
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003230 /* convert it to uint32_t */
3231 errno = 0;
3232 endptr = NULL;
3233 val = strtoul(value, &endptr, 10);
3234 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003235 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 goto error;
3237 }
3238 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003239 } else if (!strcmp(sub->name, "when")) {
3240 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003241 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003242 goto error;
3243 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003244
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003245 llist->when = read_yin_when(module, sub);
3246 if (!llist->when) {
3247 goto error;
3248 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003249 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003250 goto error;
3251 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003252 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003253 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 lyxml_free_elem(module->ctx, sub);
3258 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003261 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003262 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 goto error;
3264 }
3265 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003266 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 goto error;
3268 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003270 /* middle part - process nodes with cardinality of 0..n */
3271 if (c_must) {
3272 llist->must = calloc(c_must, sizeof *llist->must);
3273 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003274 if (c_ftrs) {
3275 llist->features = calloc(c_ftrs, sizeof *llist->features);
3276 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003277
Radek Krejci73adb602015-07-02 18:07:40 +02003278 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003279 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003280 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 if (r) {
3282 goto error;
3283 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003284 if (unres_schema_add_node(module, unres, &llist->must[llist->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003285 goto error;
3286 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003287 } else if (!strcmp(sub->name, "if-feature")) {
3288 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003289 if (unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003290 LOGLINE(sub)) == -1) {
3291 goto error;
3292 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003297
3298error:
3299
Radek Krejci1d82ef62015-08-07 14:44:40 +02003300 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003303}
3304
Michal Vasko0d343d12015-08-24 14:57:36 +02003305/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003306static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003307read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3308 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003309{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003310 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003311 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003313 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003314 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003315 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003316 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003317 char *auxs;
3318 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003320 /* init */
3321 memset(&root, 0, sizeof root);
3322 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003325 list->nodetype = LYS_LIST;
3326 list->prev = (struct lys_node *)list;
3327 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003328
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003329 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3330 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003331 goto error;
3332 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003333
Radek Krejcia9544502015-08-14 08:24:29 +02003334 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 /* process list's specific children */
3337 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003338 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3339 /* garbage */
3340 lyxml_free_elem(module->ctx, sub);
3341 continue;
3342 }
3343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 /* data statements */
3345 if (!strcmp(sub->name, "container") ||
3346 !strcmp(sub->name, "leaf-list") ||
3347 !strcmp(sub->name, "leaf") ||
3348 !strcmp(sub->name, "list") ||
3349 !strcmp(sub->name, "choice") ||
3350 !strcmp(sub->name, "uses") ||
3351 !strcmp(sub->name, "grouping") ||
3352 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003353 lyxml_unlink_elem(module->ctx, sub, 1);
3354 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 /* array counters */
3357 } else if (!strcmp(sub->name, "key")) {
3358 /* check cardinality 0..1 */
3359 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003360 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003361 goto error;
3362 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 /* count the number of keys */
3365 GETVAL(value, sub, "value");
3366 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003367 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 while ((value = strpbrk(value, " \t\n"))) {
3369 list->keys_size++;
3370 while (isspace(*value)) {
3371 value++;
3372 }
3373 }
3374 list->keys_size++;
3375 list->keys = calloc(list->keys_size, sizeof *list->keys);
3376 } else if (!strcmp(sub->name, "unique")) {
3377 c_uniq++;
Michal Vaskof8879c22015-08-21 09:07:36 +02003378 lyxml_unlink_elem(module->ctx, sub, 1);
3379 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 } else if (!strcmp(sub->name, "typedef")) {
3381 c_tpdf++;
3382 } else if (!strcmp(sub->name, "must")) {
3383 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003384 } else if (!strcmp(sub->name, "if-feature")) {
3385 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 /* optional stetments */
3388 } else if (!strcmp(sub->name, "ordered-by")) {
3389 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003390 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 goto error;
3392 }
3393 /* just checking the flags in llist is not sufficient, we would
3394 * allow multiple ordered-by statements with the "system" value
3395 */
3396 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003397
Radek Krejci1574a8d2015-08-03 14:16:52 +02003398 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003399 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3400 * state data
3401 */
3402 lyxml_free_elem(module->ctx, sub);
3403 continue;
3404 }
Radek Krejci345ad742015-06-03 11:04:18 +02003405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 GETVAL(value, sub, "value");
3407 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003408 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003410 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 goto error;
3412 }
3413 /* else system is the default value, so we can ignore it */
3414 lyxml_free_elem(module->ctx, sub);
3415 } else if (!strcmp(sub->name, "min-elements")) {
3416 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003417 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003418 goto error;
3419 }
3420 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 GETVAL(value, sub, "value");
3423 while (isspace(value[0])) {
3424 value++;
3425 }
Radek Krejci345ad742015-06-03 11:04:18 +02003426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003427 /* convert it to uint32_t */
3428 errno = 0;
3429 auxs = NULL;
3430 val = strtoul(value, &auxs, 10);
3431 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003432 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 goto error;
3434 }
3435 list->min = (uint32_t) val;
3436 lyxml_free_elem(module->ctx, sub);
3437 } else if (!strcmp(sub->name, "max-elements")) {
3438 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003439 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 goto error;
3441 }
3442 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003443
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 GETVAL(value, sub, "value");
3445 while (isspace(value[0])) {
3446 value++;
3447 }
Radek Krejci345ad742015-06-03 11:04:18 +02003448
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 /* convert it to uint32_t */
3450 errno = 0;
3451 auxs = NULL;
3452 val = strtoul(value, &auxs, 10);
3453 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003454 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003455 goto error;
3456 }
3457 list->max = (uint32_t) val;
3458 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003459 } else if (!strcmp(sub->name, "when")) {
3460 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003461 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003462 goto error;
3463 }
3464
3465 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003466 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003467 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003468 goto error;
3469 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003470 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003471 goto error;
3472 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003473 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003474 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003475 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003476 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003477 }
3478 }
Radek Krejci345ad742015-06-03 11:04:18 +02003479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003481 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003482 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 goto error;
3484 }
3485 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003486 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 goto error;
3488 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003489
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3491 if (c_tpdf) {
3492 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3493 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003494 if (c_must) {
3495 list->must = calloc(c_must, sizeof *list->must);
3496 }
3497 if (c_ftrs) {
3498 list->features = calloc(c_ftrs, sizeof *list->features);
3499 }
Radek Krejci73adb602015-07-02 18:07:40 +02003500 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003501 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003502 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003503
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003504 if (r) {
3505 goto error;
3506 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003507 } else if (!strcmp(sub->name, "if-feature")) {
3508 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003509 if (unres_schema_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003510 goto error;
3511 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003512 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003513 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003514 if (r) {
3515 goto error;
3516 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003517 if (unres_schema_add_node(module, unres, &list->must[list->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003518 goto error;
3519 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 }
3521 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003522
Radek Krejci10c760e2015-08-14 14:45:43 +02003523 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003524 goto error;
3525 }
3526
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003527 /* last part - process data nodes */
3528 LY_TREE_FOR_SAFE(root.child, next, sub) {
3529 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003530 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003532 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003533 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003534 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003536 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003538 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003540 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003542 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003544 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003545 } else {
3546 LOGINT;
3547 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003548 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003549 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 goto error;
3551 }
Radek Krejci73adb602015-07-02 18:07:40 +02003552
3553 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003555
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 if (!key_str) {
3557 /* config false list without a key */
3558 return retval;
3559 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003560 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003561 goto error;
3562 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 /* process unique statements */
3565 if (c_uniq) {
3566 list->unique = calloc(c_uniq, sizeof *list->unique);
3567 }
3568 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003569 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003570 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003571 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003572 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003573 LOGLINE(sub)) == -1) {
3574 goto error;
3575 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003577 lyxml_free_elem(module->ctx, sub);
3578 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003581
3582error:
3583
Radek Krejci1d82ef62015-08-07 14:44:40 +02003584 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003585 while (root.child) {
3586 lyxml_free_elem(module->ctx, root.child);
3587 }
3588 while (uniq.child) {
3589 lyxml_free_elem(module->ctx, uniq.child);
3590 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003591
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003593}
3594
Michal Vasko0d343d12015-08-24 14:57:36 +02003595/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003596static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003597read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3598 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003599{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003601 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003602 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003603 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 const char *value;
3605 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003606 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 /* init */
3609 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003611 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003612 cont->nodetype = LYS_CONTAINER;
3613 cont->prev = (struct lys_node *)cont;
3614 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003615
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003616 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3617 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 goto error;
3619 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003620
Radek Krejcia9544502015-08-14 08:24:29 +02003621 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3622
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003623 /* process container's specific children */
3624 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003625 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003626 /* garbage */
3627 lyxml_free_elem(module->ctx, sub);
3628 continue;
3629 }
3630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 if (!strcmp(sub->name, "presence")) {
3632 if (cont->presence) {
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 GETVAL(value, sub, "value");
3637 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003638
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003640 } else if (!strcmp(sub->name, "when")) {
3641 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003642 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003643 goto error;
3644 }
3645
3646 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003647 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003648 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003649 goto error;
3650 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003651 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003652 goto error;
3653 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003654 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 /* data statements */
3657 } else if (!strcmp(sub->name, "container") ||
3658 !strcmp(sub->name, "leaf-list") ||
3659 !strcmp(sub->name, "leaf") ||
3660 !strcmp(sub->name, "list") ||
3661 !strcmp(sub->name, "choice") ||
3662 !strcmp(sub->name, "uses") ||
3663 !strcmp(sub->name, "grouping") ||
3664 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003665 lyxml_unlink_elem(module->ctx, sub, 1);
3666 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 /* array counters */
3669 } else if (!strcmp(sub->name, "typedef")) {
3670 c_tpdf++;
3671 } else if (!strcmp(sub->name, "must")) {
3672 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003673 } else if (!strcmp(sub->name, "if-feature")) {
3674 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003676 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003678 }
3679 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3682 if (c_tpdf) {
3683 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3684 }
3685 if (c_must) {
3686 cont->must = calloc(c_must, sizeof *cont->must);
3687 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003688 if (c_ftrs) {
3689 cont->features = calloc(c_ftrs, sizeof *cont->features);
3690 }
Radek Krejci800af702015-06-02 13:46:01 +02003691
Radek Krejci73adb602015-07-02 18:07:40 +02003692 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003693 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003694 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 if (r) {
3696 goto error;
3697 }
3698 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003699 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 if (r) {
3701 goto error;
3702 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003703 if (unres_schema_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003704 LOGLINE(sub)) == -1) {
3705 goto error;
3706 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003707 } else if (!strcmp(sub->name, "if-feature")) {
3708 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003709 if (unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003710 LOGLINE(sub)) == -1) {
3711 goto error;
3712 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003713 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003715
Radek Krejci10c760e2015-08-14 14:45:43 +02003716 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003717 goto error;
3718 }
3719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 /* last part - process data nodes */
3721 LY_TREE_FOR_SAFE(root.child, next, sub) {
3722 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003723 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003725 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003727 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003729 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003731 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003733 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003735 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 goto error;
3741 }
Radek Krejci73adb602015-07-02 18:07:40 +02003742
3743 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003747
3748error:
3749
Radek Krejci1d82ef62015-08-07 14:44:40 +02003750 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003751 while (root.child) {
3752 lyxml_free_elem(module->ctx, root.child);
3753 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003756}
3757
Michal Vasko0d343d12015-08-24 14:57:36 +02003758/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003759static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003760read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003761 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003762{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003764 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003765 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003766 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 int r;
3768 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003770 /* init */
3771 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003774 grp->nodetype = LYS_GROUPING;
3775 grp->prev = (struct lys_node *)grp;
3776 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003777
Michal Vasko71e1aa82015-08-12 12:17:51 +02003778 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003779 goto error;
3780 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Radek Krejcia9544502015-08-14 08:24:29 +02003782 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3783
Radek Krejci1d82ef62015-08-07 14:44:40 +02003784 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003785 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3786 /* garbage */
3787 lyxml_free_elem(module->ctx, sub);
3788 continue;
3789 }
3790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003791 /* data statements */
3792 if (!strcmp(sub->name, "container") ||
3793 !strcmp(sub->name, "leaf-list") ||
3794 !strcmp(sub->name, "leaf") ||
3795 !strcmp(sub->name, "list") ||
3796 !strcmp(sub->name, "choice") ||
3797 !strcmp(sub->name, "uses") ||
3798 !strcmp(sub->name, "grouping") ||
3799 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003800 lyxml_unlink_elem(module->ctx, sub, 1);
3801 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003802
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 /* array counters */
3804 } else if (!strcmp(sub->name, "typedef")) {
3805 c_tpdf++;
3806 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003807 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003808 goto error;
3809 }
3810 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3813 if (c_tpdf) {
3814 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3815 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003816 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003817 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003818
Radek Krejci73adb602015-07-02 18:07:40 +02003819 if (r) {
3820 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003823
Radek Krejci10c760e2015-08-14 14:45:43 +02003824 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003825 goto error;
3826 }
3827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 /* last part - process data nodes */
3829 LY_TREE_FOR_SAFE(root.child, next, sub) {
3830 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003831 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003833 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003835 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003837 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003839 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003841 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003843 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003845 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003847 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 goto error;
3849 }
Radek Krejci73adb602015-07-02 18:07:40 +02003850
3851 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003854 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003855
3856error:
3857
Radek Krejci1d82ef62015-08-07 14:44:40 +02003858 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 while (root.child) {
3860 lyxml_free_elem(module->ctx, root.child);
3861 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003864}
3865
Michal Vasko0d343d12015-08-24 14:57:36 +02003866/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003867static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003868read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3869 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003870{
Radek Krejcie0674f82015-06-15 13:58:51 +02003871 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003872 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003873 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003874 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003875 int r;
3876 int c_tpdf = 0;
3877
Radek Krejcie0674f82015-06-15 13:58:51 +02003878 /* init */
3879 memset(&root, 0, sizeof root);
3880
Michal Vasko38d01f72015-06-15 09:41:06 +02003881 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003882 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003883
3884 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003885 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003886 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003887 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003888 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003889 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003890 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003891 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003892 }
3893
Radek Krejci76512572015-08-04 09:47:08 +02003894 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003895
Radek Krejci6a113852015-07-03 16:04:20 +02003896 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003897 goto error;
3898 }
3899
Radek Krejcia9544502015-08-14 08:24:29 +02003900 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3901
Michal Vasko38d01f72015-06-15 09:41:06 +02003902 /* data statements */
3903 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003904 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3905 /* garbage */
3906 lyxml_free_elem(module->ctx, sub);
3907 continue;
3908 }
3909
Michal Vasko38d01f72015-06-15 09:41:06 +02003910 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003911 !strcmp(sub->name, "leaf-list") ||
3912 !strcmp(sub->name, "leaf") ||
3913 !strcmp(sub->name, "list") ||
3914 !strcmp(sub->name, "choice") ||
3915 !strcmp(sub->name, "uses") ||
3916 !strcmp(sub->name, "grouping") ||
3917 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003918 lyxml_unlink_elem(module->ctx, sub, 1);
3919 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003921 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003922 } else if (!strcmp(sub->name, "typedef")) {
3923 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003924
Michal Vasko38d01f72015-06-15 09:41:06 +02003925 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003926 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003927 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003928 }
3929 }
3930
3931 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3932 if (c_tpdf) {
3933 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3934 }
3935
Radek Krejci73adb602015-07-02 18:07:40 +02003936 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003937 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003938
Radek Krejci73adb602015-07-02 18:07:40 +02003939 if (r) {
3940 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003941 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003942 }
3943
Radek Krejci10c760e2015-08-14 14:45:43 +02003944 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003945 goto error;
3946 }
3947
Michal Vasko38d01f72015-06-15 09:41:06 +02003948 /* last part - process data nodes */
3949 LY_TREE_FOR_SAFE(root.child, next, sub) {
3950 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003951 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003952 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003953 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003954 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003956 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003957 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003958 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003960 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003962 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003964 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003966 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003967 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003968 goto error;
3969 }
Radek Krejci73adb602015-07-02 18:07:40 +02003970
3971 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003972 }
3973
Michal Vasko38d01f72015-06-15 09:41:06 +02003974 return retval;
3975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003976error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003977
Radek Krejci1d82ef62015-08-07 14:44:40 +02003978 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003979 while (root.child) {
3980 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003981 }
3982
3983 return NULL;
3984}
3985
Michal Vasko0d343d12015-08-24 14:57:36 +02003986/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003987static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003988read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3989 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003990{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003991 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003992 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003993 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003994 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003995 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003996 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003997 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003998
Michal Vaskoc6551b32015-06-16 10:51:43 +02003999 memset(&root, 0, sizeof root);
4000
Michal Vasko0ea41032015-06-16 08:53:55 +02004001 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004002 notif->nodetype = LYS_NOTIF;
4003 notif->prev = (struct lys_node *)notif;
4004 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004005
Radek Krejci6a113852015-07-03 16:04:20 +02004006 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004007 goto error;
4008 }
4009
Radek Krejcia9544502015-08-14 08:24:29 +02004010 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4011
Michal Vasko0ea41032015-06-16 08:53:55 +02004012 /* process rpc's specific children */
4013 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004014 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4015 /* garbage */
4016 lyxml_free_elem(module->ctx, sub);
4017 continue;
4018 }
4019
Michal Vasko0ea41032015-06-16 08:53:55 +02004020 /* data statements */
4021 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004022 !strcmp(sub->name, "leaf-list") ||
4023 !strcmp(sub->name, "leaf") ||
4024 !strcmp(sub->name, "list") ||
4025 !strcmp(sub->name, "choice") ||
4026 !strcmp(sub->name, "uses") ||
4027 !strcmp(sub->name, "grouping") ||
4028 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004029 lyxml_unlink_elem(module->ctx, sub, 1);
4030 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004032 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004033 } else if (!strcmp(sub->name, "typedef")) {
4034 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004035 } else if (!strcmp(sub->name, "if-feature")) {
4036 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004037 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004038 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004039 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004040 }
4041 }
4042
4043 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4044 if (c_tpdf) {
4045 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4046 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004047 if (c_ftrs) {
4048 notif->features = calloc(c_ftrs, sizeof *notif->features);
4049 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004050
Radek Krejci73adb602015-07-02 18:07:40 +02004051 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004052 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004053 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004054
4055 if (r) {
4056 goto error;
4057 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004058 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004059 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004060 if (unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004061 LOGLINE(sub)) == -1) {
4062 goto error;
4063 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004064 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004065 }
4066
Radek Krejci10c760e2015-08-14 14:45:43 +02004067 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004068 goto error;
4069 }
4070
Michal Vasko0ea41032015-06-16 08:53:55 +02004071 /* last part - process data nodes */
4072 LY_TREE_FOR_SAFE(root.child, next, sub) {
4073 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004074 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004075 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004076 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004077 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004079 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004081 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004083 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004084 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004085 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004087 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004088 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004089 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004090 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004091 goto error;
4092 }
Radek Krejci73adb602015-07-02 18:07:40 +02004093
4094 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004095 }
4096
Michal Vasko0ea41032015-06-16 08:53:55 +02004097 return retval;
4098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004099error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004100
Radek Krejci1d82ef62015-08-07 14:44:40 +02004101 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004102 while (root.child) {
4103 lyxml_free_elem(module->ctx, root.child);
4104 }
4105
4106 return NULL;
4107}
4108
Michal Vasko0d343d12015-08-24 14:57:36 +02004109/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004110static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004111read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4112 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004113{
Radek Krejcie0674f82015-06-15 13:58:51 +02004114 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004115 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004116 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004117 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004118 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004119 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004120 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004121
Radek Krejcie0674f82015-06-15 13:58:51 +02004122 /* init */
4123 memset(&root, 0, sizeof root);
4124
Michal Vasko38d01f72015-06-15 09:41:06 +02004125 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004126 rpc->nodetype = LYS_RPC;
4127 rpc->prev = (struct lys_node *)rpc;
4128 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004129
Radek Krejci6a113852015-07-03 16:04:20 +02004130 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 goto error;
4132 }
4133
Radek Krejcia9544502015-08-14 08:24:29 +02004134 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4135
Michal Vasko38d01f72015-06-15 09:41:06 +02004136 /* process rpc's specific children */
4137 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004138 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4139 /* garbage */
4140 lyxml_free_elem(module->ctx, sub);
4141 continue;
4142 }
4143
Michal Vasko38d01f72015-06-15 09:41:06 +02004144 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004146 && (rpc->child->nodetype == LYS_INPUT
4147 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004148 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004149 goto error;
4150 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004151 lyxml_unlink_elem(module->ctx, sub, 1);
4152 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004155 && (rpc->child->nodetype == LYS_INPUT
4156 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004157 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004158 goto error;
4159 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004160 lyxml_unlink_elem(module->ctx, sub, 1);
4161 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004163 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004164 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004165 lyxml_unlink_elem(module->ctx, sub, 1);
4166 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004167
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004169 } else if (!strcmp(sub->name, "typedef")) {
4170 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004171 } else if (!strcmp(sub->name, "if-feature")) {
4172 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004174 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004175 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004176 }
4177 }
4178
4179 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4180 if (c_tpdf) {
4181 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4182 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004183 if (c_ftrs) {
4184 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4185 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004186
Radek Krejci73adb602015-07-02 18:07:40 +02004187 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004188 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004189 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004190
4191 if (r) {
4192 goto error;
4193 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004194 } else if (!strcmp(sub->name, "if-feature")) {
4195 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004196 if (unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004197 LOGLINE(sub)) == -1) {
4198 goto error;
4199 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004200 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004201 }
4202
Radek Krejci10c760e2015-08-14 14:45:43 +02004203 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004204 goto error;
4205 }
4206
Michal Vasko38d01f72015-06-15 09:41:06 +02004207 /* last part - process data nodes */
4208 LY_TREE_FOR_SAFE(root.child, next, sub) {
4209 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004210 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004211 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004212 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004213 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004215 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004216 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004217 goto error;
4218 }
Radek Krejci73adb602015-07-02 18:07:40 +02004219
4220 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 }
4222
Michal Vasko38d01f72015-06-15 09:41:06 +02004223 return retval;
4224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004226
Radek Krejci1d82ef62015-08-07 14:44:40 +02004227 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004228 while (root.child) {
4229 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004230 }
4231
4232 return NULL;
4233}
4234
Michal Vasko0d343d12015-08-24 14:57:36 +02004235/* logs directly
4236 *
Radek Krejci74705112015-06-05 10:25:44 +02004237 * resolve - referenced grouping should be bounded to the namespace (resolved)
4238 * only when uses does not appear in grouping. In a case of grouping's uses,
4239 * we just get information but we do not apply augment or refine to it.
4240 */
Radek Krejci76512572015-08-04 09:47:08 +02004241static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004242read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004243 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004244{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004246 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004247 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004249 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004250 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004253 uses->nodetype = LYS_USES;
4254 uses->prev = (struct lys_node *)uses;
4255 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004256
Radek Krejcia9544502015-08-14 08:24:29 +02004257 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004258 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004259
Radek Krejcia9544502015-08-14 08:24:29 +02004260 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004261 goto error;
4262 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004263
Radek Krejcia9544502015-08-14 08:24:29 +02004264 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004266 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004267 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004268 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4269 /* garbage */
4270 lyxml_free_elem(module->ctx, sub);
4271 continue;
4272 }
4273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004274 if (!strcmp(sub->name, "refine")) {
4275 c_ref++;
4276 } else if (!strcmp(sub->name, "augment")) {
4277 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004278 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004279 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004280 } else if (!strcmp(sub->name, "when")) {
4281 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004282 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004283 goto error;
4284 }
4285
4286 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004287 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004288 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004289 goto error;
4290 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02004291 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004292 goto error;
4293 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004294 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004296 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004297 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 }
4299 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004301 /* process properties with cardinality 0..n */
4302 if (c_ref) {
4303 uses->refine = calloc(c_ref, sizeof *uses->refine);
4304 }
4305 if (c_aug) {
4306 uses->augment = calloc(c_aug, sizeof *uses->augment);
4307 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004308 if (c_ftrs) {
4309 uses->features = calloc(c_ftrs, sizeof *uses->features);
4310 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004311
Radek Krejci10c760e2015-08-14 14:45:43 +02004312 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004313 goto error;
4314 }
4315
Radek Krejcia9544502015-08-14 08:24:29 +02004316 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004318 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4319 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004320 goto error;
4321 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004322 } else if (!strcmp(sub->name, "augment")) {
4323 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4324 if (r) {
4325 goto error;
4326 }
4327 } else if (!strcmp(sub->name, "if-feature")) {
4328 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004329 if (unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004330 LOGLINE(sub)) == -1) {
4331 goto error;
4332 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004333 }
4334 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004335
Michal Vasko0bd29d12015-08-19 11:45:49 +02004336 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004337 goto error;
4338 }
Radek Krejci74705112015-06-05 10:25:44 +02004339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004340 if (resolve) {
4341 /* inherit config flag */
4342 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004343 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 } else {
4345 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004346 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004347 }
4348 }
Radek Krejcib388c152015-06-04 17:03:03 +02004349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004351
4352error:
4353
Radek Krejci1d82ef62015-08-07 14:44:40 +02004354 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004355
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004357}
4358
Michal Vasko0d343d12015-08-24 14:57:36 +02004359/* logs directly
4360 *
4361 * common code for yin_read_module() and yin_read_submodule()
4362 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004363static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004364read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004365{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004367 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004368 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4369 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004371 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004372 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004373 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004374 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 +02004375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 /* init */
4377 memset(&root, 0, sizeof root);
4378 memset(&grps, 0, sizeof grps);
4379 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004380 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004381
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 /*
4383 * in the first run, we process elements with cardinality of 1 or 0..1 and
4384 * count elements with cardinality 0..n. Data elements (choices, containers,
4385 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4386 * need have all top-level and groupings already prepared at that time. In
4387 * the middle loop, we process other elements with carinality of 0..n since
4388 * we need to allocate arrays to store them.
4389 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004390 LY_TREE_FOR_SAFE(yin->child, next, child) {
4391 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004392 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004393 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 continue;
4395 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004396
Radek Krejci1d82ef62015-08-07 14:44:40 +02004397 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004398 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004399 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004402 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004404 lyxml_free_elem(ctx, child);
4405 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004406 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004407 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 goto error;
4409 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004410 GETVAL(value, child, "value");
4411 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 goto error;
4413 }
4414 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004415 lyxml_free_elem(ctx, child);
4416 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004417 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004418 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 goto error;
4420 }
4421 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004422 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004424 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004425 }
4426 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004427 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004428 goto error;
4429 }
Radek Krejcif3886932015-06-04 17:36:06 +02004430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004431 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004432 if (!child->child) {
4433 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004434 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004435 } else if (strcmp(child->child->name, "prefix")) {
4436 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004437 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004438 } else if (child->child->next) {
4439 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 goto error;
4441 }
4442 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004443 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 /* check here differs from a generic prefix check, since this prefix
4445 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004446 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004447 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 goto error;
4449 }
4450 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004453 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004454
4455 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004456 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004457 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004458 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004460 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004462 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004464 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004466 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004467 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004468 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004469 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004470 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004471 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004472
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004473 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004474 } else if (!strcmp(child->name, "container") ||
4475 !strcmp(child->name, "leaf-list") ||
4476 !strcmp(child->name, "leaf") ||
4477 !strcmp(child->name, "list") ||
4478 !strcmp(child->name, "choice") ||
4479 !strcmp(child->name, "uses") ||
4480 !strcmp(child->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004481 lyxml_unlink_elem(module->ctx, child, 1);
4482 lyxml_add_child(module->ctx, &root, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 /* keep groupings separated and process them before other data statements */
Michal Vaskof8879c22015-08-21 09:07:36 +02004485 lyxml_unlink_elem(module->ctx, child, 1);
4486 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004489 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004490 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004491 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 goto error;
4493 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004494 module->dsc = read_yin_subnode(ctx, child, "text");
4495 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 if (!module->dsc) {
4497 goto error;
4498 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004499 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004501 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004502 goto error;
4503 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004504 module->ref = read_yin_subnode(ctx, child, "text");
4505 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 if (!module->ref) {
4507 goto error;
4508 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004509 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 goto error;
4513 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004514 module->org = read_yin_subnode(ctx, child, "text");
4515 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 if (!module->org) {
4517 goto error;
4518 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004519 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004521 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 goto error;
4523 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004524 module->contact = read_yin_subnode(ctx, child, "text");
4525 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 if (!module->contact) {
4527 goto error;
4528 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004529 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 /* TODO: support YANG 1.1 ? */
4531 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004532 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 goto error;
4534 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004535 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004537 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004538 goto error;
4539 }
4540 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004541 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004543 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004544 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004545 lyxml_unlink_elem(module->ctx, child, 1);
4546 lyxml_add_child(module->ctx, &rpcs, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004547 } else if (!strcmp(child->name, "notification")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004548 lyxml_unlink_elem(module->ctx, child, 1);
4549 lyxml_add_child(module->ctx, &notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004550
Radek Krejci1d82ef62015-08-07 14:44:40 +02004551 } else if (!strcmp(child->name, "extension")) {
4552 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004553
Radek Krejci6764bb32015-07-03 15:16:04 +02004554 /* we have 2 supported (hardcoded) extensions:
4555 * NACM's default-deny-write and default-deny-all
4556 */
4557 if (strcmp(module->ns, LY_NSNACM) ||
4558 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4559 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004560 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004561 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004563 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004564 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 }
4566 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 if (!submodule) {
4569 /* check for mandatory statements */
4570 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004571 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 goto error;
4573 }
4574 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004575 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 goto error;
4577 }
4578 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 /* allocate arrays for elements with cardinality of 0..n */
4581 if (c_imp) {
4582 module->imp = calloc(c_imp, sizeof *module->imp);
4583 }
4584 if (c_rev) {
4585 module->rev = calloc(c_rev, sizeof *module->rev);
4586 }
4587 if (c_tpdf) {
4588 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4589 }
4590 if (c_ident) {
4591 module->ident = calloc(c_ident, sizeof *module->ident);
4592 }
4593 if (c_inc) {
4594 module->inc = calloc(c_inc, sizeof *module->inc);
4595 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004596 if (c_aug) {
4597 module->augment = calloc(c_aug, sizeof *module->augment);
4598 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004599 if (c_ftrs) {
4600 module->features = calloc(c_ftrs, sizeof *module->features);
4601 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004602 if (c_dev) {
4603 module->deviation = calloc(c_dev, sizeof *module->deviation);
4604 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004605
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 LY_TREE_FOR(yin->child, child) {
4608 if (!strcmp(child->name, "import")) {
4609 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 module->imp_size++;
4611 if (r) {
4612 goto error;
4613 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 /* check duplicities in imported modules */
4616 for (i = 0; i < module->imp_size - 1; i++) {
4617 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004618 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 goto error;
4620 }
4621 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004622 } else if (!strcmp(child->name, "include")) {
4623 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 module->inc_size++;
4625 if (r) {
4626 goto error;
4627 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004628
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004629 /* check duplications in include submodules */
4630 for (i = 0; i < module->inc_size - 1; i++) {
4631 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004632 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 module->inc[i].submodule->name);
4634 goto error;
4635 }
4636 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004637 } else if (!strcmp(child->name, "revision")) {
4638 GETVAL(value, child, "date");
4639 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 goto error;
4641 }
4642 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4643 /* check uniqueness of the revision date - not required by RFC */
4644 for (i = 0; i < module->rev_size; i++) {
4645 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004646 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004647 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 }
4649 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004650
Radek Krejci1d82ef62015-08-07 14:44:40 +02004651 LY_TREE_FOR(child->child, child2) {
4652 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004653 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004654 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 goto error;
4656 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004657 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 if (!module->rev[module->rev_size].dsc) {
4659 goto error;
4660 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004661 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004663 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004664 goto error;
4665 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004666 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 if (!module->rev[module->rev_size].ref) {
4668 goto error;
4669 }
4670 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004671 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 goto error;
4673 }
4674 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 /* keep the latest revision at position 0 */
4677 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4678 /* switch their position */
4679 value = strdup(module->rev[0].date);
4680 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4681 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4682 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4685 value = module->rev[0].dsc;
4686 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4687 module->rev[module->rev_size].dsc = value;
4688 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4691 value = module->rev[0].ref;
4692 module->rev[0].ref = module->rev[module->rev_size].ref;
4693 module->rev[module->rev_size].ref = value;
4694 }
4695 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 } else if (!strcmp(child->name, "typedef")) {
4699 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004700 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 if (r) {
4703 goto error;
4704 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004705 } else if (!strcmp(child->name, "identity")) {
4706 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 if (r) {
4710 goto error;
4711 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004712 } else if (!strcmp(child->name, "feature")) {
4713 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004714 module->features_size++;
4715
4716 if (r) {
4717 goto error;
4718 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004719 } else if (!strcmp(child->name, "augment")) {
4720 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004721 module->augment_size++;
4722
4723 if (r) {
4724 goto error;
4725 }
4726
4727 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4728 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004729 } else if (!strcmp(child->name, "deviation")) {
4730 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004731 module->deviation_size++;
4732
4733 if (r) {
4734 goto error;
4735 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004736 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004738
Radek Krejcif5be10f2015-06-16 13:29:36 +02004739 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 * refer to them
4741 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004742 LY_TREE_FOR_SAFE(grps.child, next, child) {
4743 node = read_yin_grouping(module, NULL, child, 0, unres);
4744 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 goto error;
4746 }
Radek Krejci74705112015-06-05 10:25:44 +02004747
Radek Krejci1d82ef62015-08-07 14:44:40 +02004748 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 }
Radek Krejci74705112015-06-05 10:25:44 +02004750
Radek Krejcif5be10f2015-06-16 13:29:36 +02004751 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004752 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004753
Radek Krejci1d82ef62015-08-07 14:44:40 +02004754 if (!strcmp(child->name, "container")) {
4755 node = read_yin_container(module, NULL, child, 1, unres);
4756 } else if (!strcmp(child->name, "leaf-list")) {
4757 node = read_yin_leaflist(module, NULL, child, 1, unres);
4758 } else if (!strcmp(child->name, "leaf")) {
4759 node = read_yin_leaf(module, NULL, child, 1, unres);
4760 } else if (!strcmp(child->name, "list")) {
4761 node = read_yin_list(module, NULL, child, 1, unres);
4762 } else if (!strcmp(child->name, "choice")) {
4763 node = read_yin_choice(module, NULL, child, 1, unres);
4764 } else if (!strcmp(child->name, "uses")) {
4765 node = read_yin_uses(module, NULL, child, 1, unres);
4766 } else if (!strcmp(child->name, "anyxml")) {
4767 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004768 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004769 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 goto error;
4771 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004772
Radek Krejci1d82ef62015-08-07 14:44:40 +02004773 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004775
4776 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004777 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4778 node = read_yin_rpc(module, NULL, child, 0, unres);
4779 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004780 goto error;
4781 }
4782
Radek Krejci1d82ef62015-08-07 14:44:40 +02004783 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004784 }
4785
4786 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004787 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4788 node = read_yin_notif(module, NULL, child, 0, unres);
4789 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004790 goto error;
4791 }
4792
Radek Krejci1d82ef62015-08-07 14:44:40 +02004793 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004794 }
4795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004796 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004797
4798error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 /* cleanup */
4800 while (root.child) {
4801 lyxml_free_elem(module->ctx, root.child);
4802 }
4803 while (grps.child) {
4804 lyxml_free_elem(module->ctx, grps.child);
4805 }
4806 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004807 lyxml_free_elem(module->ctx, rpcs.child);
4808 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004809
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004810 free(unres->item);
4811 unres->item = NULL;
4812 free(unres->type);
4813 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004814 free(unres->str_snode);
4815 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004816#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004817 free(unres->line);
4818 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004819#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004820 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004823}
4824
Michal Vasko0d343d12015-08-24 14:57:36 +02004825/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004826struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004827yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004828{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004830 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004834
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 yin = lyxml_read(module->ctx, data, 0);
4836 if (!yin) {
4837 return NULL;
4838 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 /* check root element */
4841 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004842 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 goto error;
4844 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004845
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 GETVAL(value, yin, "name");
4847 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4848 goto error;
4849 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004850
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004851 submodule = calloc(1, sizeof *submodule);
4852 if (!submodule) {
4853 LOGMEM;
4854 goto error;
4855 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004857 submodule->ctx = module->ctx;
4858 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4859 submodule->type = 1;
4860 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004861 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004864 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 goto error;
4866 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004868 /* cleanup */
4869 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004874
4875error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004876 /* cleanup */
4877 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004878 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004881}
4882
Michal Vasko0d343d12015-08-24 14:57:36 +02004883/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004884struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004885yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004886{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004888 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004889 const char *value;
4890 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004891
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004892 yin = lyxml_read(ctx, data, 0);
4893 if (!yin) {
4894 return NULL;
4895 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 /* check root element */
4898 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004899 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004900 goto error;
4901 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 GETVAL(value, yin, "name");
4904 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4905 goto error;
4906 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 module = calloc(1, sizeof *module);
4909 if (!module) {
4910 LOGMEM;
4911 goto error;
4912 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004913
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004914 module->ctx = ctx;
4915 module->name = lydict_insert(ctx, value, strlen(value));
4916 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004917 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004920 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 goto error;
4922 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004923
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 /* add to the context's list of modules */
4925 if (ctx->models.used == ctx->models.size) {
4926 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4927 if (!newlist) {
4928 LOGMEM;
4929 goto error;
4930 }
4931 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4932 newlist[i] = NULL;
4933 }
4934 ctx->models.size *= 2;
4935 ctx->models.list = newlist;
4936 }
4937 for (i = 0; ctx->models.list[i]; i++) {
4938 /* check name (name/revision) and namespace uniqueness */
4939 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004940 if (ctx->models.list[i]->rev_size == module->rev_size) {
4941 /* both have the same number of revisions */
4942 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4943 /* both have the same revision -> we already have the same module */
4944 /* so free the new one and update the old one's implement flag if needed */
4945 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004946 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02004947 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004948
4949 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4950
4951 if (implement && !ctx->models.list[i]->implemented) {
4952 lyp_set_implemented(ctx->models.list[i]);
4953 }
4954 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 }
4956 }
Radek Krejcif647e612015-07-30 11:36:07 +02004957 /* else (both elses) keep searching, for now the caller is just adding
4958 * another revision of an already present schema
4959 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4961 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4962 ctx->models.list[i]->name, module->name, module->ns);
4963 goto error;
4964 }
4965 }
4966 ctx->models.list[i] = module;
4967 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004968 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004969
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004970 /* cleanup */
4971 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004973 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004975 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004976
4977error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004978 /* cleanup */
4979 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004980 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004981
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004983}