blob: d3ac673ef8d499f2c76b02cf83d73493270d811b [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{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002584 struct lyxml_elem *sub, *next;
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
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002614 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002615 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002616 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002617 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002618 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002619 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002620 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002621 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002622 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002624 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002625 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002626 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002627 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002628 } else if (!strcmp(sub->name, "if-feature")) {
2629 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002630 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2631 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002632 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002633 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002634 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002635 goto error;
2636 }
2637
Radek Krejci1d82ef62015-08-07 14:44:40 +02002638 cs->when = read_yin_when(module, sub);
2639 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002640 goto error;
2641 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002642 if (unres_schema_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002643 goto error;
2644 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002646 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002649
Radek Krejci1d82ef62015-08-07 14:44:40 +02002650 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002652 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002653
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 lyxml_free_elem(module->ctx, sub);
2656 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002657
Radek Krejci3cf9e222015-06-18 11:37:50 +02002658 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002659 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002660 }
Radek Krejci73adb602015-07-02 18:07:40 +02002661 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002662 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002663 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 +02002664 goto error;
2665 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002666 }
Radek Krejcib388c152015-06-04 17:03:03 +02002667
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002668 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002669
2670error:
2671
Radek Krejci1d82ef62015-08-07 14:44:40 +02002672 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002675}
2676
Michal Vasko0d343d12015-08-24 14:57:36 +02002677/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002678static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002679read_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 +02002680{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 struct lyxml_elem *sub, *next;
2682 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002683 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002684 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002685 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002686 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002688 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002689 choice->nodetype = LYS_CHOICE;
2690 choice->prev = (struct lys_node *)choice;
2691 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002692
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002693 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2694 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 goto error;
2696 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002697
Radek Krejcia9544502015-08-14 08:24:29 +02002698 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2699
Michal Vasko3a0043f2015-08-12 12:11:30 +02002700 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002701 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002702 goto error;
2703 }
2704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002705 /* process choice's specific children */
2706 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002707 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2708 /* garbage */
2709 lyxml_free_elem(module->ctx, sub);
2710 continue;
2711 }
2712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002713 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002714 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 goto error;
2716 }
2717 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002718 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002719 goto error;
2720 }
2721 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002722 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002723 goto error;
2724 }
2725 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002726 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 goto error;
2728 }
2729 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002730 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 goto error;
2732 }
2733 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002734 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 goto error;
2736 }
2737 } else if (!strcmp(sub->name, "default")) {
2738 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002739 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002740 goto error;
2741 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002742 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002743 } else if (!strcmp(sub->name, "mandatory")) {
2744 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002745 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 goto error;
2747 }
2748 /* just checking the flags in leaf is not sufficient, we would allow
2749 * multiple mandatory statements with the "false" value
2750 */
2751 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 GETVAL(value, sub, "value");
2754 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002755 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002756 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002757 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002758 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002759 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002760 goto error;
2761 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002762 } else if (!strcmp(sub->name, "when")) {
2763 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002764 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002765 goto error;
2766 }
2767
2768 choice->when = read_yin_when(module, sub);
2769 if (!choice->when) {
2770 goto error;
2771 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002772 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002773 goto error;
2774 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002775 } else if (!strcmp(sub->name, "if-feature")) {
2776 c_ftrs++;
2777
2778 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2779 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002780 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002781 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002783 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002784
Radek Krejci1d82ef62015-08-07 14:44:40 +02002785 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 lyxml_free_elem(ctx, sub);
2787 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002788
Radek Krejci3cf9e222015-06-18 11:37:50 +02002789 if (c_ftrs) {
2790 choice->features = calloc(c_ftrs, sizeof *choice->features);
2791 }
2792
Radek Krejci73adb602015-07-02 18:07:40 +02002793 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002794 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002795 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 +02002796 goto error;
2797 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002798 }
2799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002800 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002801 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002802 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002803 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2804 goto error;
2805 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 /* link default with the case */
2808 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002809 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002810 goto error;
2811 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002815
2816error:
2817
Radek Krejci1d82ef62015-08-07 14:44:40 +02002818 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002820 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002821}
2822
Michal Vasko0d343d12015-08-24 14:57:36 +02002823/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002824static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002825read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002826 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002827{
Radek Krejci76512572015-08-04 09:47:08 +02002828 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002829 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 struct lyxml_elem *sub, *next;
2831 const char *value;
2832 int r;
2833 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002834 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002837 anyxml->nodetype = LYS_ANYXML;
2838 anyxml->prev = (struct lys_node *)anyxml;
2839 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002840
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002841 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2842 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 goto error;
2844 }
Radek Krejci863c2852015-06-03 15:47:11 +02002845
Radek Krejcia9544502015-08-14 08:24:29 +02002846 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002847
2848 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002849 goto error;
2850 }
2851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002853 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2854 /* garbage */
2855 lyxml_free_elem(module->ctx, sub);
2856 continue;
2857 }
2858
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002859 if (!strcmp(sub->name, "mandatory")) {
2860 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002861 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 goto error;
2863 }
2864 /* just checking the flags in leaf is not sufficient, we would allow
2865 * multiple mandatory statements with the "false" value
2866 */
2867 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002869 GETVAL(value, sub, "value");
2870 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002871 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002872 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002873 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002874 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002875 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002876 goto error;
2877 }
2878 /* else false is the default value, so we can ignore it */
2879 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002880 } else if (!strcmp(sub->name, "when")) {
2881 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002882 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002883 goto error;
2884 }
2885
2886 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002887 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002888 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002889 goto error;
2890 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002891 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002892 goto error;
2893 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002894 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 } else if (!strcmp(sub->name, "must")) {
2896 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002897 } else if (!strcmp(sub->name, "if-feature")) {
2898 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002900 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002901 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 }
2904 }
Radek Krejci863c2852015-06-03 15:47:11 +02002905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 /* middle part - process nodes with cardinality of 0..n */
2907 if (c_must) {
2908 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2909 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002910 if (c_ftrs) {
2911 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2912 }
Radek Krejci863c2852015-06-03 15:47:11 +02002913
Radek Krejci73adb602015-07-02 18:07:40 +02002914 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002916 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 if (r) {
2918 goto error;
2919 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002920 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 +02002921 goto error;
2922 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002923 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002924 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002925 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 +02002926 goto error;
2927 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 }
Radek Krejci863c2852015-06-03 15:47:11 +02002930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002932
2933error:
2934
Radek Krejci1d82ef62015-08-07 14:44:40 +02002935 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002936
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002938}
2939
Michal Vasko0d343d12015-08-24 14:57:36 +02002940/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002941static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002942read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002943 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002944{
Radek Krejci76512572015-08-04 09:47:08 +02002945 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002946 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 struct lyxml_elem *sub, *next;
2948 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002949 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002950 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002953 leaf->nodetype = LYS_LEAF;
2954 leaf->prev = (struct lys_node *)leaf;
2955 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002956
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002957 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2958 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 goto error;
2960 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002961
Radek Krejcia9544502015-08-14 08:24:29 +02002962 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002963
2964 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002965 goto error;
2966 }
2967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002968 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002969 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2970 /* garbage */
2971 lyxml_free_elem(module->ctx, sub);
2972 continue;
2973 }
2974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002976 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002977 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 goto error;
2979 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002980 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 goto error;
2982 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002983 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002984 } else if (!strcmp(sub->name, "default")) {
2985 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002986 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 goto error;
2988 }
2989 GETVAL(value, sub, "value");
2990 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002991 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002992 } else if (!strcmp(sub->name, "units")) {
2993 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002994 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002995 goto error;
2996 }
2997 GETVAL(value, sub, "name");
2998 leaf->units = lydict_insert(module->ctx, value, strlen(value));
2999 } else if (!strcmp(sub->name, "mandatory")) {
3000 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003001 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 goto error;
3003 }
3004 /* just checking the flags in leaf is not sufficient, we would allow
3005 * multiple mandatory statements with the "false" value
3006 */
3007 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 GETVAL(value, sub, "value");
3010 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003011 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003012 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003013 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003014 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003015 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 goto error;
3017 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003018 } else if (!strcmp(sub->name, "when")) {
3019 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003020 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003021 goto error;
3022 }
3023
3024 leaf->when = read_yin_when(module, sub);
3025 if (!leaf->when) {
3026 goto error;
3027 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003028 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003029 goto error;
3030 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003031
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003033 c_must++;
3034 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003035 } else if (!strcmp(sub->name, "if-feature")) {
3036 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003037 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003038
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003039 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003040 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 lyxml_free_elem(module->ctx, sub);
3045 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003046
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003048 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003049 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 goto error;
3051 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003052 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003053 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003054 goto error;
3055 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 /* middle part - process nodes with cardinality of 0..n */
3059 if (c_must) {
3060 leaf->must = calloc(c_must, sizeof *leaf->must);
3061 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003062 if (c_ftrs) {
3063 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3064 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003065
Radek Krejci73adb602015-07-02 18:07:40 +02003066 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003067 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003068 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 if (r) {
3070 goto error;
3071 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003072 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 +02003073 goto error;
3074 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003075 } else if (!strcmp(sub->name, "if-feature")) {
3076 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003077 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 +02003078 goto error;
3079 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003084
3085error:
3086
Radek Krejci1d82ef62015-08-07 14:44:40 +02003087 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003090}
3091
Michal Vasko0d343d12015-08-24 14:57:36 +02003092/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003093static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003094read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003095 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003096{
Radek Krejci76512572015-08-04 09:47:08 +02003097 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003098 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 struct lyxml_elem *sub, *next;
3100 const char *value;
3101 char *endptr;
3102 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003103 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003104 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003105 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003107 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003108 llist->nodetype = LYS_LEAFLIST;
3109 llist->prev = (struct lys_node *)llist;
3110 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003111
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003112 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3113 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003114 goto error;
3115 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003116
Radek Krejcia9544502015-08-14 08:24:29 +02003117 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003118
3119 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003120 goto error;
3121 }
3122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003123 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003124 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3125 /* garbage */
3126 lyxml_free_elem(module->ctx, sub);
3127 continue;
3128 }
3129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003131 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003132 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 goto error;
3134 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003135 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 goto error;
3137 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003138 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 } else if (!strcmp(sub->name, "units")) {
3140 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003141 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 goto error;
3143 }
3144 GETVAL(value, sub, "name");
3145 llist->units = lydict_insert(module->ctx, value, strlen(value));
3146 } else if (!strcmp(sub->name, "ordered-by")) {
3147 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003148 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 goto error;
3150 }
3151 /* just checking the flags in llist is not sufficient, we would
3152 * allow multiple ordered-by statements with the "system" value
3153 */
3154 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003155
Radek Krejci1574a8d2015-08-03 14:16:52 +02003156 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3158 * state data
3159 */
3160 lyxml_free_elem(module->ctx, sub);
3161 continue;
3162 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 GETVAL(value, sub, "value");
3165 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003166 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003168 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003169 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003170 } /* else system is the default value, so we can ignore it */
3171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 } else if (!strcmp(sub->name, "must")) {
3173 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003174 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003175 } else if (!strcmp(sub->name, "if-feature")) {
3176 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003177 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 } else if (!strcmp(sub->name, "min-elements")) {
3180 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003181 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003182 goto error;
3183 }
3184 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 GETVAL(value, sub, "value");
3187 while (isspace(value[0])) {
3188 value++;
3189 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 /* convert it to uint32_t */
3192 errno = 0;
3193 endptr = NULL;
3194 val = strtoul(value, &endptr, 10);
3195 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003196 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 goto error;
3198 }
3199 llist->min = (uint32_t) val;
3200 } else if (!strcmp(sub->name, "max-elements")) {
3201 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003202 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 goto error;
3204 }
3205 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 GETVAL(value, sub, "value");
3208 while (isspace(value[0])) {
3209 value++;
3210 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 /* convert it to uint32_t */
3213 errno = 0;
3214 endptr = NULL;
3215 val = strtoul(value, &endptr, 10);
3216 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003217 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 goto error;
3219 }
3220 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003221 } else if (!strcmp(sub->name, "when")) {
3222 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003223 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003224 goto error;
3225 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003226
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003227 llist->when = read_yin_when(module, sub);
3228 if (!llist->when) {
3229 goto error;
3230 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003231 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003232 goto error;
3233 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003235 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003236 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 lyxml_free_elem(module->ctx, sub);
3240 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003242 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003243 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003244 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 goto error;
3246 }
3247 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003248 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003249 goto error;
3250 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003252 /* middle part - process nodes with cardinality of 0..n */
3253 if (c_must) {
3254 llist->must = calloc(c_must, sizeof *llist->must);
3255 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003256 if (c_ftrs) {
3257 llist->features = calloc(c_ftrs, sizeof *llist->features);
3258 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003259
Radek Krejci73adb602015-07-02 18:07:40 +02003260 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003262 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003263 if (r) {
3264 goto error;
3265 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003266 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 +02003267 goto error;
3268 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003269 } else if (!strcmp(sub->name, "if-feature")) {
3270 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003271 if (unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003272 LOGLINE(sub)) == -1) {
3273 goto error;
3274 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003276 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003278 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003279
3280error:
3281
Radek Krejci1d82ef62015-08-07 14:44:40 +02003282 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003284 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003285}
3286
Michal Vasko0d343d12015-08-24 14:57:36 +02003287/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003288static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003289read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3290 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003291{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003292 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003293 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003295 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003296 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003298 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003299 char *auxs;
3300 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003302 /* init */
3303 memset(&root, 0, sizeof root);
3304 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003307 list->nodetype = LYS_LIST;
3308 list->prev = (struct lys_node *)list;
3309 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003310
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003311 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3312 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 goto error;
3314 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003315
Radek Krejcia9544502015-08-14 08:24:29 +02003316 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3317
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 /* process list's specific children */
3319 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003320 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3321 /* garbage */
3322 lyxml_free_elem(module->ctx, sub);
3323 continue;
3324 }
3325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 /* data statements */
3327 if (!strcmp(sub->name, "container") ||
3328 !strcmp(sub->name, "leaf-list") ||
3329 !strcmp(sub->name, "leaf") ||
3330 !strcmp(sub->name, "list") ||
3331 !strcmp(sub->name, "choice") ||
3332 !strcmp(sub->name, "uses") ||
3333 !strcmp(sub->name, "grouping") ||
3334 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003335 lyxml_unlink_elem(module->ctx, sub, 1);
3336 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003338 /* array counters */
3339 } else if (!strcmp(sub->name, "key")) {
3340 /* check cardinality 0..1 */
3341 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003342 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003343 goto error;
3344 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003345
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003346 /* count the number of keys */
3347 GETVAL(value, sub, "value");
3348 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003349 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 while ((value = strpbrk(value, " \t\n"))) {
3351 list->keys_size++;
3352 while (isspace(*value)) {
3353 value++;
3354 }
3355 }
3356 list->keys_size++;
3357 list->keys = calloc(list->keys_size, sizeof *list->keys);
3358 } else if (!strcmp(sub->name, "unique")) {
3359 c_uniq++;
Michal Vaskof8879c22015-08-21 09:07:36 +02003360 lyxml_unlink_elem(module->ctx, sub, 1);
3361 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 } else if (!strcmp(sub->name, "typedef")) {
3363 c_tpdf++;
3364 } else if (!strcmp(sub->name, "must")) {
3365 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003366 } else if (!strcmp(sub->name, "if-feature")) {
3367 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003368
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 /* optional stetments */
3370 } else if (!strcmp(sub->name, "ordered-by")) {
3371 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003372 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003373 goto error;
3374 }
3375 /* just checking the flags in llist is not sufficient, we would
3376 * allow multiple ordered-by statements with the "system" value
3377 */
3378 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003379
Radek Krejci1574a8d2015-08-03 14:16:52 +02003380 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003381 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3382 * state data
3383 */
3384 lyxml_free_elem(module->ctx, sub);
3385 continue;
3386 }
Radek Krejci345ad742015-06-03 11:04:18 +02003387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 GETVAL(value, sub, "value");
3389 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003390 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003392 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003393 goto error;
3394 }
3395 /* else system is the default value, so we can ignore it */
3396 lyxml_free_elem(module->ctx, sub);
3397 } else if (!strcmp(sub->name, "min-elements")) {
3398 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003399 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 goto error;
3401 }
3402 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003404 GETVAL(value, sub, "value");
3405 while (isspace(value[0])) {
3406 value++;
3407 }
Radek Krejci345ad742015-06-03 11:04:18 +02003408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 /* convert it to uint32_t */
3410 errno = 0;
3411 auxs = NULL;
3412 val = strtoul(value, &auxs, 10);
3413 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003414 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 goto error;
3416 }
3417 list->min = (uint32_t) val;
3418 lyxml_free_elem(module->ctx, sub);
3419 } else if (!strcmp(sub->name, "max-elements")) {
3420 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003421 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 goto error;
3423 }
3424 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003425
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 GETVAL(value, sub, "value");
3427 while (isspace(value[0])) {
3428 value++;
3429 }
Radek Krejci345ad742015-06-03 11:04:18 +02003430
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003431 /* convert it to uint32_t */
3432 errno = 0;
3433 auxs = NULL;
3434 val = strtoul(value, &auxs, 10);
3435 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003436 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 goto error;
3438 }
3439 list->max = (uint32_t) val;
3440 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003441 } else if (!strcmp(sub->name, "when")) {
3442 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003443 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003444 goto error;
3445 }
3446
3447 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003448 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003449 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003450 goto error;
3451 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003452 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003453 goto error;
3454 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003455 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003456 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003457 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003458 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 }
3460 }
Radek Krejci345ad742015-06-03 11:04:18 +02003461
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003462 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003463 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003464 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 goto error;
3466 }
3467 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003468 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 goto error;
3470 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003471
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003472 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3473 if (c_tpdf) {
3474 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3475 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003476 if (c_must) {
3477 list->must = calloc(c_must, sizeof *list->must);
3478 }
3479 if (c_ftrs) {
3480 list->features = calloc(c_ftrs, sizeof *list->features);
3481 }
Radek Krejci73adb602015-07-02 18:07:40 +02003482 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003484 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003485
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003486 if (r) {
3487 goto error;
3488 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003489 } else if (!strcmp(sub->name, "if-feature")) {
3490 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003491 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 +02003492 goto error;
3493 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003494 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003495 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003496 if (r) {
3497 goto error;
3498 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003499 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 +02003500 goto error;
3501 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 }
3503 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003504
Radek Krejci10c760e2015-08-14 14:45:43 +02003505 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003506 goto error;
3507 }
3508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 /* last part - process data nodes */
3510 LY_TREE_FOR_SAFE(root.child, next, sub) {
3511 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003512 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003514 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003515 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003516 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003517 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003518 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003519 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003520 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003522 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003524 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003526 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003527 } else {
3528 LOGINT;
3529 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003530 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003531 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 goto error;
3533 }
Radek Krejci73adb602015-07-02 18:07:40 +02003534
3535 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 if (!key_str) {
3539 /* config false list without a key */
3540 return retval;
3541 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003542 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003543 goto error;
3544 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003545
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 /* process unique statements */
3547 if (c_uniq) {
3548 list->unique = calloc(c_uniq, sizeof *list->unique);
3549 }
3550 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003551 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003552 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003553 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003554 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003555 LOGLINE(sub)) == -1) {
3556 goto error;
3557 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003558
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003559 lyxml_free_elem(module->ctx, sub);
3560 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003563
3564error:
3565
Radek Krejci1d82ef62015-08-07 14:44:40 +02003566 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 while (root.child) {
3568 lyxml_free_elem(module->ctx, root.child);
3569 }
3570 while (uniq.child) {
3571 lyxml_free_elem(module->ctx, uniq.child);
3572 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003573
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003575}
3576
Michal Vasko0d343d12015-08-24 14:57:36 +02003577/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003578static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003579read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3580 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003581{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003583 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003584 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003585 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 const char *value;
3587 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003588 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003589
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 /* init */
3591 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003594 cont->nodetype = LYS_CONTAINER;
3595 cont->prev = (struct lys_node *)cont;
3596 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003597
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003598 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3599 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 goto error;
3601 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003602
Radek Krejcia9544502015-08-14 08:24:29 +02003603 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3604
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 /* process container's specific children */
3606 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003607 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003608 /* garbage */
3609 lyxml_free_elem(module->ctx, sub);
3610 continue;
3611 }
3612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 if (!strcmp(sub->name, "presence")) {
3614 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003615 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003616 goto error;
3617 }
3618 GETVAL(value, sub, "value");
3619 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003622 } else if (!strcmp(sub->name, "when")) {
3623 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003624 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003625 goto error;
3626 }
3627
3628 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003629 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003630 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003631 goto error;
3632 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003633 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003634 goto error;
3635 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003636 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003638 /* data statements */
3639 } else if (!strcmp(sub->name, "container") ||
3640 !strcmp(sub->name, "leaf-list") ||
3641 !strcmp(sub->name, "leaf") ||
3642 !strcmp(sub->name, "list") ||
3643 !strcmp(sub->name, "choice") ||
3644 !strcmp(sub->name, "uses") ||
3645 !strcmp(sub->name, "grouping") ||
3646 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003647 lyxml_unlink_elem(module->ctx, sub, 1);
3648 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 /* array counters */
3651 } else if (!strcmp(sub->name, "typedef")) {
3652 c_tpdf++;
3653 } else if (!strcmp(sub->name, "must")) {
3654 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003655 } else if (!strcmp(sub->name, "if-feature")) {
3656 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003658 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 }
3661 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003663 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3664 if (c_tpdf) {
3665 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3666 }
3667 if (c_must) {
3668 cont->must = calloc(c_must, sizeof *cont->must);
3669 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003670 if (c_ftrs) {
3671 cont->features = calloc(c_ftrs, sizeof *cont->features);
3672 }
Radek Krejci800af702015-06-02 13:46:01 +02003673
Radek Krejci73adb602015-07-02 18:07:40 +02003674 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003675 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003676 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 if (r) {
3678 goto error;
3679 }
3680 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003681 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 if (r) {
3683 goto error;
3684 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003685 if (unres_schema_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003686 LOGLINE(sub)) == -1) {
3687 goto error;
3688 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 } else if (!strcmp(sub->name, "if-feature")) {
3690 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003691 if (unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003692 LOGLINE(sub)) == -1) {
3693 goto error;
3694 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003695 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003697
Radek Krejci10c760e2015-08-14 14:45:43 +02003698 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003699 goto error;
3700 }
3701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* last part - process data nodes */
3703 LY_TREE_FOR_SAFE(root.child, next, sub) {
3704 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003705 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003706 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003707 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003709 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003710 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003711 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003715 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003717 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003721 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 goto error;
3723 }
Radek Krejci73adb602015-07-02 18:07:40 +02003724
3725 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003729
3730error:
3731
Radek Krejci1d82ef62015-08-07 14:44:40 +02003732 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 while (root.child) {
3734 lyxml_free_elem(module->ctx, root.child);
3735 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003736
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003737 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003738}
3739
Michal Vasko0d343d12015-08-24 14:57:36 +02003740/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003741static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003742read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003743 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003746 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003747 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003748 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003749 int r;
3750 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003751
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 /* init */
3753 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003756 grp->nodetype = LYS_GROUPING;
3757 grp->prev = (struct lys_node *)grp;
3758 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003759
Michal Vasko71e1aa82015-08-12 12:17:51 +02003760 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003761 goto error;
3762 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763
Radek Krejcia9544502015-08-14 08:24:29 +02003764 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3765
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003767 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3768 /* garbage */
3769 lyxml_free_elem(module->ctx, sub);
3770 continue;
3771 }
3772
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003773 /* data statements */
3774 if (!strcmp(sub->name, "container") ||
3775 !strcmp(sub->name, "leaf-list") ||
3776 !strcmp(sub->name, "leaf") ||
3777 !strcmp(sub->name, "list") ||
3778 !strcmp(sub->name, "choice") ||
3779 !strcmp(sub->name, "uses") ||
3780 !strcmp(sub->name, "grouping") ||
3781 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003782 lyxml_unlink_elem(module->ctx, sub, 1);
3783 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003784
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003785 /* array counters */
3786 } else if (!strcmp(sub->name, "typedef")) {
3787 c_tpdf++;
3788 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003789 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 goto error;
3791 }
3792 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003794 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3795 if (c_tpdf) {
3796 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3797 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003798 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003799 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003800
Radek Krejci73adb602015-07-02 18:07:40 +02003801 if (r) {
3802 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003805
Radek Krejci10c760e2015-08-14 14:45:43 +02003806 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003807 goto error;
3808 }
3809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003810 /* last part - process data nodes */
3811 LY_TREE_FOR_SAFE(root.child, next, sub) {
3812 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003813 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003815 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003817 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003819 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003820 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003821 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003823 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003825 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003827 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003829 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003830 goto error;
3831 }
Radek Krejci73adb602015-07-02 18:07:40 +02003832
3833 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003834 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003837
3838error:
3839
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 while (root.child) {
3842 lyxml_free_elem(module->ctx, root.child);
3843 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003846}
3847
Michal Vasko0d343d12015-08-24 14:57:36 +02003848/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003849static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003850read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3851 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003852{
Radek Krejcie0674f82015-06-15 13:58:51 +02003853 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003855 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003856 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003857 int r;
3858 int c_tpdf = 0;
3859
Radek Krejcie0674f82015-06-15 13:58:51 +02003860 /* init */
3861 memset(&root, 0, sizeof root);
3862
Michal Vasko38d01f72015-06-15 09:41:06 +02003863 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003864 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003865
3866 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003867 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003868 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003869 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003870 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003871 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003872 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003873 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003874 }
3875
Radek Krejci76512572015-08-04 09:47:08 +02003876 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003877
Radek Krejci6a113852015-07-03 16:04:20 +02003878 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003879 goto error;
3880 }
3881
Radek Krejcia9544502015-08-14 08:24:29 +02003882 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3883
Michal Vasko38d01f72015-06-15 09:41:06 +02003884 /* data statements */
3885 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003886 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3887 /* garbage */
3888 lyxml_free_elem(module->ctx, sub);
3889 continue;
3890 }
3891
Michal Vasko38d01f72015-06-15 09:41:06 +02003892 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003893 !strcmp(sub->name, "leaf-list") ||
3894 !strcmp(sub->name, "leaf") ||
3895 !strcmp(sub->name, "list") ||
3896 !strcmp(sub->name, "choice") ||
3897 !strcmp(sub->name, "uses") ||
3898 !strcmp(sub->name, "grouping") ||
3899 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003900 lyxml_unlink_elem(module->ctx, sub, 1);
3901 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003903 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003904 } else if (!strcmp(sub->name, "typedef")) {
3905 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003906
Michal Vasko38d01f72015-06-15 09:41:06 +02003907 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003908 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003909 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003910 }
3911 }
3912
3913 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3914 if (c_tpdf) {
3915 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3916 }
3917
Radek Krejci73adb602015-07-02 18:07:40 +02003918 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003919 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003920
Radek Krejci73adb602015-07-02 18:07:40 +02003921 if (r) {
3922 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003923 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003924 }
3925
Radek Krejci10c760e2015-08-14 14:45:43 +02003926 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003927 goto error;
3928 }
3929
Michal Vasko38d01f72015-06-15 09:41:06 +02003930 /* last part - process data nodes */
3931 LY_TREE_FOR_SAFE(root.child, next, sub) {
3932 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003933 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003934 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003935 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003936 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003937 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003938 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003939 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003940 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003941 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003942 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003943 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003944 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003945 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003946 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003947 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003948 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003949 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003950 goto error;
3951 }
Radek Krejci73adb602015-07-02 18:07:40 +02003952
3953 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003954 }
3955
Michal Vasko38d01f72015-06-15 09:41:06 +02003956 return retval;
3957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003958error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003959
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003961 while (root.child) {
3962 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003963 }
3964
3965 return NULL;
3966}
3967
Michal Vasko0d343d12015-08-24 14:57:36 +02003968/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003969static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003970read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3971 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003972{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003973 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003974 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003975 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003976 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003977 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003978 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003979 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003980
Michal Vaskoc6551b32015-06-16 10:51:43 +02003981 memset(&root, 0, sizeof root);
3982
Michal Vasko0ea41032015-06-16 08:53:55 +02003983 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02003984 notif->nodetype = LYS_NOTIF;
3985 notif->prev = (struct lys_node *)notif;
3986 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02003987
Radek Krejci6a113852015-07-03 16:04:20 +02003988 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003989 goto error;
3990 }
3991
Radek Krejcia9544502015-08-14 08:24:29 +02003992 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3993
Michal Vasko0ea41032015-06-16 08:53:55 +02003994 /* process rpc's specific children */
3995 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003996 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3997 /* garbage */
3998 lyxml_free_elem(module->ctx, sub);
3999 continue;
4000 }
4001
Michal Vasko0ea41032015-06-16 08:53:55 +02004002 /* data statements */
4003 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004004 !strcmp(sub->name, "leaf-list") ||
4005 !strcmp(sub->name, "leaf") ||
4006 !strcmp(sub->name, "list") ||
4007 !strcmp(sub->name, "choice") ||
4008 !strcmp(sub->name, "uses") ||
4009 !strcmp(sub->name, "grouping") ||
4010 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004011 lyxml_unlink_elem(module->ctx, sub, 1);
4012 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004013
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004014 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004015 } else if (!strcmp(sub->name, "typedef")) {
4016 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004017 } else if (!strcmp(sub->name, "if-feature")) {
4018 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004019 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004020 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004021 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004022 }
4023 }
4024
4025 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4026 if (c_tpdf) {
4027 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4028 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004029 if (c_ftrs) {
4030 notif->features = calloc(c_ftrs, sizeof *notif->features);
4031 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004032
Radek Krejci73adb602015-07-02 18:07:40 +02004033 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004034 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004035 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004036
4037 if (r) {
4038 goto error;
4039 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004040 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004041 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004042 if (unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004043 LOGLINE(sub)) == -1) {
4044 goto error;
4045 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004046 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004047 }
4048
Radek Krejci10c760e2015-08-14 14:45:43 +02004049 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004050 goto error;
4051 }
4052
Michal Vasko0ea41032015-06-16 08:53:55 +02004053 /* last part - process data nodes */
4054 LY_TREE_FOR_SAFE(root.child, next, sub) {
4055 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004056 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004057 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004058 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004059 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004060 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004061 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004062 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004063 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004064 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004065 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004066 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004067 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004068 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004069 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004070 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004071 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004072 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004073 goto error;
4074 }
Radek Krejci73adb602015-07-02 18:07:40 +02004075
4076 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004077 }
4078
Michal Vasko0ea41032015-06-16 08:53:55 +02004079 return retval;
4080
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004081error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004082
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004084 while (root.child) {
4085 lyxml_free_elem(module->ctx, root.child);
4086 }
4087
4088 return NULL;
4089}
4090
Michal Vasko0d343d12015-08-24 14:57:36 +02004091/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004092static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004093read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4094 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004095{
Radek Krejcie0674f82015-06-15 13:58:51 +02004096 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004097 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004098 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004099 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004100 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004102 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004103
Radek Krejcie0674f82015-06-15 13:58:51 +02004104 /* init */
4105 memset(&root, 0, sizeof root);
4106
Michal Vasko38d01f72015-06-15 09:41:06 +02004107 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004108 rpc->nodetype = LYS_RPC;
4109 rpc->prev = (struct lys_node *)rpc;
4110 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004111
Radek Krejci6a113852015-07-03 16:04:20 +02004112 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004113 goto error;
4114 }
4115
Radek Krejcia9544502015-08-14 08:24:29 +02004116 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4117
Michal Vasko38d01f72015-06-15 09:41:06 +02004118 /* process rpc's specific children */
4119 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004120 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4121 /* garbage */
4122 lyxml_free_elem(module->ctx, sub);
4123 continue;
4124 }
4125
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004127 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004128 && (rpc->child->nodetype == LYS_INPUT
4129 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004130 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004131 goto error;
4132 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004133 lyxml_unlink_elem(module->ctx, sub, 1);
4134 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004135 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004136 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004137 && (rpc->child->nodetype == LYS_INPUT
4138 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004139 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004140 goto error;
4141 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004142 lyxml_unlink_elem(module->ctx, sub, 1);
4143 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004145 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004146 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004147 lyxml_unlink_elem(module->ctx, sub, 1);
4148 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004150 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004151 } else if (!strcmp(sub->name, "typedef")) {
4152 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004153 } else if (!strcmp(sub->name, "if-feature")) {
4154 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004155 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004156 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004157 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004158 }
4159 }
4160
4161 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4162 if (c_tpdf) {
4163 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4164 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004165 if (c_ftrs) {
4166 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4167 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004168
Radek Krejci73adb602015-07-02 18:07:40 +02004169 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004171 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004172
4173 if (r) {
4174 goto error;
4175 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004176 } else if (!strcmp(sub->name, "if-feature")) {
4177 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004178 if (unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004179 LOGLINE(sub)) == -1) {
4180 goto error;
4181 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004182 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004183 }
4184
Radek Krejci10c760e2015-08-14 14:45:43 +02004185 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004186 goto error;
4187 }
4188
Michal Vasko38d01f72015-06-15 09:41:06 +02004189 /* last part - process data nodes */
4190 LY_TREE_FOR_SAFE(root.child, next, sub) {
4191 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004192 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004193 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004194 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004195 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004196 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004197 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004198 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004199 goto error;
4200 }
Radek Krejci73adb602015-07-02 18:07:40 +02004201
4202 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004203 }
4204
Michal Vasko38d01f72015-06-15 09:41:06 +02004205 return retval;
4206
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004208
Radek Krejci1d82ef62015-08-07 14:44:40 +02004209 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004210 while (root.child) {
4211 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004212 }
4213
4214 return NULL;
4215}
4216
Michal Vasko0d343d12015-08-24 14:57:36 +02004217/* logs directly
4218 *
Radek Krejci74705112015-06-05 10:25:44 +02004219 * resolve - referenced grouping should be bounded to the namespace (resolved)
4220 * only when uses does not appear in grouping. In a case of grouping's uses,
4221 * we just get information but we do not apply augment or refine to it.
4222 */
Radek Krejci76512572015-08-04 09:47:08 +02004223static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004224read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004225 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004226{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004227 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004228 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004229 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004231 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004232 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004234 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004235 uses->nodetype = LYS_USES;
4236 uses->prev = (struct lys_node *)uses;
4237 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004238
Radek Krejcia9544502015-08-14 08:24:29 +02004239 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004240 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004241
Radek Krejcia9544502015-08-14 08:24:29 +02004242 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004243 goto error;
4244 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004245
Radek Krejcia9544502015-08-14 08:24:29 +02004246 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4247
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004249 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004250 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4251 /* garbage */
4252 lyxml_free_elem(module->ctx, sub);
4253 continue;
4254 }
4255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004256 if (!strcmp(sub->name, "refine")) {
4257 c_ref++;
4258 } else if (!strcmp(sub->name, "augment")) {
4259 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004260 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004261 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004262 } else if (!strcmp(sub->name, "when")) {
4263 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004264 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004265 goto error;
4266 }
4267
4268 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004269 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004270 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004271 goto error;
4272 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02004273 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004274 goto error;
4275 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004276 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004277 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004278 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004279 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 }
4281 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 /* process properties with cardinality 0..n */
4284 if (c_ref) {
4285 uses->refine = calloc(c_ref, sizeof *uses->refine);
4286 }
4287 if (c_aug) {
4288 uses->augment = calloc(c_aug, sizeof *uses->augment);
4289 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004290 if (c_ftrs) {
4291 uses->features = calloc(c_ftrs, sizeof *uses->features);
4292 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004293
Radek Krejci10c760e2015-08-14 14:45:43 +02004294 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004295 goto error;
4296 }
4297
Radek Krejcia9544502015-08-14 08:24:29 +02004298 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004300 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4301 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004302 goto error;
4303 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004304 } else if (!strcmp(sub->name, "augment")) {
4305 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4306 if (r) {
4307 goto error;
4308 }
4309 } else if (!strcmp(sub->name, "if-feature")) {
4310 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004311 if (unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004312 LOGLINE(sub)) == -1) {
4313 goto error;
4314 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004315 }
4316 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004317
Michal Vasko0bd29d12015-08-19 11:45:49 +02004318 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004319 goto error;
4320 }
Radek Krejci74705112015-06-05 10:25:44 +02004321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 if (resolve) {
4323 /* inherit config flag */
4324 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004325 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326 } else {
4327 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004328 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004329 }
4330 }
Radek Krejcib388c152015-06-04 17:03:03 +02004331
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004332 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004333
4334error:
4335
Radek Krejci1d82ef62015-08-07 14:44:40 +02004336 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004337
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004338 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004339}
4340
Michal Vasko0d343d12015-08-24 14:57:36 +02004341/* logs directly
4342 *
4343 * common code for yin_read_module() and yin_read_submodule()
4344 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004345static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004346read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004347{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004349 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004350 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4351 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004353 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004355 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004356 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 +02004357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004358 /* init */
4359 memset(&root, 0, sizeof root);
4360 memset(&grps, 0, sizeof grps);
4361 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004362 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 /*
4365 * in the first run, we process elements with cardinality of 1 or 0..1 and
4366 * count elements with cardinality 0..n. Data elements (choices, containers,
4367 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4368 * need have all top-level and groupings already prepared at that time. In
4369 * the middle loop, we process other elements with carinality of 0..n since
4370 * we need to allocate arrays to store them.
4371 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 LY_TREE_FOR_SAFE(yin->child, next, child) {
4373 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004374 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004375 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 continue;
4377 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004378
Radek Krejci1d82ef62015-08-07 14:44:40 +02004379 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004381 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 goto error;
4383 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004384 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004386 lyxml_free_elem(ctx, child);
4387 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004389 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 goto error;
4391 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004392 GETVAL(value, child, "value");
4393 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 goto error;
4395 }
4396 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004397 lyxml_free_elem(ctx, child);
4398 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004400 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004401 goto error;
4402 }
4403 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004404 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004406 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 }
4408 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004409 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 goto error;
4411 }
Radek Krejcif3886932015-06-04 17:36:06 +02004412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004414 if (!child->child) {
4415 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004417 } else if (strcmp(child->child->name, "prefix")) {
4418 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004419 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004420 } else if (child->child->next) {
4421 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 goto error;
4423 }
4424 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004425 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 /* check here differs from a generic prefix check, since this prefix
4427 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004428 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004429 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004430 goto error;
4431 }
4432 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004433
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004434 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004435 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004436
4437 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004438 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004439 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004440 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004442 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004443 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004444 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004446 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004448 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004449 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004450 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004451 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004452 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004453 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004454
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004455 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004456 } else if (!strcmp(child->name, "container") ||
4457 !strcmp(child->name, "leaf-list") ||
4458 !strcmp(child->name, "leaf") ||
4459 !strcmp(child->name, "list") ||
4460 !strcmp(child->name, "choice") ||
4461 !strcmp(child->name, "uses") ||
4462 !strcmp(child->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004463 lyxml_unlink_elem(module->ctx, child, 1);
4464 lyxml_add_child(module->ctx, &root, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004465 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 /* keep groupings separated and process them before other data statements */
Michal Vaskof8879c22015-08-21 09:07:36 +02004467 lyxml_unlink_elem(module->ctx, child, 1);
4468 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004471 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004472 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004473 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 goto error;
4475 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004476 module->dsc = read_yin_subnode(ctx, child, "text");
4477 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 if (!module->dsc) {
4479 goto error;
4480 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004481 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004482 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 goto error;
4485 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004486 module->ref = read_yin_subnode(ctx, child, "text");
4487 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 if (!module->ref) {
4489 goto error;
4490 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004491 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004493 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 goto error;
4495 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004496 module->org = read_yin_subnode(ctx, child, "text");
4497 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004498 if (!module->org) {
4499 goto error;
4500 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004501 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004502 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004503 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 goto error;
4505 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004506 module->contact = read_yin_subnode(ctx, child, "text");
4507 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 if (!module->contact) {
4509 goto error;
4510 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 /* TODO: support YANG 1.1 ? */
4513 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004514 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 goto error;
4516 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004517 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004519 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 goto error;
4521 }
4522 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004523 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004524
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004525 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004526 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004527 lyxml_unlink_elem(module->ctx, child, 1);
4528 lyxml_add_child(module->ctx, &rpcs, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004529 } else if (!strcmp(child->name, "notification")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004530 lyxml_unlink_elem(module->ctx, child, 1);
4531 lyxml_add_child(module->ctx, &notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004532
Radek Krejci1d82ef62015-08-07 14:44:40 +02004533 } else if (!strcmp(child->name, "extension")) {
4534 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004535
Radek Krejci6764bb32015-07-03 15:16:04 +02004536 /* we have 2 supported (hardcoded) extensions:
4537 * NACM's default-deny-write and default-deny-all
4538 */
4539 if (strcmp(module->ns, LY_NSNACM) ||
4540 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4541 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004542 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004543 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004545 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004546 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 }
4548 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 if (!submodule) {
4551 /* check for mandatory statements */
4552 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004553 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 goto error;
4555 }
4556 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004557 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 goto error;
4559 }
4560 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 /* allocate arrays for elements with cardinality of 0..n */
4563 if (c_imp) {
4564 module->imp = calloc(c_imp, sizeof *module->imp);
4565 }
4566 if (c_rev) {
4567 module->rev = calloc(c_rev, sizeof *module->rev);
4568 }
4569 if (c_tpdf) {
4570 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4571 }
4572 if (c_ident) {
4573 module->ident = calloc(c_ident, sizeof *module->ident);
4574 }
4575 if (c_inc) {
4576 module->inc = calloc(c_inc, sizeof *module->inc);
4577 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004578 if (c_aug) {
4579 module->augment = calloc(c_aug, sizeof *module->augment);
4580 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004581 if (c_ftrs) {
4582 module->features = calloc(c_ftrs, sizeof *module->features);
4583 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004584 if (c_dev) {
4585 module->deviation = calloc(c_dev, sizeof *module->deviation);
4586 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004587
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004589 LY_TREE_FOR(yin->child, child) {
4590 if (!strcmp(child->name, "import")) {
4591 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004592 module->imp_size++;
4593 if (r) {
4594 goto error;
4595 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004596
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 /* check duplicities in imported modules */
4598 for (i = 0; i < module->imp_size - 1; i++) {
4599 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004600 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 goto error;
4602 }
4603 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004604 } else if (!strcmp(child->name, "include")) {
4605 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 module->inc_size++;
4607 if (r) {
4608 goto error;
4609 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 /* check duplications in include submodules */
4612 for (i = 0; i < module->inc_size - 1; i++) {
4613 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004614 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 module->inc[i].submodule->name);
4616 goto error;
4617 }
4618 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 } else if (!strcmp(child->name, "revision")) {
4620 GETVAL(value, child, "date");
4621 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 goto error;
4623 }
4624 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4625 /* check uniqueness of the revision date - not required by RFC */
4626 for (i = 0; i < module->rev_size; i++) {
4627 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004628 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004629 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 }
4631 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004632
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 LY_TREE_FOR(child->child, child2) {
4634 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004636 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637 goto error;
4638 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 if (!module->rev[module->rev_size].dsc) {
4641 goto error;
4642 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004645 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004646 goto error;
4647 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004648 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 if (!module->rev[module->rev_size].ref) {
4650 goto error;
4651 }
4652 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004653 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 goto error;
4655 }
4656 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 /* keep the latest revision at position 0 */
4659 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4660 /* switch their position */
4661 value = strdup(module->rev[0].date);
4662 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4663 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4664 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004666 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4667 value = module->rev[0].dsc;
4668 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4669 module->rev[module->rev_size].dsc = value;
4670 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004672 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4673 value = module->rev[0].ref;
4674 module->rev[0].ref = module->rev[module->rev_size].ref;
4675 module->rev[module->rev_size].ref = value;
4676 }
4677 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004680 } else if (!strcmp(child->name, "typedef")) {
4681 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 if (r) {
4685 goto error;
4686 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004687 } else if (!strcmp(child->name, "identity")) {
4688 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004689 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 if (r) {
4692 goto error;
4693 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004694 } else if (!strcmp(child->name, "feature")) {
4695 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004696 module->features_size++;
4697
4698 if (r) {
4699 goto error;
4700 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004701 } else if (!strcmp(child->name, "augment")) {
4702 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004703 module->augment_size++;
4704
4705 if (r) {
4706 goto error;
4707 }
4708
4709 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4710 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004711 } else if (!strcmp(child->name, "deviation")) {
4712 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004713 module->deviation_size++;
4714
4715 if (r) {
4716 goto error;
4717 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004719 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004720
Radek Krejcif5be10f2015-06-16 13:29:36 +02004721 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 * refer to them
4723 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004724 LY_TREE_FOR_SAFE(grps.child, next, child) {
4725 node = read_yin_grouping(module, NULL, child, 0, unres);
4726 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 goto error;
4728 }
Radek Krejci74705112015-06-05 10:25:44 +02004729
Radek Krejci1d82ef62015-08-07 14:44:40 +02004730 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004731 }
Radek Krejci74705112015-06-05 10:25:44 +02004732
Radek Krejcif5be10f2015-06-16 13:29:36 +02004733 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004734 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004735
Radek Krejci1d82ef62015-08-07 14:44:40 +02004736 if (!strcmp(child->name, "container")) {
4737 node = read_yin_container(module, NULL, child, 1, unres);
4738 } else if (!strcmp(child->name, "leaf-list")) {
4739 node = read_yin_leaflist(module, NULL, child, 1, unres);
4740 } else if (!strcmp(child->name, "leaf")) {
4741 node = read_yin_leaf(module, NULL, child, 1, unres);
4742 } else if (!strcmp(child->name, "list")) {
4743 node = read_yin_list(module, NULL, child, 1, unres);
4744 } else if (!strcmp(child->name, "choice")) {
4745 node = read_yin_choice(module, NULL, child, 1, unres);
4746 } else if (!strcmp(child->name, "uses")) {
4747 node = read_yin_uses(module, NULL, child, 1, unres);
4748 } else if (!strcmp(child->name, "anyxml")) {
4749 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004751 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004752 goto error;
4753 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004754
Radek Krejci1d82ef62015-08-07 14:44:40 +02004755 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004756 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004757
4758 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004759 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4760 node = read_yin_rpc(module, NULL, child, 0, unres);
4761 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004762 goto error;
4763 }
4764
Radek Krejci1d82ef62015-08-07 14:44:40 +02004765 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004766 }
4767
4768 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004769 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4770 node = read_yin_notif(module, NULL, child, 0, unres);
4771 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004772 goto error;
4773 }
4774
Radek Krejci1d82ef62015-08-07 14:44:40 +02004775 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004776 }
4777
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004779
4780error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004781 /* cleanup */
4782 while (root.child) {
4783 lyxml_free_elem(module->ctx, root.child);
4784 }
4785 while (grps.child) {
4786 lyxml_free_elem(module->ctx, grps.child);
4787 }
4788 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004789 lyxml_free_elem(module->ctx, rpcs.child);
4790 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004791
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004792 free(unres->item);
4793 unres->item = NULL;
4794 free(unres->type);
4795 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004796 free(unres->str_snode);
4797 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004798#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004799 free(unres->line);
4800 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004801#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004802 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004805}
4806
Michal Vasko0d343d12015-08-24 14:57:36 +02004807/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004808struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004809yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004810{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004811 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004812 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004816
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004817 yin = lyxml_read(module->ctx, data, 0);
4818 if (!yin) {
4819 return NULL;
4820 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004822 /* check root element */
4823 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004824 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004825 goto error;
4826 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004828 GETVAL(value, yin, "name");
4829 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4830 goto error;
4831 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 submodule = calloc(1, sizeof *submodule);
4834 if (!submodule) {
4835 LOGMEM;
4836 goto error;
4837 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 submodule->ctx = module->ctx;
4840 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4841 submodule->type = 1;
4842 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004843 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004845 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004846 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 goto error;
4848 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004849
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004850 /* cleanup */
4851 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004853 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004855 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004856
4857error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 /* cleanup */
4859 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004860 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004861
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004862 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004863}
4864
Michal Vasko0d343d12015-08-24 14:57:36 +02004865/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004866struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004867yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004870 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 const char *value;
4872 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 yin = lyxml_read(ctx, data, 0);
4875 if (!yin) {
4876 return NULL;
4877 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 /* check root element */
4880 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004881 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 goto error;
4883 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004884
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004885 GETVAL(value, yin, "name");
4886 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4887 goto error;
4888 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004889
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 module = calloc(1, sizeof *module);
4891 if (!module) {
4892 LOGMEM;
4893 goto error;
4894 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 module->ctx = ctx;
4897 module->name = lydict_insert(ctx, value, strlen(value));
4898 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004899 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004902 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 goto error;
4904 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004905
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 /* add to the context's list of modules */
4907 if (ctx->models.used == ctx->models.size) {
4908 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4909 if (!newlist) {
4910 LOGMEM;
4911 goto error;
4912 }
4913 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4914 newlist[i] = NULL;
4915 }
4916 ctx->models.size *= 2;
4917 ctx->models.list = newlist;
4918 }
4919 for (i = 0; ctx->models.list[i]; i++) {
4920 /* check name (name/revision) and namespace uniqueness */
4921 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004922 if (ctx->models.list[i]->rev_size == module->rev_size) {
4923 /* both have the same number of revisions */
4924 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4925 /* both have the same revision -> we already have the same module */
4926 /* so free the new one and update the old one's implement flag if needed */
4927 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004928 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02004929 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004930
4931 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4932
4933 if (implement && !ctx->models.list[i]->implemented) {
4934 lyp_set_implemented(ctx->models.list[i]);
4935 }
4936 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004937 }
4938 }
Radek Krejcif647e612015-07-30 11:36:07 +02004939 /* else (both elses) keep searching, for now the caller is just adding
4940 * another revision of an already present schema
4941 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4943 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4944 ctx->models.list[i]->name, module->name, module->ns);
4945 goto error;
4946 }
4947 }
4948 ctx->models.list[i] = module;
4949 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004950 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004952 /* cleanup */
4953 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004954
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004955 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004956
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004957 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004958
4959error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 /* cleanup */
4961 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004962 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004963
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004965}