blob: d33e3fd459f4f3878138caadae65e50fa13a13a8 [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);
Michal Vaskof7eee892015-08-24 15:03:11 +0200490 if (rc == -1) {
491 LOGVAL(LYE_INPREF, LOGLINE(yin), type->prefix);
492 goto error;
493 } else if (rc == EXIT_FAILURE) {
494 /* HACK for unres */
495 type->der = (struct lys_tpdf *)parent;
496 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200497 if (rc == -1) {
498 goto error;
Michal Vaskof7eee892015-08-24 15:03:11 +0200499 } else {
500 return EXIT_SUCCESS;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200501 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200502 }
503 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200505 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200506 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200507 /* RFC 6020 9.7.4 - bit */
508
509 /* get bit specifications, at least one must be present */
510 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200511 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
512 /* garbage */
513 lyxml_free_elem(module->ctx, node);
514 continue;
515 }
516
Radek Krejci994b6f62015-06-18 16:47:27 +0200517 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200518 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200519 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200520 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200521 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200522 }
523 }
Radek Krejciac781922015-07-09 15:35:14 +0200524 if (!type->der->type.der && !type->info.bits.count) {
525 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200526 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200527 goto error;
528 }
Radek Krejciac781922015-07-09 15:35:14 +0200529 if (type->der->type.der && type->info.bits.count) {
530 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200531 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200532 goto error;
533 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200534
535 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200536 p = 0;
537 i = -1;
538 LY_TREE_FOR(yin->child, next) {
539 i++;
540
541 GETVAL(value, next, "name");
542 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200543 goto error;
544 }
545 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200546 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200547 type->info.bits.count = i + 1;
548 goto error;
549 }
550
551 /* check the name uniqueness */
552 for (j = 0; j < i; j++) {
553 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200554 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200555 type->info.bits.count = i + 1;
556 goto error;
557 }
558 }
559
Radek Krejci0d70c372015-07-02 16:23:10 +0200560 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200561 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200562 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
563 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200564 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200565 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200566
Radek Krejci0d70c372015-07-02 16:23:10 +0200567 if (!strcmp(node->name, "position")) {
568 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200569 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200570
571 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200572 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200573 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200574 type->info.bits.count = i + 1;
575 goto error;
576 }
577 type->info.bits.bit[i].pos = (uint32_t)p_;
578
579 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200580 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200581 p = type->info.bits.bit[i].pos;
582 p++;
583 } else {
584 /* check that the value is unique */
585 for (j = 0; j < i; j++) {
586 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200587 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 +0200588 type->info.bits.count = i + 1;
589 goto error;
590 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200591 }
592 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200593 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200594 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200595 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200596 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200597 }
598 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200599 /* assign value automatically */
600 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200601 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200602 type->info.bits.count = i + 1;
603 goto error;
604 }
605 type->info.bits.bit[i].pos = (uint32_t)p;
606 p++;
607 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200608
609 /* keep them ordered by position */
610 j = i;
611 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
612 /* switch them */
613 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
614 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
615 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
616 j--;
617 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200618 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200619 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200620
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200621 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200622 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200623 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200624 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
625 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200626 continue;
627 }
628
Radek Krejcif9401c32015-06-26 16:47:36 +0200629 if (!strcmp(node->name, "range")) {
630 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200631 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200632 goto error;
633 }
634
635 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200636 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200637 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200638 goto error;
639 }
640 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
641 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
642
643 /* get possible substatements */
644 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
645 goto error;
646 }
647 } else if (!strcmp(node->name, "fraction-digits")) {
648 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200649 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200650 goto error;
651 }
652 GETVAL(value, node, "value");
653 v = strtol(value, NULL, 10);
654
655 /* range check */
656 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200657 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200658 goto error;
659 }
660 type->info.dec64.dig = (uint8_t)v;
661 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200662 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200663 goto error;
664 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200665 }
666
667 /* mandatory sub-statement(s) check */
668 if (!type->info.dec64.dig && !type->der->type.der) {
669 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200670 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200671 goto error;
672 }
Radek Krejci7511f402015-07-10 09:56:30 +0200673 if (type->info.dec64.dig && type->der->type.der) {
674 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200675 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200676 goto error;
677 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200678 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200680 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200681 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200682
Radek Krejci994b6f62015-06-18 16:47:27 +0200683 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200684 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200685 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
686 /* garbage */
687 lyxml_free_elem(module->ctx, node);
688 continue;
689 }
690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200692 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200693 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200694 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200695 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200696 }
697 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200698 if (!type->der->type.der && !type->info.enums.count) {
699 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200700 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200701 goto error;
702 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200703 if (type->der->type.der && type->info.enums.count) {
704 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200705 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200706 goto error;
707 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200708
Radek Krejci1574a8d2015-08-03 14:16:52 +0200709 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200710 v = 0;
711 i = -1;
712 LY_TREE_FOR(yin->child, next) {
713 i++;
714
715 GETVAL(value, next, "name");
716 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200717 goto error;
718 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200719 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200720 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200721 type->info.enums.count = i + 1;
722 goto error;
723 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200725 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200726 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200728 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200729 type->info.enums.count = i + 1;
730 goto error;
731 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200732
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200733 /* check the name uniqueness */
734 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200735 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200736 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 type->info.enums.count = i + 1;
738 goto error;
739 }
740 }
Radek Krejci04581c62015-05-22 21:24:00 +0200741
Radek Krejci0d70c372015-07-02 16:23:10 +0200742 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200743 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200744 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
745 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200746 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200747 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200748
Radek Krejci0d70c372015-07-02 16:23:10 +0200749 if (!strcmp(node->name, "value")) {
750 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200751 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200752
753 /* range check */
754 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200755 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200756 type->info.enums.count = i + 1;
757 goto error;
758 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200759 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200760
761 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200762 if (type->info.enums.enm[i].value > v) {
763 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200764 v++;
765 } else {
766 /* check that the value is unique */
767 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200768 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200769 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200770 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200771 type->info.enums.count = i + 1;
772 goto error;
773 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 }
775 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200776 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200777 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200778 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200780 }
781 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200782 /* assign value automatically */
783 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200784 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200785 type->info.enums.count = i + 1;
786 goto error;
787 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200788 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200789 v++;
790 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200791 }
792 break;
793
794 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200795 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200796
797 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200798 LY_TREE_FOR_SAFE(yin->child, next, node) {
799 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
800 /* garbage */
801 lyxml_free_elem(module->ctx, node);
802 continue;
803 }
804
805 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200806 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200807 goto error;
808 }
809 }
810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200812 if (type->der->type.der) {
813 /* this is just a derived type with no base specified/required */
814 break;
815 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200816 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 goto error;
818 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200819 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200820 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200821 goto error;
822 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200823 GETVAL(value, yin->child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +0200824 if (unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200825 goto error;
826 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200827 break;
828
829 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200830 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200831 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200832 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
833 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200834 continue;
835 }
836
Radek Krejciaf351422015-06-19 14:49:38 +0200837 if (!strcmp(node->name, "require-instance")) {
838 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200839 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200840 goto error;
841 }
842 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200843 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200844 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200845 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200846 type->info.inst.req = -1;
847 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200848 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200849 goto error;
850 }
851 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200852 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200853 goto error;
854 }
Radek Krejciaf351422015-06-19 14:49:38 +0200855 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200856
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200857 break;
858
Radek Krejcif2860132015-06-20 12:37:20 +0200859 case LY_TYPE_BINARY:
860 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200861 case LY_TYPE_INT8:
862 case LY_TYPE_INT16:
863 case LY_TYPE_INT32:
864 case LY_TYPE_INT64:
865 case LY_TYPE_UINT8:
866 case LY_TYPE_UINT16:
867 case LY_TYPE_UINT32:
868 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200869 /* RFC 6020 9.2.4 - range */
870
871 /* length and range are actually the same restriction, so process
872 * them by this common code, we just need to differ the name and
873 * structure where the information will be stored
874 */
875 if (type->base == LY_TYPE_BINARY) {
876 restr = &type->info.binary.length;
877 name = "length";
878 } else {
879 restr = &type->info.num.range;
880 name = "range";
881 }
882
Radek Krejci73adb602015-07-02 18:07:40 +0200883 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200884 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
885 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200886 continue;
887 }
888
Radek Krejcif2860132015-06-20 12:37:20 +0200889 if (!strcmp(node->name, name)) {
890 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200891 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200892 goto error;
893 }
894
895 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200896 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200897 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200898 goto error;
899 }
900 *restr = calloc(1, sizeof **restr);
901 (*restr)->expr = lydict_insert(module->ctx, value, 0);
902
903 /* get possible substatements */
904 if (read_restr_substmt(module->ctx, *restr, node)) {
905 goto error;
906 }
907 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200908 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200909 goto error;
910 }
Radek Krejcif2860132015-06-20 12:37:20 +0200911 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200912 break;
913
914 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200915 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200916 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200917 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
918 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200919 continue;
920 }
921
Radek Krejcidc4c1412015-06-19 15:39:54 +0200922 if (!strcmp(node->name, "path")) {
923 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200924 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200925 goto error;
926 }
927
928 GETVAL(value, node, "value");
Radek Krejcidc4c1412015-06-19 15:39:54 +0200929 type->info.lref.path = lydict_insert(module->ctx, value, 0);
Michal Vasko0bd29d12015-08-19 11:45:49 +0200930 if (unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200931 goto error;
932 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200933
Radek Krejcidc4c1412015-06-19 15:39:54 +0200934 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200935 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200936 goto error;
937 }
Radek Krejci73adb602015-07-02 18:07:40 +0200938 }
939
940 if (!type->info.lref.path) {
941 if (type->der->type.der) {
942 /* this is just a derived type with no path specified/required */
943 break;
944 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200945 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200946 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200948 break;
949
950 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200951 /* RFC 6020 9.4.4 - length */
952 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200953 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200954 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200955 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
956 /* garbage */
957 lyxml_free_elem(module->ctx, node);
958 continue;
959 }
960
Radek Krejci3733a802015-06-19 13:43:21 +0200961 if (!strcmp(node->name, "length")) {
962 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200963 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200964 goto error;
965 }
966
967 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200968 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200969 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200970 goto error;
971 }
972 type->info.str.length = calloc(1, sizeof *type->info.str.length);
973 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
974
Radek Krejci5fbc9162015-06-19 14:11:11 +0200975 /* get possible sub-statements */
976 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200977 goto error;
978 }
Radek Krejci82d971d2015-06-19 14:20:50 +0200979 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200980 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200981 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200982 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200983 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200984 goto error;
985 }
986 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200987 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200988 if (i) {
989 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
990 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +0200991 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200992
993 /* check that the regex is valid */
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +0200994 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
995 if (!precomp) {
996 LOGVAL(LYE_INREGEX, LOGLINE(node), value, err_ptr);
Michal Vasko69068852015-07-13 14:34:31 +0200997 free(type->info.str.patterns);
998 goto error;
999 }
Michal Vaskoe4e8fbd2015-08-24 14:54:49 +02001000 free(precomp);
Michal Vasko69068852015-07-13 14:34:31 +02001001
Radek Krejci73adb602015-07-02 18:07:40 +02001002 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001003
1004 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +02001005 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +02001006 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001007 goto error;
1008 }
Radek Krejci73adb602015-07-02 18:07:40 +02001009 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001010 }
1011 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001012 break;
1013
1014 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001015 /* RFC 6020 7.4 - type */
1016 /* count number of types in union */
1017 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001018 LY_TREE_FOR_SAFE(yin->child, next, node) {
1019 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1020 /* garbage */
1021 lyxml_free_elem(module->ctx, node);
1022 continue;
1023 }
1024
Radek Krejcie4c366b2015-07-02 10:11:31 +02001025 if (!strcmp(node->name, "type")) {
1026 i++;
1027 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001028 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001029 goto error;
1030 }
1031 }
1032
1033 if (!i) {
1034 if (type->der->type.der) {
1035 /* this is just a derived type with no base specified/required */
1036 break;
1037 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001038 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001039 goto error;
1040 }
1041
1042 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001043 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001044 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001045 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001046 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001047 goto error;
1048 }
1049 type->info.uni.count++;
1050
1051 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001052 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001053 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001054 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001055 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001056 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001057 goto error;
1058 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001059 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001060 break;
1061
1062 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001063 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001064 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1065 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001066 LY_TREE_FOR(yin->child, node) {
1067 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001068 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001069 goto error;
1070 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001071 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001072 break;
1073 }
1074
1075 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001076
1077error:
1078
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001079 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001080}
1081
Michal Vasko0d343d12015-08-24 14:57:36 +02001082/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001083static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001084fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001085{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001087 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001088 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001090 GETVAL(value, yin, "name");
1091 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1092 goto error;
1093 }
1094 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001096 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001097 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 goto error;
1099 }
Radek Krejcieac35532015-05-31 19:09:15 +02001100
Radek Krejci73adb602015-07-02 18:07:40 +02001101 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001102 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1103 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001104 continue;
1105 }
1106
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001107 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001108 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001109 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001110 goto error;
1111 }
Radek Krejci73adb602015-07-02 18:07:40 +02001112 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1113 goto error;
1114 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001115 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 } else if (!strcmp(node->name, "default")) {
1117 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001118 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 goto error;
1120 }
1121 GETVAL(value, node, "value");
1122 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001124 } else if (!strcmp(node->name, "units")) {
1125 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001126 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 goto error;
1128 }
1129 GETVAL(value, node, "name");
1130 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1131 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001132 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 goto error;
1134 }
1135 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001137 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001138 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001139 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 goto error;
1141 }
Radek Krejcieac35532015-05-31 19:09:15 +02001142
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001143 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001144 if (tpdf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02001145 if (unres_schema_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001146 goto error;
1147 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001148 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001149
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001150 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001151
1152error:
1153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001154 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001155}
1156
Michal Vasko0d343d12015-08-24 14:57:36 +02001157/* logs directly */
Radek Krejci3cf9e222015-06-18 11:37:50 +02001158static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001159fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_schema *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001160{
1161 const char *value;
1162 struct lyxml_elem *child, *next;
1163 int c = 0;
1164
Radek Krejcib05774c2015-06-18 13:52:59 +02001165 GETVAL(value, yin, "name");
1166 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1167 goto error;
1168 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001169 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001170 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001171
Radek Krejci76512572015-08-04 09:47:08 +02001172 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001173 goto error;
1174 }
1175
1176 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001177 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1178 /* garbage */
1179 lyxml_free_elem(module->ctx, child);
1180 continue;
1181 }
1182
Radek Krejci3cf9e222015-06-18 11:37:50 +02001183 if (!strcmp(child->name, "if-feature")) {
1184 c++;
1185 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001186 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001187 goto error;
1188 }
1189 }
1190
1191 if (c) {
1192 f->features = calloc(c, sizeof *f->features);
1193 }
Radek Krejci73adb602015-07-02 18:07:40 +02001194 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001195 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02001196 if (unres_schema_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001197 goto error;
1198 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001199 }
1200
Radek Krejci3cf9e222015-06-18 11:37:50 +02001201 return EXIT_SUCCESS;
1202
1203error:
1204
1205 return EXIT_FAILURE;
1206}
1207
Michal Vasko0d343d12015-08-24 14:57:36 +02001208/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001209static int
Radek Krejcib8048692015-08-05 13:36:34 +02001210fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001211{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001214 GETVAL(value, yin, "condition");
Radek Krejci0bd5db42015-06-19 13:30:07 +02001215 must->expr = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02001216
Radek Krejci41726f92015-06-19 13:11:05 +02001217 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001218
Radek Krejci41726f92015-06-19 13:11:05 +02001219error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001221 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001222}
1223
Michal Vasko0d343d12015-08-24 14:57:36 +02001224/* logs directly
1225 *
Radek Krejcieb00f512015-07-01 16:44:58 +02001226 * type: 0 - min, 1 - max
1227 */
1228static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001229deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001230{
1231 const char *value;
1232 char *endptr;
1233 unsigned long val;
1234 uint32_t *ui32val;
1235
1236 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001237 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001238 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001239 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001240 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001241 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001242 }
Radek Krejci76512572015-08-04 09:47:08 +02001243 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001244 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001245 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001246 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001247 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001248 }
1249 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001250 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1251 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001252 goto error;
1253 }
1254
1255 GETVAL(value, node, "value");
1256 while (isspace(value[0])) {
1257 value++;
1258 }
1259
1260 /* convert it to uint32_t */
1261 errno = 0;
1262 endptr = NULL;
1263 val = strtoul(value, &endptr, 10);
1264 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001265 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001266 goto error;
1267 }
1268 if (type) {
1269 d->max = (uint32_t)val;
1270 } else {
1271 d->min = (uint32_t)val;
1272 }
1273
1274 if (d->mod == LY_DEVIATE_ADD) {
1275 /* check that there is no current value */
1276 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001277 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1278 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001279 goto error;
1280 }
1281 }
1282
1283 if (d->mod == LY_DEVIATE_DEL) {
1284 /* check values */
1285 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001286 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1287 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001288 goto error;
1289 }
1290 /* remove current min-elements value of the target */
1291 *ui32val = 0;
1292 } else { /* add (already checked) and replace */
1293 /* set new value specified in deviation */
1294 *ui32val = (uint32_t)val;
1295 }
1296
1297 return EXIT_SUCCESS;
1298
1299error:
1300
1301 return EXIT_FAILURE;
1302}
1303
Michal Vasko0d343d12015-08-24 14:57:36 +02001304/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001305static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001306fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001307{
1308 const char *value, **stritem;
1309 struct lyxml_elem *next, *child, *develem;
1310 int c_dev = 0, c_must, c_uniq;
1311 int f_min = 0; /* flags */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001312 int i, j, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001313 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001314 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001315 struct lys_node_choice *choice = NULL;
1316 struct lys_node_leaf *leaf = NULL;
1317 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001318 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001319 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001320 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001321
1322 GETVAL(value, yin, "target-node");
1323 dev->target_name = lydict_insert(module->ctx, value, 0);
1324
1325 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001326 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1327 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001328 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001329 goto error;
1330 }
1331 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001332 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001333 goto error;
1334 }
1335 /* mark the target module as deviated */
1336 dev->target->module->deviated = 1;
1337
1338 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001339 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1340 /* garbage */
1341 lyxml_free_elem(module->ctx, child);
1342 continue;
1343 }
1344
Radek Krejcieb00f512015-07-01 16:44:58 +02001345 if (!strcmp(child->name, "description")) {
1346 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001347 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001348 goto error;
1349 }
1350 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1351 if (!dev->dsc) {
1352 goto error;
1353 }
1354 } else if (!strcmp(child->name, "reference")) {
1355 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001356 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 goto error;
1358 }
1359 dev->ref = read_yin_subnode(module->ctx, child, "text");
1360 if (!dev->ref) {
1361 goto error;
1362 }
1363 } else if (!strcmp(child->name, "deviate")) {
1364 c_dev++;
1365
1366 /* skip lyxml_free_elem() at the end of the loop, node will be
1367 * further processed later
1368 */
1369 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001370
Radek Krejcieb00f512015-07-01 16:44:58 +02001371 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001372 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 goto error;
1374 }
1375
1376 lyxml_free_elem(module->ctx, child);
1377 }
1378
1379 if (c_dev) {
1380 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1381 }
1382
1383 LY_TREE_FOR(yin->child, develem) {
1384 /* init */
1385 f_min = 0;
1386 c_must = 0;
1387 c_uniq = 0;
1388
1389 /* get deviation type */
1390 GETVAL(value, develem, "value");
1391 if (!strcmp(value, "not-supported")) {
1392 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1393 /* no property expected in this case */
1394 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001395 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001396 goto error;
1397 }
1398
Radek Krejci5b917642015-07-02 09:03:13 +02001399 /* and neither any other deviate statement is expected,
1400 * not-supported deviation must be the only deviation of the target
1401 */
1402 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001403 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1404 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001405 goto error;
1406 }
1407
1408
Radek Krejcieb00f512015-07-01 16:44:58 +02001409 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001410 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001411 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001412
Radek Krejci5b917642015-07-02 09:03:13 +02001413 dev->deviate_size = 1;
1414 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001415 } else if (!strcmp(value, "add")) {
1416 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1417 } else if (!strcmp(value, "replace")) {
1418 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1419 } else if (!strcmp(value, "delete")) {
1420 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1421 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001422 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001423 goto error;
1424 }
1425 d = &dev->deviate[dev->deviate_size];
1426
1427 /* process deviation properties */
1428 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001429 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1430 /* garbage */
1431 lyxml_free_elem(module->ctx, child);
1432 continue;
1433 }
1434
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001436 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001437 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001438 goto error;
1439 }
1440
1441 /* for we deviate from RFC 6020 and allow config property even it is/is not
1442 * specified in the target explicitly since config property inherits. So we expect
1443 * that config is specified in every node. But for delete, we check that the value
1444 * is the same as here in deviation
1445 */
1446 GETVAL(value, child, "value");
1447 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001448 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001449 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001450 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001451 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001452 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001453 goto error;
1454 }
1455
1456 if (d->mod == LY_DEVIATE_DEL) {
1457 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001458 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001459 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1460 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001461 goto error;
1462 }
1463 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001464 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001465
1466 /* ... and inherit config value from the target's parent */
1467 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001468 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001469 } else {
1470 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001471 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 }
1473 } else { /* add and replace are the same in this case */
1474 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001475 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001476
1477 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001478 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001479 }
1480 } else if (!strcmp(child->name, "default")) {
1481 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001482 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001483 goto error;
1484 }
1485 GETVAL(value, child, "value");
1486 d->dflt = lydict_insert(module->ctx, value, 0);
1487
Radek Krejci76512572015-08-04 09:47:08 +02001488 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001489 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001490
1491 if (d->mod == LY_DEVIATE_ADD) {
1492 /* check that there is no current value */
1493 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001494 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1495 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001496 goto error;
1497 }
1498 }
1499
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001500 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1501 if (rc) {
1502 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1503 goto error;
1504 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001505 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001506 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001507 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1508 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001509 goto error;
1510 }
1511 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001512 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 if (!choice->dflt) {
1514 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001515 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001516 goto error;
1517 }
1518 }
Radek Krejci76512572015-08-04 09:47:08 +02001519 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001520 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001521
1522 if (d->mod == LY_DEVIATE_ADD) {
1523 /* check that there is no current value */
1524 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001525 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1526 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001527 goto error;
1528 }
1529 }
1530
1531 if (d->mod == LY_DEVIATE_DEL) {
1532 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001533 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1534 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001535 goto error;
1536 }
1537 /* remove value */
1538 lydict_remove(leaf->module->ctx, leaf->dflt);
1539 leaf->dflt = NULL;
1540 } else { /* add (already checked) and replace */
1541 /* remove value */
1542 lydict_remove(leaf->module->ctx, leaf->dflt);
1543
1544 /* set new value */
1545 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1546 }
1547 } else {
1548 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001549 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1550 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001551 goto error;
1552 }
1553 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001554 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001555 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001556 goto error;
1557 }
1558
1559 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001560 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001561 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1562 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001563 goto error;
1564 }
1565
1566 GETVAL(value, child, "value");
1567 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001568 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001569 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001570 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001571 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001572 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001573 goto error;
1574 }
1575
1576 if (d->mod == LY_DEVIATE_ADD) {
1577 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001578 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001579 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1580 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001581 goto error;
1582 }
1583 }
1584
1585 if (d->mod == LY_DEVIATE_DEL) {
1586 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001587 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001588 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1589 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001590 goto error;
1591 }
1592 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001593 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001594 } else { /* add (already checked) and replace */
1595 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001596 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001597
1598 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001599 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001600 }
1601 } else if (!strcmp(child->name, "min-elements")) {
1602 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001603 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001604 goto error;
1605 }
1606 f_min = 1;
1607
1608 if (deviate_minmax(dev->target, child, d, 0)) {
1609 goto error;
1610 }
1611 } else if (!strcmp(child->name, "max-elements")) {
1612 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001613 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001614 goto error;
1615 }
1616
1617 if (deviate_minmax(dev->target, child, d, 1)) {
1618 goto error;
1619 }
1620 } else if (!strcmp(child->name, "must")) {
1621 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001622 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1623 continue;
1624 } else if (!strcmp(child->name, "type")) {
1625 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001626 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001627 goto error;
1628 }
1629
1630 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001631 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001632 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001633 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001634 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001635 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001636 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1637 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001638 goto error;
1639 }
1640
1641 if (d->mod == LY_DEVIATE_ADD) {
1642 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001643 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1644 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 } else if (d->mod == LY_DEVIATE_DEL) {
1647 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001648 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1649 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 goto error;
1651 }
1652
1653 /* replace */
1654 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001655 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001656
1657 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001658 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001659 goto error;
1660 }
1661 d->type = t;
1662 } else if (!strcmp(child->name, "unique")) {
1663 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001664 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1665 continue;
1666 } else if (!strcmp(child->name, "units")) {
1667 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001668 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 goto error;
1670 }
1671
1672 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001673 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001674 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001675 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001676 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001677 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001678 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1679 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001680 goto error;
1681 }
1682
1683 /* get units value */
1684 GETVAL(value, child, "name");
1685 d->units = lydict_insert(module->ctx, value, 0);
1686
1687 /* apply to target */
1688 if (d->mod == LY_DEVIATE_ADD) {
1689 /* check that there is no current value */
1690 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001691 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1692 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001693 goto error;
1694 }
1695 }
1696
1697 if (d->mod == LY_DEVIATE_DEL) {
1698 /* check values */
1699 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001700 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1701 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 goto error;
1703 }
1704 /* remove current units value of the target */
1705 lydict_remove(dev->target->module->ctx, *stritem);
1706 } else { /* add (already checked) and replace */
1707 /* remove current units value of the target ... */
1708 lydict_remove(dev->target->module->ctx, *stritem);
1709
1710 /* ... and replace it with the value specified in deviation */
1711 *stritem = lydict_insert(module->ctx, value, 0);
1712 }
1713 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001714 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001715 goto error;
1716 }
1717
1718 lyxml_free_elem(module->ctx, child);
1719 }
1720
1721 if (c_must) {
1722 /* check target node type */
1723 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001724 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001725 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1726 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 break;
Radek Krejci76512572015-08-04 09:47:08 +02001728 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001729 trg_must = &((struct lys_node_container *)dev->target)->must;
1730 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001731 break;
Radek Krejci76512572015-08-04 09:47:08 +02001732 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001733 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1734 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001735 break;
Radek Krejci76512572015-08-04 09:47:08 +02001736 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001737 trg_must = &((struct lys_node_list *)dev->target)->must;
1738 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001739 break;
Radek Krejci76512572015-08-04 09:47:08 +02001740 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001741 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1742 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001743 break;
1744 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001745 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1746 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 goto error;
1748 }
1749
1750 if (d->mod == LY_DEVIATE_RPL) {
1751 /* remove target's musts and allocate new array for it */
1752 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001753 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1754 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001755 goto error;
1756 }
1757
1758 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001759 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001760 }
1761 free(*trg_must);
1762 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1763 d->must_size = c_must;
1764 *trg_must_size = 0;
1765 } else if (d->mod == LY_DEVIATE_ADD) {
1766 /* reallocate the must array of the target */
1767 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1768 *trg_must = d->must;
1769 d->must = &(*trg_must[*trg_must_size]);
1770 d->must_size = c_must;
1771 } else { /* LY_DEVIATE_DEL */
1772 d->must = calloc(c_must, sizeof *d->must);
1773 }
1774 }
1775 if (c_uniq) {
1776 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001777 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001778 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1779 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001780 goto error;
1781 }
1782
Radek Krejcib8048692015-08-05 13:36:34 +02001783 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001784 if (d->mod == LY_DEVIATE_RPL) {
1785 /* remove target's unique and allocate new array for it */
1786 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001787 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1788 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001789 goto error;
1790 }
1791
1792 for (i = 0; i < list->unique_size; i++) {
1793 free(list->unique[i].leafs);
1794 }
1795 free(list->unique);
1796 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1797 d->unique_size = c_uniq;
1798 list->unique_size = 0;
1799 } else if (d->mod == LY_DEVIATE_ADD) {
1800 /* reallocate the unique array of the target */
1801 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1802 list->unique = d->unique;
1803 d->unique = &list->unique[list->unique_size];
1804 d->unique_size = c_uniq;
1805 } else { /* LY_DEVIATE_DEL */
1806 d->unique = calloc(c_uniq, sizeof *d->unique);
1807 }
1808 }
1809
1810 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001811 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001812 if (!strcmp(child->name, "must")) {
1813 if (d->mod == LY_DEVIATE_DEL) {
1814 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1815 goto error;
1816 }
1817
1818 /* find must to delete, we are ok with just matching conditions */
1819 for (i = 0; i < *trg_must_size; i++) {
1820 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1821 /* we have a match, free the must structure ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001822 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001823 /* ... and maintain the array */
1824 (*trg_must_size)--;
1825 if (i != *trg_must_size) {
1826 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1827 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1828 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1829 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1830 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1831 }
1832 if (!(*trg_must_size)) {
1833 free(*trg_must);
1834 *trg_must = NULL;
1835 } else {
1836 (*trg_must)[*trg_must_size].expr = NULL;
1837 (*trg_must)[*trg_must_size].dsc = NULL;
1838 (*trg_must)[*trg_must_size].ref = NULL;
1839 (*trg_must)[*trg_must_size].eapptag = NULL;
1840 (*trg_must)[*trg_must_size].emsg = NULL;
1841 }
1842
1843 i = -1; /* set match flag */
1844 break;
1845 }
1846 }
1847 d->must_size++;
1848 if (i != -1) {
1849 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001850 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1851 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001852 goto error;
1853 }
1854 } else { /* replace or add */
1855 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1856 goto error;
1857 }
1858 (*trg_must_size)++;
1859 }
1860 } else if (!strcmp(child->name, "unique")) {
1861 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001862 GETVAL(value, child, "tag");
1863 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001864 goto error;
1865 }
1866
1867 /* find unique structures to delete */
1868 for (i = 0; i < list->unique_size; i++) {
1869 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1870 continue;
1871 }
1872
1873 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1874 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1875 break;
1876 }
1877 }
1878
1879 if (j == d->unique[d->unique_size].leafs_size) {
1880 /* we have a match, free the unique structure ... */
1881 free(list->unique[i].leafs);
1882 /* ... and maintain the array */
1883 list->unique_size--;
1884 if (i != list->unique_size) {
1885 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1886 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1887 }
1888
1889 if (!list->unique_size) {
1890 free(list->unique);
1891 list->unique = NULL;
1892 } else {
1893 list->unique[list->unique_size].leafs_size = 0;
1894 list->unique[list->unique_size].leafs = NULL;
1895 }
1896
1897 i = -1; /* set match flag */
1898 break;
1899 }
1900 }
1901
1902 d->unique_size++;
1903 if (i != -1) {
1904 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001905 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1906 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001907 goto error;
1908 }
1909 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001910 GETVAL(value, child, "tag");
1911 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001912 goto error;
1913 }
1914 list->unique_size++;
1915 }
1916 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001917 }
Radek Krejci5b917642015-07-02 09:03:13 +02001918
1919 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 }
1921
Radek Krejcieb00f512015-07-01 16:44:58 +02001922 return EXIT_SUCCESS;
1923
1924error:
1925
1926 if (dev->deviate) {
1927 for (i = 0; i < dev->deviate_size; i++) {
1928 lydict_remove(module->ctx, dev->deviate[i].dflt);
1929 lydict_remove(module->ctx, dev->deviate[i].units);
1930
1931 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1932 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001933 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001934 }
1935 free(dev->deviate[i].must);
1936
1937 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1938 free(dev->deviate[i].unique[j].leafs);
1939 }
1940 free(dev->deviate[i].unique);
1941 }
1942 }
1943 free(dev->deviate);
1944 }
1945
1946 return EXIT_FAILURE;
1947}
1948
Michal Vasko0d343d12015-08-24 14:57:36 +02001949/* logs directly */
Radek Krejcieb00f512015-07-01 16:44:58 +02001950static int
Radek Krejcib8048692015-08-05 13:36:34 +02001951fill_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 +02001952 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001953{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001954 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001956 struct lys_node *node;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001957 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02001958
Michal Vasko591e0b22015-08-13 13:53:43 +02001959 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001960 GETVAL(value, yin, "target-node");
1961 aug->target_name = lydict_insert(module->ctx, value, 0);
1962 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001963
Michal Vasko1d87a922015-08-21 12:57:16 +02001964 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001965 goto error;
1966 }
1967
1968 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001969 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1970 /* garbage */
1971 lyxml_free_elem(module->ctx, child);
1972 continue;
1973 }
1974
Radek Krejci3cf9e222015-06-18 11:37:50 +02001975 if (!strcmp(child->name, "if-feature")) {
1976 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001977 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001978 } else if (!strcmp(child->name, "when")) {
1979 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001980 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001981 goto error;
1982 }
1983
1984 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001985 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001986 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001987 goto error;
1988 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02001989 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 +02001990 goto error;
1991 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001992 lyxml_free_elem(module->ctx, child);
1993 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001994
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 /* check allowed data sub-statements */
1996 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001997 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001998 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001999 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002000 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002001 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002002 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002004 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002005 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002006 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002007 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002009 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002010 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002011 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002013 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002014 goto error;
2015 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002016
Radek Krejci1d82ef62015-08-07 14:44:40 +02002017 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002018 goto error;
2019 }
2020
2021 /* check for mandatory nodes - if the target node is in another module
2022 * the added nodes cannot be mandatory
2023 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002024 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002025 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002026 goto error;
2027 }
2028
Radek Krejci1d82ef62015-08-07 14:44:40 +02002029 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002030 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002031 }
2032
2033 if (c) {
2034 aug->features = calloc(c, sizeof *aug->features);
2035 }
2036
2037 LY_TREE_FOR_SAFE(yin->child, next, child) {
2038 if (!strcmp(child->name, "if-feature")) {
2039 GETVAL(value, child, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002040 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 +02002041 goto error;
2042 }
Radek Krejci73adb602015-07-02 18:07:40 +02002043 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002044 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002045 }
2046
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002048 * connected to the tree and adjusted (if possible right now).
2049 * However, if this is augment in a uses, it gets resolved
2050 * when the uses does and cannot be resolved now for sure
2051 * (the grouping was not yet copied into uses).
2052 */
2053 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko1d87a922015-08-21 12:57:16 +02002054 if (resolve_augment(aug, aug->child)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002055 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2056 goto error;
2057 }
Michal Vasko49291b32015-08-06 09:49:41 +02002058 }
Radek Krejci106efc02015-06-10 14:36:27 +02002059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002061
2062error:
2063
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002065}
2066
Michal Vasko0d343d12015-08-24 14:57:36 +02002067/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068static int
Radek Krejcib8048692015-08-05 13:36:34 +02002069fill_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 +02002070 struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002071{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 struct lyxml_elem *sub, *next;
2073 const char *value;
2074 char *endptr;
2075 int f_mand = 0, f_min = 0, f_max = 0;
2076 int c_must = 0;
2077 int r;
2078 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002079
Radek Krejci76512572015-08-04 09:47:08 +02002080 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002081 goto error;
2082 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002083
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002084 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002085 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002088 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2089 /* garbage */
2090 lyxml_free_elem(module->ctx, sub);
2091 continue;
2092 }
2093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 /* limited applicability */
2095 if (!strcmp(sub->name, "default")) {
2096 /* leaf or choice */
2097 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002098 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 goto error;
2100 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002102 /* check possibility of statements combination */
2103 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002104 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002106 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 goto error;
2108 }
2109 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002110 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 GETVAL(value, sub, "value");
2114 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2115 } else if (!strcmp(sub->name, "mandatory")) {
2116 /* leaf, choice or anyxml */
2117 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002118 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 goto error;
2120 }
2121 /* just checking the flags in leaf is not sufficient, we would allow
2122 * multiple mandatory statements with the "false" value
2123 */
2124 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 /* check possibility of statements combination */
2127 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002128 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002129 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002130 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 goto error;
2132 }
2133 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002134 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002135 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 GETVAL(value, sub, "value");
2138 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002139 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002140 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002141 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002142 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002143 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002144 goto error;
2145 }
2146 } else if (!strcmp(sub->name, "min-elements")) {
2147 /* list or leaf-list */
2148 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002149 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 goto error;
2151 }
2152 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 /* check possibility of statements combination */
2155 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002156 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002157 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002158 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002159 goto error;
2160 }
2161 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002162 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002164
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002165 GETVAL(value, sub, "value");
2166 while (isspace(value[0])) {
2167 value++;
2168 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002169
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 /* convert it to uint32_t */
2171 errno = 0;
2172 endptr = NULL;
2173 val = strtoul(value, &endptr, 10);
2174 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002175 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002176 goto error;
2177 }
2178 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 /* magic - bit 3 in flags means min set */
2181 rfn->flags |= 0x04;
2182 } else if (!strcmp(sub->name, "max-elements")) {
2183 /* list or leaf-list */
2184 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002185 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 goto error;
2187 }
2188 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 /* check possibility of statements combination */
2191 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002192 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002194 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 goto error;
2196 }
2197 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002198 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002201 GETVAL(value, sub, "value");
2202 while (isspace(value[0])) {
2203 value++;
2204 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002205
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 /* convert it to uint32_t */
2207 errno = 0;
2208 endptr = NULL;
2209 val = strtoul(value, &endptr, 10);
2210 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002211 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 goto error;
2213 }
2214 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 /* magic - bit 4 in flags means min set */
2217 rfn->flags |= 0x08;
2218 } else if (!strcmp(sub->name, "presence")) {
2219 /* container */
2220 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002221 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002222 goto error;
2223 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002225 /* check possibility of statements combination */
2226 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002227 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002229 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 goto error;
2231 }
2232 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002233 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 GETVAL(value, sub, "value");
2237 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2238 } else if (!strcmp(sub->name, "must")) {
2239 /* leaf-list, list, container or anyxml */
2240 /* check possibility of statements combination */
2241 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002242 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002244 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 goto error;
2246 }
2247 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002248 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002252 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002255 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 goto error;
2257 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002258
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 lyxml_free_elem(module->ctx, sub);
2260 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 /* process nodes with cardinality of 0..n */
2263 if (c_must) {
2264 rfn->must = calloc(c_must, sizeof *rfn->must);
2265 }
Radek Krejci73adb602015-07-02 18:07:40 +02002266 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002267 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002268 if (r) {
2269 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002270 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002271 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 +02002272 LOGLINE(sub)) == -1) {
2273 goto error;
2274 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002275 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002278
2279error:
2280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002282}
2283
Michal Vasko0d343d12015-08-24 14:57:36 +02002284/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285static int
Radek Krejcib8048692015-08-05 13:36:34 +02002286fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002287{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002288 struct lyxml_elem *child;
2289 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002292 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2293 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002294 continue;
2295 }
2296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002297 if (!strcmp(child->name, "prefix")) {
2298 GETVAL(value, child, "value");
2299 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2300 goto error;
2301 }
2302 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2303 } else if (!strcmp(child->name, "revision-date")) {
2304 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002305 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002306 goto error;
2307 }
2308 GETVAL(value, child, "date");
2309 if (check_date(value, LOGLINE(child))) {
2310 goto error;
2311 }
2312 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2313 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002314 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002315 goto error;
2316 }
2317 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002319 /* check mandatory information */
2320 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002321 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 goto error;
2323 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002326 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002328 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2329 if (!imp->module) {
2330 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2331 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002332 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002333 goto error;
2334 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002338
2339error:
2340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002342}
2343
Michal Vasko0d343d12015-08-24 14:57:36 +02002344/* logs directly */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345static int
Radek Krejcib8048692015-08-05 13:36:34 +02002346fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002347{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 struct lyxml_elem *child;
2349 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002352 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2353 /* garbage */
2354 continue;
2355 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 if (!strcmp(child->name, "revision-date")) {
2357 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002358 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 goto error;
2360 }
2361 GETVAL(value, child, "date");
2362 if (check_date(value, LOGLINE(child))) {
2363 goto error;
2364 }
2365 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2366 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002367 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368 goto error;
2369 }
2370 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002371
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002372 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002373 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002375 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 +02002376 if (!inc->submodule) {
2377 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2378 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002379 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002380 goto error;
2381 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002382 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 /* check that belongs-to corresponds */
2385 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002386 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002387 }
2388 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002389 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2390 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002391 goto error;
2392 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002393
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002394 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002395
2396error:
2397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002399}
2400
Michal Vasko0d343d12015-08-24 14:57:36 +02002401/* logs directly
2402 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002403 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002404 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002405 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002406 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002407static int
Radek Krejcib8048692015-08-05 13:36:34 +02002408read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002409 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002410{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002411 const char *value;
2412 struct lyxml_elem *sub, *next;
2413 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002414
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002415 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002416 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002417 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002418
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002419 if (opt & OPT_IDENT) {
2420 GETVAL(value, xmlnode, "name");
2421 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2422 goto error;
2423 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002424 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002426
Radek Krejci6764bb32015-07-03 15:16:04 +02002427 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002428 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002429 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002430 }
2431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002432 /* process local parameters */
2433 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002434 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002435 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002436 lyxml_free_elem(ctx, sub);
2437 continue;
2438 }
2439 if (strcmp(sub->ns->value, LY_NSYIN)) {
2440 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002441 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002442 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002443 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002444 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002445 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002446 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002447 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002448 goto error;
2449 }
2450 }
2451
2452 /* else garbage */
2453 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002454 continue;
2455 }
2456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002457 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002458 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002459 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 goto error;
2461 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002462 node->dsc = read_yin_subnode(ctx, sub, "text");
2463 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002464 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 }
2466 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002468 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469 goto error;
2470 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471 node->ref = read_yin_subnode(ctx, sub, "text");
2472 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002473 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 }
2475 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002476 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002477 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 goto error;
2479 }
2480 GETVAL(value, sub, "value");
2481 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002482 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002483 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002484 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002486 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002487 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002488 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002489 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002490 }
2491 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002492 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002493 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 goto error;
2495 }
2496 GETVAL(value, sub, "value");
2497 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002498 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002499 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002500 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002501 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002502 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002503 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002504 }
2505 } else {
2506 /* skip the lyxml_free_elem */
2507 continue;
2508 }
2509 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002510 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002511
Radek Krejci1d82ef62015-08-07 14:44:40 +02002512 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 /* get config flag from parent */
2514 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002515 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002516 } else {
2517 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002518 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002519 }
2520 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002521
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002522 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002523
2524error:
2525
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002526 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002527}
2528
Michal Vasko0d343d12015-08-24 14:57:36 +02002529/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002530static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002531read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002532{
Radek Krejci76512572015-08-04 09:47:08 +02002533 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002534 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002535 const char *value;
2536
2537 retval = calloc(1, sizeof *retval);
2538
2539 GETVAL(value, yin, "condition");
2540 retval->cond = lydict_insert(module->ctx, value, 0);
2541
Radek Krejci73adb602015-07-02 18:07:40 +02002542 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002543 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2544 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002545 continue;
2546 }
2547
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002548 if (!strcmp(child->name, "description")) {
2549 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002550 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002551 goto error;
2552 }
2553 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2554 if (!retval->dsc) {
2555 goto error;
2556 }
2557 } else if (!strcmp(child->name, "reference")) {
2558 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002559 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002560 goto error;
2561 }
2562 retval->ref = read_yin_subnode(module->ctx, child, "text");
2563 if (!retval->ref) {
2564 goto error;
2565 }
2566 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002567 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002568 goto error;
2569 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002570 }
2571
2572 return retval;
2573
2574error:
2575
Radek Krejci1d82ef62015-08-07 14:44:40 +02002576 lys_node_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002577 return NULL;
2578}
2579
Michal Vasko0d343d12015-08-24 14:57:36 +02002580/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002581static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002582read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2583 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002584{
Michal Vasko29fc0182015-08-24 15:02:39 +02002585 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002586 struct lys_node_case *cs;
2587 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002588 int c_ftrs = 0;
2589 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002590
Radek Krejcie867c852015-08-27 09:52:34 +02002591 /* init */
2592 memset(&root, 0, sizeof root);
2593
Radek Krejci1d82ef62015-08-07 14:44:40 +02002594 cs = calloc(1, sizeof *cs);
2595 cs->nodetype = LYS_CASE;
2596 cs->prev = (struct lys_node *)cs;
2597 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002598
Radek Krejci6a113852015-07-03 16:04:20 +02002599 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 goto error;
2601 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002602
Radek Krejcia9544502015-08-14 08:24:29 +02002603 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2604
Michal Vasko3a0043f2015-08-12 12:11:30 +02002605 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002606 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002607 goto error;
2608 }
2609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002610 /* process choice's specific children */
2611 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002612 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2613 /* garbage */
2614 lyxml_free_elem(module->ctx, sub);
2615 continue;
2616 }
2617
Michal Vasko29fc0182015-08-24 15:02:39 +02002618 if (!strcmp(sub->name, "container") ||
2619 !strcmp(sub->name, "leaf-list") ||
2620 !strcmp(sub->name, "leaf") ||
2621 !strcmp(sub->name, "list") ||
2622 !strcmp(sub->name, "uses") ||
2623 !strcmp(sub->name, "choice") ||
2624 !strcmp(sub->name, "anyxml")) {
2625
2626 lyxml_unlink_elem(module->ctx, sub, 1);
2627 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002628 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002629 c_ftrs++;
2630 /* 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 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002645
2646 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002648 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002649 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002650 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002651 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002652
Radek Krejci3cf9e222015-06-18 11:37:50 +02002653 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002654 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002655 }
Radek Krejci73adb602015-07-02 18:07:40 +02002656 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002657 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002658 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 +02002659 goto error;
2660 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002661 }
Radek Krejcib388c152015-06-04 17:03:03 +02002662
Michal Vasko29fc0182015-08-24 15:02:39 +02002663 /* last part - process data nodes */
2664 LY_TREE_FOR_SAFE(root.child, next, sub) {
2665 if (!strcmp(sub->name, "container")) {
2666 node = read_yin_container(module, retval, sub, resolve, unres);
2667 } else if (!strcmp(sub->name, "leaf-list")) {
2668 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2669 } else if (!strcmp(sub->name, "leaf")) {
2670 node = read_yin_leaf(module, retval, sub, resolve, unres);
2671 } else if (!strcmp(sub->name, "list")) {
2672 node = read_yin_list(module, retval, sub, resolve, unres);
2673 } else if (!strcmp(sub->name, "choice")) {
2674 node = read_yin_choice(module, retval, sub, resolve, unres);
2675 } else if (!strcmp(sub->name, "uses")) {
2676 node = read_yin_uses(module, retval, sub, resolve, unres);
2677 } else if (!strcmp(sub->name, "anyxml")) {
2678 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2679 }
2680 if (!node) {
2681 goto error;
2682 }
2683
2684 lyxml_free_elem(module->ctx, sub);
2685 }
2686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002688
2689error:
2690
Michal Vasko29fc0182015-08-24 15:02:39 +02002691 while (root.child) {
2692 lyxml_free_elem(module->ctx, root.child);
2693 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002694 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002695
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002697}
2698
Michal Vasko0d343d12015-08-24 14:57:36 +02002699/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002700static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002701read_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 +02002702{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002703 struct lyxml_elem *sub, *next;
2704 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002705 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002706 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002707 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002708 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002711 choice->nodetype = LYS_CHOICE;
2712 choice->prev = (struct lys_node *)choice;
2713 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002714
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002715 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2716 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002717 goto error;
2718 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002719
Radek Krejcia9544502015-08-14 08:24:29 +02002720 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2721
Michal Vasko3a0043f2015-08-12 12:11:30 +02002722 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002723 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002724 goto error;
2725 }
2726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002727 /* process choice's specific children */
2728 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002729 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2730 /* garbage */
2731 lyxml_free_elem(module->ctx, sub);
2732 continue;
2733 }
2734
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002735 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002736 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002737 goto error;
2738 }
2739 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002740 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002741 goto error;
2742 }
2743 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002744 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 }
2747 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002748 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 goto error;
2750 }
2751 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002752 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 goto error;
2754 }
2755 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002756 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002757 goto error;
2758 }
2759 } else if (!strcmp(sub->name, "default")) {
2760 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002761 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 goto error;
2763 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002764 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 } else if (!strcmp(sub->name, "mandatory")) {
2766 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002767 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002768 goto error;
2769 }
2770 /* just checking the flags in leaf is not sufficient, we would allow
2771 * multiple mandatory statements with the "false" value
2772 */
2773 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002774
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002775 GETVAL(value, sub, "value");
2776 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002777 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002778 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002779 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002780 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002781 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 goto error;
2783 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002784 } else if (!strcmp(sub->name, "when")) {
2785 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002786 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002787 goto error;
2788 }
2789
2790 choice->when = read_yin_when(module, sub);
2791 if (!choice->when) {
2792 goto error;
2793 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002794 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002795 goto error;
2796 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002797 } else if (!strcmp(sub->name, "if-feature")) {
2798 c_ftrs++;
2799
2800 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2801 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002803 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002804 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002805 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002806
Radek Krejci1d82ef62015-08-07 14:44:40 +02002807 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 lyxml_free_elem(ctx, sub);
2809 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002810
Radek Krejci3cf9e222015-06-18 11:37:50 +02002811 if (c_ftrs) {
2812 choice->features = calloc(c_ftrs, sizeof *choice->features);
2813 }
2814
Radek Krejci73adb602015-07-02 18:07:40 +02002815 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002816 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002817 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 +02002818 goto error;
2819 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002820 }
2821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002822 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002823 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002824 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002825 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2826 goto error;
2827 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002829 /* link default with the case */
2830 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002831 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002832 goto error;
2833 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002834 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002837
2838error:
2839
Radek Krejci1d82ef62015-08-07 14:44:40 +02002840 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002841
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002843}
2844
Michal Vasko0d343d12015-08-24 14:57:36 +02002845/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002846static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002847read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002848 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002849{
Radek Krejci76512572015-08-04 09:47:08 +02002850 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002851 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002852 struct lyxml_elem *sub, *next;
2853 const char *value;
2854 int r;
2855 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002856 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002859 anyxml->nodetype = LYS_ANYXML;
2860 anyxml->prev = (struct lys_node *)anyxml;
2861 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002862
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002863 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2864 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002865 goto error;
2866 }
Radek Krejci863c2852015-06-03 15:47:11 +02002867
Radek Krejcia9544502015-08-14 08:24:29 +02002868 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002869
2870 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002871 goto error;
2872 }
2873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002874 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002875 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2876 /* garbage */
2877 lyxml_free_elem(module->ctx, sub);
2878 continue;
2879 }
2880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 if (!strcmp(sub->name, "mandatory")) {
2882 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002883 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 goto error;
2885 }
2886 /* just checking the flags in leaf is not sufficient, we would allow
2887 * multiple mandatory statements with the "false" value
2888 */
2889 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002891 GETVAL(value, sub, "value");
2892 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002893 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002894 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002895 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002896 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002897 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002898 goto error;
2899 }
2900 /* else false is the default value, so we can ignore it */
2901 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002902 } else if (!strcmp(sub->name, "when")) {
2903 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002904 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002905 goto error;
2906 }
2907
2908 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002909 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002910 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002911 goto error;
2912 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002913 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002914 goto error;
2915 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002916 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 } else if (!strcmp(sub->name, "must")) {
2918 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002919 } else if (!strcmp(sub->name, "if-feature")) {
2920 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002923 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 }
2926 }
Radek Krejci863c2852015-06-03 15:47:11 +02002927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 /* middle part - process nodes with cardinality of 0..n */
2929 if (c_must) {
2930 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2931 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002932 if (c_ftrs) {
2933 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2934 }
Radek Krejci863c2852015-06-03 15:47:11 +02002935
Radek Krejci73adb602015-07-02 18:07:40 +02002936 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002937 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002938 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002939 if (r) {
2940 goto error;
2941 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002942 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 +02002943 goto error;
2944 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002945 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002946 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002947 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 +02002948 goto error;
2949 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002951 }
Radek Krejci863c2852015-06-03 15:47:11 +02002952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002953 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002954
2955error:
2956
Radek Krejci1d82ef62015-08-07 14:44:40 +02002957 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002958
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002959 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002960}
2961
Michal Vasko0d343d12015-08-24 14:57:36 +02002962/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002963static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002964read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002965 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002966{
Radek Krejci76512572015-08-04 09:47:08 +02002967 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002968 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 struct lyxml_elem *sub, *next;
2970 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002971 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002972 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002974 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002975 leaf->nodetype = LYS_LEAF;
2976 leaf->prev = (struct lys_node *)leaf;
2977 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002978
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002979 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2980 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 goto error;
2982 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002983
Radek Krejcia9544502015-08-14 08:24:29 +02002984 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002985
2986 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002987 goto error;
2988 }
2989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002991 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2992 /* garbage */
2993 lyxml_free_elem(module->ctx, sub);
2994 continue;
2995 }
2996
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002998 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002999 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 goto error;
3001 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003002 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003003 goto error;
3004 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003005 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 } else if (!strcmp(sub->name, "default")) {
3007 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003008 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 goto error;
3010 }
3011 GETVAL(value, sub, "value");
3012 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003013 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 } else if (!strcmp(sub->name, "units")) {
3015 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003016 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 goto error;
3018 }
3019 GETVAL(value, sub, "name");
3020 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3021 } else if (!strcmp(sub->name, "mandatory")) {
3022 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003023 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 goto error;
3025 }
3026 /* just checking the flags in leaf is not sufficient, we would allow
3027 * multiple mandatory statements with the "false" value
3028 */
3029 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003030
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 GETVAL(value, sub, "value");
3032 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003033 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003034 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003035 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003036 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003037 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 goto error;
3039 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003040 } else if (!strcmp(sub->name, "when")) {
3041 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003042 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003043 goto error;
3044 }
3045
3046 leaf->when = read_yin_when(module, sub);
3047 if (!leaf->when) {
3048 goto error;
3049 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003050 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003051 goto error;
3052 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003053
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003054 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003055 c_must++;
3056 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003057 } else if (!strcmp(sub->name, "if-feature")) {
3058 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003059 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003062 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003064 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 lyxml_free_elem(module->ctx, sub);
3067 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003070 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003071 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003072 goto error;
3073 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003074 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003075 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003076 goto error;
3077 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 /* middle part - process nodes with cardinality of 0..n */
3081 if (c_must) {
3082 leaf->must = calloc(c_must, sizeof *leaf->must);
3083 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003084 if (c_ftrs) {
3085 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3086 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003087
Radek Krejci73adb602015-07-02 18:07:40 +02003088 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003089 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003090 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 if (r) {
3092 goto error;
3093 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003094 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 +02003095 goto error;
3096 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003097 } else if (!strcmp(sub->name, "if-feature")) {
3098 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003099 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 +02003100 goto error;
3101 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003103 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003104
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003105 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003106
3107error:
3108
Radek Krejci1d82ef62015-08-07 14:44:40 +02003109 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003111 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003112}
3113
Michal Vasko0d343d12015-08-24 14:57:36 +02003114/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003115static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003116read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003117 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003118{
Radek Krejci76512572015-08-04 09:47:08 +02003119 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003120 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003121 struct lyxml_elem *sub, *next;
3122 const char *value;
3123 char *endptr;
3124 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003125 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003126 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003128
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003130 llist->nodetype = LYS_LEAFLIST;
3131 llist->prev = (struct lys_node *)llist;
3132 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003133
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003134 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3135 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003136 goto error;
3137 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003138
Radek Krejcia9544502015-08-14 08:24:29 +02003139 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003140
3141 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003142 goto error;
3143 }
3144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003146 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3147 /* garbage */
3148 lyxml_free_elem(module->ctx, sub);
3149 continue;
3150 }
3151
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003153 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003154 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 goto error;
3156 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003157 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 goto error;
3159 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003160 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 } else if (!strcmp(sub->name, "units")) {
3162 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003163 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 goto error;
3165 }
3166 GETVAL(value, sub, "name");
3167 llist->units = lydict_insert(module->ctx, value, strlen(value));
3168 } else if (!strcmp(sub->name, "ordered-by")) {
3169 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003170 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003171 goto error;
3172 }
3173 /* just checking the flags in llist is not sufficient, we would
3174 * allow multiple ordered-by statements with the "system" value
3175 */
3176 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003177
Radek Krejci1574a8d2015-08-03 14:16:52 +02003178 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3180 * state data
3181 */
3182 lyxml_free_elem(module->ctx, sub);
3183 continue;
3184 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 GETVAL(value, sub, "value");
3187 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003188 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003189 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003190 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003192 } /* else system is the default value, so we can ignore it */
3193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 } else if (!strcmp(sub->name, "must")) {
3195 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003196 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003197 } else if (!strcmp(sub->name, "if-feature")) {
3198 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003199 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003200
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 } else if (!strcmp(sub->name, "min-elements")) {
3202 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003203 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 goto error;
3205 }
3206 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003208 GETVAL(value, sub, "value");
3209 while (isspace(value[0])) {
3210 value++;
3211 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 /* convert it to uint32_t */
3214 errno = 0;
3215 endptr = NULL;
3216 val = strtoul(value, &endptr, 10);
3217 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003218 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 goto error;
3220 }
3221 llist->min = (uint32_t) val;
3222 } else if (!strcmp(sub->name, "max-elements")) {
3223 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003224 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
3227 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 GETVAL(value, sub, "value");
3230 while (isspace(value[0])) {
3231 value++;
3232 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003234 /* convert it to uint32_t */
3235 errno = 0;
3236 endptr = NULL;
3237 val = strtoul(value, &endptr, 10);
3238 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003239 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003240 goto error;
3241 }
3242 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003243 } else if (!strcmp(sub->name, "when")) {
3244 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003245 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003246 goto error;
3247 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003248
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003249 llist->when = read_yin_when(module, sub);
3250 if (!llist->when) {
3251 goto error;
3252 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003253 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003254 goto error;
3255 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003257 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003259 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 lyxml_free_elem(module->ctx, sub);
3262 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003263
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003265 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003266 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003267 goto error;
3268 }
3269 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003270 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 goto error;
3272 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 /* middle part - process nodes with cardinality of 0..n */
3275 if (c_must) {
3276 llist->must = calloc(c_must, sizeof *llist->must);
3277 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003278 if (c_ftrs) {
3279 llist->features = calloc(c_ftrs, sizeof *llist->features);
3280 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003281
Radek Krejci73adb602015-07-02 18:07:40 +02003282 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003283 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003284 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003285 if (r) {
3286 goto error;
3287 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003288 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 +02003289 goto error;
3290 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003291 } else if (!strcmp(sub->name, "if-feature")) {
3292 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003293 if (unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003294 LOGLINE(sub)) == -1) {
3295 goto error;
3296 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003298 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003301
3302error:
3303
Radek Krejci1d82ef62015-08-07 14:44:40 +02003304 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003305
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003306 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003307}
3308
Michal Vasko0d343d12015-08-24 14:57:36 +02003309/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003310static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003311read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3312 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003313{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003314 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003315 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003317 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003318 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003320 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 char *auxs;
3322 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 /* init */
3325 memset(&root, 0, sizeof root);
3326 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003329 list->nodetype = LYS_LIST;
3330 list->prev = (struct lys_node *)list;
3331 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003332
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003333 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3334 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 goto error;
3336 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003337
Radek Krejcia9544502015-08-14 08:24:29 +02003338 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003340 /* process list's specific children */
3341 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003342 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3343 /* garbage */
3344 lyxml_free_elem(module->ctx, sub);
3345 continue;
3346 }
3347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 /* data statements */
3349 if (!strcmp(sub->name, "container") ||
3350 !strcmp(sub->name, "leaf-list") ||
3351 !strcmp(sub->name, "leaf") ||
3352 !strcmp(sub->name, "list") ||
3353 !strcmp(sub->name, "choice") ||
3354 !strcmp(sub->name, "uses") ||
3355 !strcmp(sub->name, "grouping") ||
3356 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003357 lyxml_unlink_elem(module->ctx, sub, 1);
3358 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 /* array counters */
3361 } else if (!strcmp(sub->name, "key")) {
3362 /* check cardinality 0..1 */
3363 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003364 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 goto error;
3366 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 /* count the number of keys */
3369 GETVAL(value, sub, "value");
3370 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003371 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003372 while ((value = strpbrk(value, " \t\n"))) {
3373 list->keys_size++;
3374 while (isspace(*value)) {
3375 value++;
3376 }
3377 }
3378 list->keys_size++;
3379 list->keys = calloc(list->keys_size, sizeof *list->keys);
3380 } else if (!strcmp(sub->name, "unique")) {
3381 c_uniq++;
Michal Vaskof8879c22015-08-21 09:07:36 +02003382 lyxml_unlink_elem(module->ctx, sub, 1);
3383 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 } else if (!strcmp(sub->name, "typedef")) {
3385 c_tpdf++;
3386 } else if (!strcmp(sub->name, "must")) {
3387 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003388 } else if (!strcmp(sub->name, "if-feature")) {
3389 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 /* optional stetments */
3392 } else if (!strcmp(sub->name, "ordered-by")) {
3393 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003394 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003395 goto error;
3396 }
3397 /* just checking the flags in llist is not sufficient, we would
3398 * allow multiple ordered-by statements with the "system" value
3399 */
3400 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003401
Radek Krejci1574a8d2015-08-03 14:16:52 +02003402 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3404 * state data
3405 */
3406 lyxml_free_elem(module->ctx, sub);
3407 continue;
3408 }
Radek Krejci345ad742015-06-03 11:04:18 +02003409
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 GETVAL(value, sub, "value");
3411 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003412 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003413 } else if (strcmp(value, "system")) {
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 /* else system is the default value, so we can ignore it */
3418 lyxml_free_elem(module->ctx, sub);
3419 } else if (!strcmp(sub->name, "min-elements")) {
3420 if (f_min) {
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_min = 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 > 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->min = (uint32_t) val;
3440 lyxml_free_elem(module->ctx, sub);
3441 } else if (!strcmp(sub->name, "max-elements")) {
3442 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003443 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 goto error;
3445 }
3446 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003447
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003448 GETVAL(value, sub, "value");
3449 while (isspace(value[0])) {
3450 value++;
3451 }
Radek Krejci345ad742015-06-03 11:04:18 +02003452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 /* convert it to uint32_t */
3454 errno = 0;
3455 auxs = NULL;
3456 val = strtoul(value, &auxs, 10);
3457 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003458 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 goto error;
3460 }
3461 list->max = (uint32_t) val;
3462 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003463 } else if (!strcmp(sub->name, "when")) {
3464 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003465 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003466 goto error;
3467 }
3468
3469 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003470 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003471 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003472 goto error;
3473 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003474 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003475 goto error;
3476 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003477 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003478 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003479 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003480 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 }
3482 }
Radek Krejci345ad742015-06-03 11:04:18 +02003483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003485 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003486 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 goto error;
3488 }
3489 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003490 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 goto error;
3492 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003493
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3495 if (c_tpdf) {
3496 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3497 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003498 if (c_must) {
3499 list->must = calloc(c_must, sizeof *list->must);
3500 }
3501 if (c_ftrs) {
3502 list->features = calloc(c_ftrs, sizeof *list->features);
3503 }
Radek Krejci73adb602015-07-02 18:07:40 +02003504 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003506 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003507
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003508 if (r) {
3509 goto error;
3510 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003511 } else if (!strcmp(sub->name, "if-feature")) {
3512 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003513 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 +02003514 goto error;
3515 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003516 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003517 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003518 if (r) {
3519 goto error;
3520 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003521 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 +02003522 goto error;
3523 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003524 }
3525 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003526
Radek Krejci10c760e2015-08-14 14:45:43 +02003527 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003528 goto error;
3529 }
3530
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003531 /* last part - process data nodes */
3532 LY_TREE_FOR_SAFE(root.child, next, sub) {
3533 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003534 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003535 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003536 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003538 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003540 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003541 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003542 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003544 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003545 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003546 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003547 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003548 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003549 } else {
3550 LOGINT;
3551 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003552 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003553 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003554 goto error;
3555 }
Radek Krejci73adb602015-07-02 18:07:40 +02003556
3557 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003559
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 if (!key_str) {
3561 /* config false list without a key */
3562 return retval;
3563 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003564 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003565 goto error;
3566 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 /* process unique statements */
3569 if (c_uniq) {
3570 list->unique = calloc(c_uniq, sizeof *list->unique);
3571 }
3572 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003573 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003574 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003575 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003576 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003577 LOGLINE(sub)) == -1) {
3578 goto error;
3579 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 lyxml_free_elem(module->ctx, sub);
3582 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003584 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003585
3586error:
3587
Radek Krejci1d82ef62015-08-07 14:44:40 +02003588 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003589 while (root.child) {
3590 lyxml_free_elem(module->ctx, root.child);
3591 }
3592 while (uniq.child) {
3593 lyxml_free_elem(module->ctx, uniq.child);
3594 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003595
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003596 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003597}
3598
Michal Vasko0d343d12015-08-24 14:57:36 +02003599/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003600static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003601read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3602 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003603{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003604 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003605 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003606 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003607 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 const char *value;
3609 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003610 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 /* init */
3613 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003614
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003616 cont->nodetype = LYS_CONTAINER;
3617 cont->prev = (struct lys_node *)cont;
3618 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003619
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003620 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3621 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003622 goto error;
3623 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003624
Radek Krejcia9544502015-08-14 08:24:29 +02003625 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 /* process container's specific children */
3628 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003629 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003630 /* garbage */
3631 lyxml_free_elem(module->ctx, sub);
3632 continue;
3633 }
3634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 if (!strcmp(sub->name, "presence")) {
3636 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003637 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003638 goto error;
3639 }
3640 GETVAL(value, sub, "value");
3641 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003644 } else if (!strcmp(sub->name, "when")) {
3645 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003646 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003647 goto error;
3648 }
3649
3650 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003651 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003652 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003653 goto error;
3654 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003655 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003656 goto error;
3657 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003658 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003660 /* data statements */
3661 } else if (!strcmp(sub->name, "container") ||
3662 !strcmp(sub->name, "leaf-list") ||
3663 !strcmp(sub->name, "leaf") ||
3664 !strcmp(sub->name, "list") ||
3665 !strcmp(sub->name, "choice") ||
3666 !strcmp(sub->name, "uses") ||
3667 !strcmp(sub->name, "grouping") ||
3668 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003669 lyxml_unlink_elem(module->ctx, sub, 1);
3670 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003671
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003672 /* array counters */
3673 } else if (!strcmp(sub->name, "typedef")) {
3674 c_tpdf++;
3675 } else if (!strcmp(sub->name, "must")) {
3676 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003677 } else if (!strcmp(sub->name, "if-feature")) {
3678 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003680 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003681 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 }
3683 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003685 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3686 if (c_tpdf) {
3687 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3688 }
3689 if (c_must) {
3690 cont->must = calloc(c_must, sizeof *cont->must);
3691 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003692 if (c_ftrs) {
3693 cont->features = calloc(c_ftrs, sizeof *cont->features);
3694 }
Radek Krejci800af702015-06-02 13:46:01 +02003695
Radek Krejci73adb602015-07-02 18:07:40 +02003696 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003697 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003698 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 if (r) {
3700 goto error;
3701 }
3702 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003703 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003704 if (r) {
3705 goto error;
3706 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003707 if (unres_schema_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003708 LOGLINE(sub)) == -1) {
3709 goto error;
3710 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003711 } else if (!strcmp(sub->name, "if-feature")) {
3712 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003713 if (unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003714 LOGLINE(sub)) == -1) {
3715 goto error;
3716 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003717 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003719
Radek Krejci10c760e2015-08-14 14:45:43 +02003720 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003721 goto error;
3722 }
3723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 /* last part - process data nodes */
3725 LY_TREE_FOR_SAFE(root.child, next, sub) {
3726 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003727 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003729 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003731 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003733 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003735 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003741 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003743 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 goto error;
3745 }
Radek Krejci73adb602015-07-02 18:07:40 +02003746
3747 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003751
3752error:
3753
Radek Krejci1d82ef62015-08-07 14:44:40 +02003754 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003755 while (root.child) {
3756 lyxml_free_elem(module->ctx, root.child);
3757 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003758
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003760}
3761
Michal Vasko0d343d12015-08-24 14:57:36 +02003762/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003763static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003764read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003765 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003766{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003768 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003769 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003770 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 int r;
3772 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 /* init */
3775 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003778 grp->nodetype = LYS_GROUPING;
3779 grp->prev = (struct lys_node *)grp;
3780 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Michal Vasko71e1aa82015-08-12 12:17:51 +02003782 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 goto error;
3784 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Radek Krejcia9544502015-08-14 08:24:29 +02003786 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3787
Radek Krejci1d82ef62015-08-07 14:44:40 +02003788 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003789 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3790 /* garbage */
3791 lyxml_free_elem(module->ctx, sub);
3792 continue;
3793 }
3794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 /* data statements */
3796 if (!strcmp(sub->name, "container") ||
3797 !strcmp(sub->name, "leaf-list") ||
3798 !strcmp(sub->name, "leaf") ||
3799 !strcmp(sub->name, "list") ||
3800 !strcmp(sub->name, "choice") ||
3801 !strcmp(sub->name, "uses") ||
3802 !strcmp(sub->name, "grouping") ||
3803 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003804 lyxml_unlink_elem(module->ctx, sub, 1);
3805 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 /* array counters */
3808 } else if (!strcmp(sub->name, "typedef")) {
3809 c_tpdf++;
3810 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003811 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 goto error;
3813 }
3814 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003815
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003816 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3817 if (c_tpdf) {
3818 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3819 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003820 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003821 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003822
Radek Krejci73adb602015-07-02 18:07:40 +02003823 if (r) {
3824 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003825 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003826 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003827
Radek Krejci10c760e2015-08-14 14:45:43 +02003828 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003829 goto error;
3830 }
3831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003832 /* last part - process data nodes */
3833 LY_TREE_FOR_SAFE(root.child, next, sub) {
3834 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003835 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003836 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003837 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003838 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003839 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003841 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003842 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003843 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003844 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003845 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003846 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003847 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003848 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003849 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003850 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003851 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003852 goto error;
3853 }
Radek Krejci73adb602015-07-02 18:07:40 +02003854
3855 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003856 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003859
3860error:
3861
Radek Krejci1d82ef62015-08-07 14:44:40 +02003862 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003863 while (root.child) {
3864 lyxml_free_elem(module->ctx, root.child);
3865 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003868}
3869
Michal Vasko0d343d12015-08-24 14:57:36 +02003870/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003871static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003872read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3873 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003874{
Radek Krejcie0674f82015-06-15 13:58:51 +02003875 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003876 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003877 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003878 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003879 int r;
3880 int c_tpdf = 0;
3881
Radek Krejcie0674f82015-06-15 13:58:51 +02003882 /* init */
3883 memset(&root, 0, sizeof root);
3884
Michal Vasko38d01f72015-06-15 09:41:06 +02003885 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003886 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003887
3888 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003889 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003890 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003891 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003892 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003893 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003894 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003895 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003896 }
3897
Radek Krejci76512572015-08-04 09:47:08 +02003898 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003899
Radek Krejci6a113852015-07-03 16:04:20 +02003900 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003901 goto error;
3902 }
3903
Radek Krejcia9544502015-08-14 08:24:29 +02003904 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3905
Michal Vasko38d01f72015-06-15 09:41:06 +02003906 /* data statements */
3907 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003908 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3909 /* garbage */
3910 lyxml_free_elem(module->ctx, sub);
3911 continue;
3912 }
3913
Michal Vasko38d01f72015-06-15 09:41:06 +02003914 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003915 !strcmp(sub->name, "leaf-list") ||
3916 !strcmp(sub->name, "leaf") ||
3917 !strcmp(sub->name, "list") ||
3918 !strcmp(sub->name, "choice") ||
3919 !strcmp(sub->name, "uses") ||
3920 !strcmp(sub->name, "grouping") ||
3921 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003922 lyxml_unlink_elem(module->ctx, sub, 1);
3923 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003925 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003926 } else if (!strcmp(sub->name, "typedef")) {
3927 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003928
Michal Vasko38d01f72015-06-15 09:41:06 +02003929 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003930 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003931 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003932 }
3933 }
3934
3935 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3936 if (c_tpdf) {
3937 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3938 }
3939
Radek Krejci73adb602015-07-02 18:07:40 +02003940 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003941 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003942
Radek Krejci73adb602015-07-02 18:07:40 +02003943 if (r) {
3944 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003945 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003946 }
3947
Radek Krejci10c760e2015-08-14 14:45:43 +02003948 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003949 goto error;
3950 }
3951
Michal Vasko38d01f72015-06-15 09:41:06 +02003952 /* last part - process data nodes */
3953 LY_TREE_FOR_SAFE(root.child, next, sub) {
3954 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003956 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003957 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003958 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003960 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003962 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003964 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003966 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003967 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003968 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003969 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003970 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003971 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003972 goto error;
3973 }
Radek Krejci73adb602015-07-02 18:07:40 +02003974
3975 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003976 }
3977
Michal Vasko38d01f72015-06-15 09:41:06 +02003978 return retval;
3979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003980error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003981
Radek Krejci1d82ef62015-08-07 14:44:40 +02003982 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003983 while (root.child) {
3984 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003985 }
3986
3987 return NULL;
3988}
3989
Michal Vasko0d343d12015-08-24 14:57:36 +02003990/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003991static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003992read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3993 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003994{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003995 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003996 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003997 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003998 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003999 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004000 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004001 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004002
Michal Vaskoc6551b32015-06-16 10:51:43 +02004003 memset(&root, 0, sizeof root);
4004
Michal Vasko0ea41032015-06-16 08:53:55 +02004005 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004006 notif->nodetype = LYS_NOTIF;
4007 notif->prev = (struct lys_node *)notif;
4008 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004009
Radek Krejci6a113852015-07-03 16:04:20 +02004010 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004011 goto error;
4012 }
4013
Radek Krejcia9544502015-08-14 08:24:29 +02004014 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4015
Michal Vasko0ea41032015-06-16 08:53:55 +02004016 /* process rpc's specific children */
4017 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004018 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4019 /* garbage */
4020 lyxml_free_elem(module->ctx, sub);
4021 continue;
4022 }
4023
Michal Vasko0ea41032015-06-16 08:53:55 +02004024 /* data statements */
4025 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004026 !strcmp(sub->name, "leaf-list") ||
4027 !strcmp(sub->name, "leaf") ||
4028 !strcmp(sub->name, "list") ||
4029 !strcmp(sub->name, "choice") ||
4030 !strcmp(sub->name, "uses") ||
4031 !strcmp(sub->name, "grouping") ||
4032 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004033 lyxml_unlink_elem(module->ctx, sub, 1);
4034 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004035
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004036 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004037 } else if (!strcmp(sub->name, "typedef")) {
4038 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004039 } else if (!strcmp(sub->name, "if-feature")) {
4040 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004041 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004042 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004043 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004044 }
4045 }
4046
4047 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4048 if (c_tpdf) {
4049 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4050 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004051 if (c_ftrs) {
4052 notif->features = calloc(c_ftrs, sizeof *notif->features);
4053 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004054
Radek Krejci73adb602015-07-02 18:07:40 +02004055 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004056 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004057 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004058
4059 if (r) {
4060 goto error;
4061 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004062 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004063 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004064 if (unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004065 LOGLINE(sub)) == -1) {
4066 goto error;
4067 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004068 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004069 }
4070
Radek Krejci10c760e2015-08-14 14:45:43 +02004071 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004072 goto error;
4073 }
4074
Michal Vasko0ea41032015-06-16 08:53:55 +02004075 /* last part - process data nodes */
4076 LY_TREE_FOR_SAFE(root.child, next, sub) {
4077 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004078 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004079 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004080 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004081 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004082 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004083 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004084 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004085 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004086 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004087 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004088 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004089 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004090 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004091 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004092 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004093 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004094 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004095 goto error;
4096 }
Radek Krejci73adb602015-07-02 18:07:40 +02004097
4098 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004099 }
4100
Michal Vasko0ea41032015-06-16 08:53:55 +02004101 return retval;
4102
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004103error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004104
Radek Krejci1d82ef62015-08-07 14:44:40 +02004105 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004106 while (root.child) {
4107 lyxml_free_elem(module->ctx, root.child);
4108 }
4109
4110 return NULL;
4111}
4112
Michal Vasko0d343d12015-08-24 14:57:36 +02004113/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004114static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004115read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4116 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004117{
Radek Krejcie0674f82015-06-15 13:58:51 +02004118 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004119 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004120 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004121 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004122 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004123 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004124 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004125
Radek Krejcie0674f82015-06-15 13:58:51 +02004126 /* init */
4127 memset(&root, 0, sizeof root);
4128
Michal Vasko38d01f72015-06-15 09:41:06 +02004129 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004130 rpc->nodetype = LYS_RPC;
4131 rpc->prev = (struct lys_node *)rpc;
4132 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004133
Radek Krejci6a113852015-07-03 16:04:20 +02004134 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004135 goto error;
4136 }
4137
Radek Krejcia9544502015-08-14 08:24:29 +02004138 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4139
Michal Vasko38d01f72015-06-15 09:41:06 +02004140 /* process rpc's specific children */
4141 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004142 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4143 /* garbage */
4144 lyxml_free_elem(module->ctx, sub);
4145 continue;
4146 }
4147
Michal Vasko38d01f72015-06-15 09:41:06 +02004148 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004149 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004150 && (rpc->child->nodetype == LYS_INPUT
4151 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004152 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 goto error;
4154 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004155 lyxml_unlink_elem(module->ctx, sub, 1);
4156 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004157 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004158 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004159 && (rpc->child->nodetype == LYS_INPUT
4160 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004161 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004162 goto error;
4163 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004164 lyxml_unlink_elem(module->ctx, sub, 1);
4165 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004167 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004168 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004169 lyxml_unlink_elem(module->ctx, sub, 1);
4170 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004172 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 } else if (!strcmp(sub->name, "typedef")) {
4174 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004175 } else if (!strcmp(sub->name, "if-feature")) {
4176 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004177 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004178 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004179 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004180 }
4181 }
4182
4183 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4184 if (c_tpdf) {
4185 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4186 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004187 if (c_ftrs) {
4188 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4189 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004190
Radek Krejci73adb602015-07-02 18:07:40 +02004191 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004192 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004193 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004194
4195 if (r) {
4196 goto error;
4197 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004198 } else if (!strcmp(sub->name, "if-feature")) {
4199 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004200 if (unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004201 LOGLINE(sub)) == -1) {
4202 goto error;
4203 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004204 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004205 }
4206
Radek Krejci10c760e2015-08-14 14:45:43 +02004207 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004208 goto error;
4209 }
4210
Michal Vasko38d01f72015-06-15 09:41:06 +02004211 /* last part - process data nodes */
4212 LY_TREE_FOR_SAFE(root.child, next, sub) {
4213 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004214 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004215 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004216 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004217 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004218 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004219 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004220 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 goto error;
4222 }
Radek Krejci73adb602015-07-02 18:07:40 +02004223
4224 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004225 }
4226
Michal Vasko38d01f72015-06-15 09:41:06 +02004227 return retval;
4228
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004229error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004230
Radek Krejci1d82ef62015-08-07 14:44:40 +02004231 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004232 while (root.child) {
4233 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004234 }
4235
4236 return NULL;
4237}
4238
Michal Vasko0d343d12015-08-24 14:57:36 +02004239/* logs directly
4240 *
Radek Krejci74705112015-06-05 10:25:44 +02004241 * resolve - referenced grouping should be bounded to the namespace (resolved)
4242 * only when uses does not appear in grouping. In a case of grouping's uses,
4243 * we just get information but we do not apply augment or refine to it.
4244 */
Radek Krejci76512572015-08-04 09:47:08 +02004245static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004246read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004247 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004248{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004249 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004250 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004251 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004253 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004256 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004257 uses->nodetype = LYS_USES;
4258 uses->prev = (struct lys_node *)uses;
4259 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004260
Radek Krejcia9544502015-08-14 08:24:29 +02004261 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004262 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004263
Radek Krejcia9544502015-08-14 08:24:29 +02004264 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004265 goto error;
4266 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004267
Radek Krejcia9544502015-08-14 08:24:29 +02004268 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4269
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004270 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004271 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004272 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4273 /* garbage */
4274 lyxml_free_elem(module->ctx, sub);
4275 continue;
4276 }
4277
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 if (!strcmp(sub->name, "refine")) {
4279 c_ref++;
4280 } else if (!strcmp(sub->name, "augment")) {
4281 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004282 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004283 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004284 } else if (!strcmp(sub->name, "when")) {
4285 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004286 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004287 goto error;
4288 }
4289
4290 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004291 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004292 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004293 goto error;
4294 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02004295 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004296 goto error;
4297 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004298 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004300 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004301 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 }
4303 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004304
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004305 /* process properties with cardinality 0..n */
4306 if (c_ref) {
4307 uses->refine = calloc(c_ref, sizeof *uses->refine);
4308 }
4309 if (c_aug) {
4310 uses->augment = calloc(c_aug, sizeof *uses->augment);
4311 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004312 if (c_ftrs) {
4313 uses->features = calloc(c_ftrs, sizeof *uses->features);
4314 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004315
Radek Krejci10c760e2015-08-14 14:45:43 +02004316 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004317 goto error;
4318 }
4319
Radek Krejcia9544502015-08-14 08:24:29 +02004320 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004322 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4323 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004324 goto error;
4325 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004326 } else if (!strcmp(sub->name, "augment")) {
4327 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4328 if (r) {
4329 goto error;
4330 }
4331 } else if (!strcmp(sub->name, "if-feature")) {
4332 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004333 if (unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004334 LOGLINE(sub)) == -1) {
4335 goto error;
4336 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 }
4338 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004339
Michal Vasko0bd29d12015-08-19 11:45:49 +02004340 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004341 goto error;
4342 }
Radek Krejci74705112015-06-05 10:25:44 +02004343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 if (resolve) {
4345 /* inherit config flag */
4346 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004347 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 } else {
4349 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004350 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 }
4352 }
Radek Krejcib388c152015-06-04 17:03:03 +02004353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004355
4356error:
4357
Radek Krejci1d82ef62015-08-07 14:44:40 +02004358 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004361}
4362
Michal Vasko0d343d12015-08-24 14:57:36 +02004363/* logs directly
4364 *
4365 * common code for yin_read_module() and yin_read_submodule()
4366 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004368read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004369{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004371 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4373 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004375 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004377 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004378 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 +02004379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 /* init */
4381 memset(&root, 0, sizeof root);
4382 memset(&grps, 0, sizeof grps);
4383 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004384 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004385
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004386 /*
4387 * in the first run, we process elements with cardinality of 1 or 0..1 and
4388 * count elements with cardinality 0..n. Data elements (choices, containers,
4389 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4390 * need have all top-level and groupings already prepared at that time. In
4391 * the middle loop, we process other elements with carinality of 0..n since
4392 * we need to allocate arrays to store them.
4393 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004394 LY_TREE_FOR_SAFE(yin->child, next, child) {
4395 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004396 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004397 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004398 continue;
4399 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004400
Radek Krejci1d82ef62015-08-07 14:44:40 +02004401 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004402 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004403 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 goto error;
4405 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004406 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004408 lyxml_free_elem(ctx, child);
4409 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004410 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004411 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004412 goto error;
4413 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004414 GETVAL(value, child, "value");
4415 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 goto error;
4417 }
4418 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004419 lyxml_free_elem(ctx, child);
4420 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004422 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004423 goto error;
4424 }
4425 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004426 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004427 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004428 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 }
4430 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004431 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 goto error;
4433 }
Radek Krejcif3886932015-06-04 17:36:06 +02004434
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004436 if (!child->child) {
4437 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004439 } else if (strcmp(child->child->name, "prefix")) {
4440 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004442 } else if (child->child->next) {
4443 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 goto error;
4445 }
4446 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004447 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 /* check here differs from a generic prefix check, since this prefix
4449 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004450 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004451 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004452 goto error;
4453 }
4454 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004455
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004456 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004457 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004458
4459 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004460 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004461 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004462 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004464 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004465 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004466 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004467 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004468 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004469 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004470 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004471 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004472 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004473 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004474 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004475 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004476
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004477 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004478 } else if (!strcmp(child->name, "container") ||
4479 !strcmp(child->name, "leaf-list") ||
4480 !strcmp(child->name, "leaf") ||
4481 !strcmp(child->name, "list") ||
4482 !strcmp(child->name, "choice") ||
4483 !strcmp(child->name, "uses") ||
4484 !strcmp(child->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004485 lyxml_unlink_elem(module->ctx, child, 1);
4486 lyxml_add_child(module->ctx, &root, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004487 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 /* keep groupings separated and process them before other data statements */
Michal Vaskof8879c22015-08-21 09:07:36 +02004489 lyxml_unlink_elem(module->ctx, child, 1);
4490 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004492 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004493 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004494 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004495 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004496 goto error;
4497 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004498 module->dsc = read_yin_subnode(ctx, child, "text");
4499 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 if (!module->dsc) {
4501 goto error;
4502 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004503 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004504 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004505 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004506 goto error;
4507 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004508 module->ref = read_yin_subnode(ctx, child, "text");
4509 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 if (!module->ref) {
4511 goto error;
4512 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004513 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004514 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004515 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 goto error;
4517 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004518 module->org = read_yin_subnode(ctx, child, "text");
4519 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 if (!module->org) {
4521 goto error;
4522 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004523 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004525 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 goto error;
4527 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004528 module->contact = read_yin_subnode(ctx, child, "text");
4529 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004530 if (!module->contact) {
4531 goto error;
4532 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004533 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 /* TODO: support YANG 1.1 ? */
4535 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004536 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 goto error;
4538 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004539 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004541 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 goto error;
4543 }
4544 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004545 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004546
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004547 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004548 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004549 lyxml_unlink_elem(module->ctx, child, 1);
4550 lyxml_add_child(module->ctx, &rpcs, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004551 } else if (!strcmp(child->name, "notification")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004552 lyxml_unlink_elem(module->ctx, child, 1);
4553 lyxml_add_child(module->ctx, &notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004554
Radek Krejci1d82ef62015-08-07 14:44:40 +02004555 } else if (!strcmp(child->name, "extension")) {
4556 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004557
Radek Krejci6764bb32015-07-03 15:16:04 +02004558 /* we have 2 supported (hardcoded) extensions:
4559 * NACM's default-deny-write and default-deny-all
4560 */
4561 if (strcmp(module->ns, LY_NSNACM) ||
4562 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4563 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004564 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004565 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004567 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 }
4570 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004571
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 if (!submodule) {
4573 /* check for mandatory statements */
4574 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004575 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004576 goto error;
4577 }
4578 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004579 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 goto error;
4581 }
4582 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004583
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004584 /* allocate arrays for elements with cardinality of 0..n */
4585 if (c_imp) {
4586 module->imp = calloc(c_imp, sizeof *module->imp);
4587 }
4588 if (c_rev) {
4589 module->rev = calloc(c_rev, sizeof *module->rev);
4590 }
4591 if (c_tpdf) {
4592 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4593 }
4594 if (c_ident) {
4595 module->ident = calloc(c_ident, sizeof *module->ident);
4596 }
4597 if (c_inc) {
4598 module->inc = calloc(c_inc, sizeof *module->inc);
4599 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004600 if (c_aug) {
4601 module->augment = calloc(c_aug, sizeof *module->augment);
4602 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004603 if (c_ftrs) {
4604 module->features = calloc(c_ftrs, sizeof *module->features);
4605 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004606 if (c_dev) {
4607 module->deviation = calloc(c_dev, sizeof *module->deviation);
4608 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004609
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 LY_TREE_FOR(yin->child, child) {
4612 if (!strcmp(child->name, "import")) {
4613 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 module->imp_size++;
4615 if (r) {
4616 goto error;
4617 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004619 /* check duplicities in imported modules */
4620 for (i = 0; i < module->imp_size - 1; i++) {
4621 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004622 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 goto error;
4624 }
4625 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004626 } else if (!strcmp(child->name, "include")) {
4627 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 module->inc_size++;
4629 if (r) {
4630 goto error;
4631 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004632
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 /* check duplications in include submodules */
4634 for (i = 0; i < module->inc_size - 1; i++) {
4635 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004636 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004637 module->inc[i].submodule->name);
4638 goto error;
4639 }
4640 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 } else if (!strcmp(child->name, "revision")) {
4642 GETVAL(value, child, "date");
4643 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004644 goto error;
4645 }
4646 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4647 /* check uniqueness of the revision date - not required by RFC */
4648 for (i = 0; i < module->rev_size; i++) {
4649 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004650 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004651 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004652 }
4653 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004654
Radek Krejci1d82ef62015-08-07 14:44:40 +02004655 LY_TREE_FOR(child->child, child2) {
4656 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004658 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 goto error;
4660 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004661 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 if (!module->rev[module->rev_size].dsc) {
4663 goto error;
4664 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004665 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004666 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004667 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 goto error;
4669 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004670 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 if (!module->rev[module->rev_size].ref) {
4672 goto error;
4673 }
4674 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004675 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004676 goto error;
4677 }
4678 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004680 /* keep the latest revision at position 0 */
4681 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4682 /* switch their position */
4683 value = strdup(module->rev[0].date);
4684 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4685 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4686 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004687
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4689 value = module->rev[0].dsc;
4690 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4691 module->rev[module->rev_size].dsc = value;
4692 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4695 value = module->rev[0].ref;
4696 module->rev[0].ref = module->rev[module->rev_size].ref;
4697 module->rev[module->rev_size].ref = value;
4698 }
4699 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004700
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004701 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004702 } else if (!strcmp(child->name, "typedef")) {
4703 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004705
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004706 if (r) {
4707 goto error;
4708 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004709 } else if (!strcmp(child->name, "identity")) {
4710 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004711 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004712
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 if (r) {
4714 goto error;
4715 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004716 } else if (!strcmp(child->name, "feature")) {
4717 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004718 module->features_size++;
4719
4720 if (r) {
4721 goto error;
4722 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004723 } else if (!strcmp(child->name, "augment")) {
4724 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004725 module->augment_size++;
4726
4727 if (r) {
4728 goto error;
4729 }
4730
4731 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4732 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004733 } else if (!strcmp(child->name, "deviation")) {
4734 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004735 module->deviation_size++;
4736
4737 if (r) {
4738 goto error;
4739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004742
Radek Krejcif5be10f2015-06-16 13:29:36 +02004743 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 * refer to them
4745 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004746 LY_TREE_FOR_SAFE(grps.child, next, child) {
4747 node = read_yin_grouping(module, NULL, child, 0, unres);
4748 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004749 goto error;
4750 }
Radek Krejci74705112015-06-05 10:25:44 +02004751
Radek Krejci1d82ef62015-08-07 14:44:40 +02004752 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004753 }
Radek Krejci74705112015-06-05 10:25:44 +02004754
Radek Krejcif5be10f2015-06-16 13:29:36 +02004755 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004756 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004757
Radek Krejci1d82ef62015-08-07 14:44:40 +02004758 if (!strcmp(child->name, "container")) {
4759 node = read_yin_container(module, NULL, child, 1, unres);
4760 } else if (!strcmp(child->name, "leaf-list")) {
4761 node = read_yin_leaflist(module, NULL, child, 1, unres);
4762 } else if (!strcmp(child->name, "leaf")) {
4763 node = read_yin_leaf(module, NULL, child, 1, unres);
4764 } else if (!strcmp(child->name, "list")) {
4765 node = read_yin_list(module, NULL, child, 1, unres);
4766 } else if (!strcmp(child->name, "choice")) {
4767 node = read_yin_choice(module, NULL, child, 1, unres);
4768 } else if (!strcmp(child->name, "uses")) {
4769 node = read_yin_uses(module, NULL, child, 1, unres);
4770 } else if (!strcmp(child->name, "anyxml")) {
4771 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004772 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004773 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 goto error;
4775 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004776
Radek Krejci1d82ef62015-08-07 14:44:40 +02004777 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004779
4780 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004781 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4782 node = read_yin_rpc(module, NULL, child, 0, unres);
4783 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004784 goto error;
4785 }
4786
Radek Krejci1d82ef62015-08-07 14:44:40 +02004787 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004788 }
4789
4790 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004791 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4792 node = read_yin_notif(module, NULL, child, 0, unres);
4793 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004794 goto error;
4795 }
4796
Radek Krejci1d82ef62015-08-07 14:44:40 +02004797 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004798 }
4799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004801
4802error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004803 /* cleanup */
4804 while (root.child) {
4805 lyxml_free_elem(module->ctx, root.child);
4806 }
4807 while (grps.child) {
4808 lyxml_free_elem(module->ctx, grps.child);
4809 }
4810 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004811 lyxml_free_elem(module->ctx, rpcs.child);
4812 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004813
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004814 free(unres->item);
4815 unres->item = NULL;
4816 free(unres->type);
4817 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004818 free(unres->str_snode);
4819 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004820#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004821 free(unres->line);
4822 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004823#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004824 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004826 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004827}
4828
Michal Vasko0d343d12015-08-24 14:57:36 +02004829/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004830struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004831yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004832{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004834 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004837 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 yin = lyxml_read(module->ctx, data, 0);
4840 if (!yin) {
4841 return NULL;
4842 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004843
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 /* check root element */
4845 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004846 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
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 GETVAL(value, yin, "name");
4851 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4852 goto error;
4853 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004855 submodule = calloc(1, sizeof *submodule);
4856 if (!submodule) {
4857 LOGMEM;
4858 goto error;
4859 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004861 submodule->ctx = module->ctx;
4862 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4863 submodule->type = 1;
4864 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004865 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004867 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004868 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 goto error;
4870 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 /* cleanup */
4873 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004876
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004878
4879error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 /* cleanup */
4881 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004882 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004885}
4886
Michal Vasko0d343d12015-08-24 14:57:36 +02004887/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004888struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004889yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004890{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004892 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 const char *value;
4894 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004895
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004896 yin = lyxml_read(ctx, data, 0);
4897 if (!yin) {
4898 return NULL;
4899 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004900
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 /* check root element */
4902 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004903 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004904 goto error;
4905 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004906
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004907 GETVAL(value, yin, "name");
4908 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4909 goto error;
4910 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004911
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004912 module = calloc(1, sizeof *module);
4913 if (!module) {
4914 LOGMEM;
4915 goto error;
4916 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004917
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004918 module->ctx = ctx;
4919 module->name = lydict_insert(ctx, value, strlen(value));
4920 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004921 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004922
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004923 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004924 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004925 goto error;
4926 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 /* add to the context's list of modules */
4929 if (ctx->models.used == ctx->models.size) {
4930 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4931 if (!newlist) {
4932 LOGMEM;
4933 goto error;
4934 }
4935 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4936 newlist[i] = NULL;
4937 }
4938 ctx->models.size *= 2;
4939 ctx->models.list = newlist;
4940 }
4941 for (i = 0; ctx->models.list[i]; i++) {
4942 /* check name (name/revision) and namespace uniqueness */
4943 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004944 if (ctx->models.list[i]->rev_size == module->rev_size) {
4945 /* both have the same number of revisions */
4946 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4947 /* both have the same revision -> we already have the same module */
4948 /* so free the new one and update the old one's implement flag if needed */
4949 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004950 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02004951 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004952
4953 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4954
4955 if (implement && !ctx->models.list[i]->implemented) {
4956 lyp_set_implemented(ctx->models.list[i]);
4957 }
4958 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004959 }
4960 }
Radek Krejcif647e612015-07-30 11:36:07 +02004961 /* else (both elses) keep searching, for now the caller is just adding
4962 * another revision of an already present schema
4963 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004964 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4965 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4966 ctx->models.list[i]->name, module->name, module->ns);
4967 goto error;
4968 }
4969 }
4970 ctx->models.list[i] = module;
4971 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004972 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 /* cleanup */
4975 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004977 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004978
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004980
4981error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004982 /* cleanup */
4983 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004984 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004986 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004987}