blob: 226024de3eb5ac98e8b04d41c6e24f481f489cb1 [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 Krejci1d82ef62015-08-07 14:44:40 +02002591 cs = calloc(1, sizeof *cs);
2592 cs->nodetype = LYS_CASE;
2593 cs->prev = (struct lys_node *)cs;
2594 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002595
Radek Krejci6a113852015-07-03 16:04:20 +02002596 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 goto error;
2598 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002599
Radek Krejcia9544502015-08-14 08:24:29 +02002600 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2601
Michal Vasko3a0043f2015-08-12 12:11:30 +02002602 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002603 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002604 goto error;
2605 }
2606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 /* process choice's specific children */
2608 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002609 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2610 /* garbage */
2611 lyxml_free_elem(module->ctx, sub);
2612 continue;
2613 }
2614
Michal Vasko29fc0182015-08-24 15:02:39 +02002615 if (!strcmp(sub->name, "container") ||
2616 !strcmp(sub->name, "leaf-list") ||
2617 !strcmp(sub->name, "leaf") ||
2618 !strcmp(sub->name, "list") ||
2619 !strcmp(sub->name, "uses") ||
2620 !strcmp(sub->name, "choice") ||
2621 !strcmp(sub->name, "anyxml")) {
2622
2623 lyxml_unlink_elem(module->ctx, sub, 1);
2624 lyxml_add_child(module->ctx, &root, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002625 } else if (!strcmp(sub->name, "if-feature")) {
Michal Vasko29fc0182015-08-24 15:02:39 +02002626 c_ftrs++;
2627 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2628 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002629 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002630 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002631 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002632 goto error;
2633 }
2634
Radek Krejci1d82ef62015-08-07 14:44:40 +02002635 cs->when = read_yin_when(module, sub);
2636 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002637 goto error;
2638 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002639 if (unres_schema_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002640 goto error;
2641 }
Michal Vasko29fc0182015-08-24 15:02:39 +02002642
2643 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002644 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002645 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002647 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002649
Radek Krejci3cf9e222015-06-18 11:37:50 +02002650 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002651 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002652 }
Radek Krejci73adb602015-07-02 18:07:40 +02002653 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002654 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002655 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 +02002656 goto error;
2657 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002658 }
Radek Krejcib388c152015-06-04 17:03:03 +02002659
Michal Vasko29fc0182015-08-24 15:02:39 +02002660 /* last part - process data nodes */
2661 LY_TREE_FOR_SAFE(root.child, next, sub) {
2662 if (!strcmp(sub->name, "container")) {
2663 node = read_yin_container(module, retval, sub, resolve, unres);
2664 } else if (!strcmp(sub->name, "leaf-list")) {
2665 node = read_yin_leaflist(module, retval, sub, resolve, unres);
2666 } else if (!strcmp(sub->name, "leaf")) {
2667 node = read_yin_leaf(module, retval, sub, resolve, unres);
2668 } else if (!strcmp(sub->name, "list")) {
2669 node = read_yin_list(module, retval, sub, resolve, unres);
2670 } else if (!strcmp(sub->name, "choice")) {
2671 node = read_yin_choice(module, retval, sub, resolve, unres);
2672 } else if (!strcmp(sub->name, "uses")) {
2673 node = read_yin_uses(module, retval, sub, resolve, unres);
2674 } else if (!strcmp(sub->name, "anyxml")) {
2675 node = read_yin_anyxml(module, retval, sub, resolve, unres);
2676 }
2677 if (!node) {
2678 goto error;
2679 }
2680
2681 lyxml_free_elem(module->ctx, sub);
2682 }
2683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002685
2686error:
2687
Michal Vasko29fc0182015-08-24 15:02:39 +02002688 while (root.child) {
2689 lyxml_free_elem(module->ctx, root.child);
2690 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002691 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002692
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002694}
2695
Michal Vasko0d343d12015-08-24 14:57:36 +02002696/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002697static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002698read_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 +02002699{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 struct lyxml_elem *sub, *next;
2701 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002702 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002703 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002704 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002705 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002706
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002707 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002708 choice->nodetype = LYS_CHOICE;
2709 choice->prev = (struct lys_node *)choice;
2710 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002711
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002712 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2713 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 goto error;
2715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002716
Radek Krejcia9544502015-08-14 08:24:29 +02002717 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2718
Michal Vasko3a0043f2015-08-12 12:11:30 +02002719 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002720 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002721 goto error;
2722 }
2723
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002724 /* process choice's specific children */
2725 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002726 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2727 /* garbage */
2728 lyxml_free_elem(module->ctx, sub);
2729 continue;
2730 }
2731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002733 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 goto error;
2735 }
2736 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002737 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 goto error;
2739 }
2740 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002741 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002742 goto error;
2743 }
2744 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002745 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 goto error;
2747 }
2748 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002749 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002750 goto error;
2751 }
2752 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002753 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002754 goto error;
2755 }
2756 } else if (!strcmp(sub->name, "default")) {
2757 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002758 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002759 goto error;
2760 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002761 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 } else if (!strcmp(sub->name, "mandatory")) {
2763 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002764 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 goto error;
2766 }
2767 /* just checking the flags in leaf is not sufficient, we would allow
2768 * multiple mandatory statements with the "false" value
2769 */
2770 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 GETVAL(value, sub, "value");
2773 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002774 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002775 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002776 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002777 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002778 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 goto error;
2780 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002781 } else if (!strcmp(sub->name, "when")) {
2782 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002783 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002784 goto error;
2785 }
2786
2787 choice->when = read_yin_when(module, sub);
2788 if (!choice->when) {
2789 goto error;
2790 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002791 if (unres_schema_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002792 goto error;
2793 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002794 } else if (!strcmp(sub->name, "if-feature")) {
2795 c_ftrs++;
2796
2797 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2798 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002800 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002803
Radek Krejci1d82ef62015-08-07 14:44:40 +02002804 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002805 lyxml_free_elem(ctx, sub);
2806 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002807
Radek Krejci3cf9e222015-06-18 11:37:50 +02002808 if (c_ftrs) {
2809 choice->features = calloc(c_ftrs, sizeof *choice->features);
2810 }
2811
Radek Krejci73adb602015-07-02 18:07:40 +02002812 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002813 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002814 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 +02002815 goto error;
2816 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002817 }
2818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002820 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002821 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002822 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2823 goto error;
2824 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002825
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002826 /* link default with the case */
2827 if (dflt_str) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02002828 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002829 goto error;
2830 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002831 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002834
2835error:
2836
Radek Krejci1d82ef62015-08-07 14:44:40 +02002837 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002840}
2841
Michal Vasko0d343d12015-08-24 14:57:36 +02002842/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002843static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002844read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002845 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002846{
Radek Krejci76512572015-08-04 09:47:08 +02002847 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002848 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 struct lyxml_elem *sub, *next;
2850 const char *value;
2851 int r;
2852 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002853 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002855 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002856 anyxml->nodetype = LYS_ANYXML;
2857 anyxml->prev = (struct lys_node *)anyxml;
2858 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002859
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002860 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2861 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002862 goto error;
2863 }
Radek Krejci863c2852015-06-03 15:47:11 +02002864
Radek Krejcia9544502015-08-14 08:24:29 +02002865 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002866
2867 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002868 goto error;
2869 }
2870
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002871 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002872 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2873 /* garbage */
2874 lyxml_free_elem(module->ctx, sub);
2875 continue;
2876 }
2877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 if (!strcmp(sub->name, "mandatory")) {
2879 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002880 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 goto error;
2882 }
2883 /* just checking the flags in leaf is not sufficient, we would allow
2884 * multiple mandatory statements with the "false" value
2885 */
2886 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 GETVAL(value, sub, "value");
2889 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002890 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002891 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002892 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002893 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002894 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 goto error;
2896 }
2897 /* else false is the default value, so we can ignore it */
2898 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002899 } else if (!strcmp(sub->name, "when")) {
2900 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002901 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002902 goto error;
2903 }
2904
2905 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002906 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002907 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002908 goto error;
2909 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002910 if (unres_schema_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002911 goto error;
2912 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002913 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 } else if (!strcmp(sub->name, "must")) {
2915 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002916 } else if (!strcmp(sub->name, "if-feature")) {
2917 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002919 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002920 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002921 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002922 }
2923 }
Radek Krejci863c2852015-06-03 15:47:11 +02002924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 /* middle part - process nodes with cardinality of 0..n */
2926 if (c_must) {
2927 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2928 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002929 if (c_ftrs) {
2930 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2931 }
Radek Krejci863c2852015-06-03 15:47:11 +02002932
Radek Krejci73adb602015-07-02 18:07:40 +02002933 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002935 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 if (r) {
2937 goto error;
2938 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02002939 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 +02002940 goto error;
2941 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002942 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002943 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02002944 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 +02002945 goto error;
2946 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002947 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002948 }
Radek Krejci863c2852015-06-03 15:47:11 +02002949
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002950 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002951
2952error:
2953
Radek Krejci1d82ef62015-08-07 14:44:40 +02002954 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002955
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002956 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002957}
2958
Michal Vasko0d343d12015-08-24 14:57:36 +02002959/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02002960static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002961read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002962 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002963{
Radek Krejci76512572015-08-04 09:47:08 +02002964 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002965 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 struct lyxml_elem *sub, *next;
2967 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002968 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002969 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002972 leaf->nodetype = LYS_LEAF;
2973 leaf->prev = (struct lys_node *)leaf;
2974 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002975
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002976 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2977 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 goto error;
2979 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002980
Radek Krejcia9544502015-08-14 08:24:29 +02002981 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002982
2983 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002984 goto error;
2985 }
2986
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002988 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2989 /* garbage */
2990 lyxml_free_elem(module->ctx, sub);
2991 continue;
2992 }
2993
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002994 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002995 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002996 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002997 goto error;
2998 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002999 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003000 goto error;
3001 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003002 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003003 } else if (!strcmp(sub->name, "default")) {
3004 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003005 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 goto error;
3007 }
3008 GETVAL(value, sub, "value");
3009 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003010 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 } else if (!strcmp(sub->name, "units")) {
3012 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003013 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 goto error;
3015 }
3016 GETVAL(value, sub, "name");
3017 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3018 } else if (!strcmp(sub->name, "mandatory")) {
3019 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003020 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 goto error;
3022 }
3023 /* just checking the flags in leaf is not sufficient, we would allow
3024 * multiple mandatory statements with the "false" value
3025 */
3026 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003027
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003028 GETVAL(value, sub, "value");
3029 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003030 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003031 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003032 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003033 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003034 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 goto error;
3036 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003037 } else if (!strcmp(sub->name, "when")) {
3038 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003039 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003040 goto error;
3041 }
3042
3043 leaf->when = read_yin_when(module, sub);
3044 if (!leaf->when) {
3045 goto error;
3046 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003047 if (unres_schema_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003048 goto error;
3049 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003051 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003052 c_must++;
3053 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003054 } else if (!strcmp(sub->name, "if-feature")) {
3055 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003059 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003061 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 lyxml_free_elem(module->ctx, sub);
3064 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003067 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003068 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 goto error;
3070 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003071 if (leaf->dflt) {
Michal Vasko0bd29d12015-08-19 11:45:49 +02003072 if (unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003073 goto error;
3074 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003076
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003077 /* middle part - process nodes with cardinality of 0..n */
3078 if (c_must) {
3079 leaf->must = calloc(c_must, sizeof *leaf->must);
3080 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003081 if (c_ftrs) {
3082 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3083 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003084
Radek Krejci73adb602015-07-02 18:07:40 +02003085 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003086 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003087 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003088 if (r) {
3089 goto error;
3090 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003091 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 +02003092 goto error;
3093 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003094 } else if (!strcmp(sub->name, "if-feature")) {
3095 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003096 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 +02003097 goto error;
3098 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003100 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003101
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003103
3104error:
3105
Radek Krejci1d82ef62015-08-07 14:44:40 +02003106 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003107
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003108 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003109}
3110
Michal Vasko0d343d12015-08-24 14:57:36 +02003111/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003112static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003113read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003114 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003115{
Radek Krejci76512572015-08-04 09:47:08 +02003116 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003117 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 struct lyxml_elem *sub, *next;
3119 const char *value;
3120 char *endptr;
3121 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003122 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003123 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003126 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003127 llist->nodetype = LYS_LEAFLIST;
3128 llist->prev = (struct lys_node *)llist;
3129 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003130
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003131 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3132 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 goto error;
3134 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003135
Radek Krejcia9544502015-08-14 08:24:29 +02003136 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003137
3138 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003139 goto error;
3140 }
3141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003143 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3144 /* garbage */
3145 lyxml_free_elem(module->ctx, sub);
3146 continue;
3147 }
3148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003149 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003150 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003151 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 goto error;
3153 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003154 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 goto error;
3156 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003157 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 } else if (!strcmp(sub->name, "units")) {
3159 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003160 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 goto error;
3162 }
3163 GETVAL(value, sub, "name");
3164 llist->units = lydict_insert(module->ctx, value, strlen(value));
3165 } else if (!strcmp(sub->name, "ordered-by")) {
3166 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003167 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003168 goto error;
3169 }
3170 /* just checking the flags in llist is not sufficient, we would
3171 * allow multiple ordered-by statements with the "system" value
3172 */
3173 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003174
Radek Krejci1574a8d2015-08-03 14:16:52 +02003175 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003176 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3177 * state data
3178 */
3179 lyxml_free_elem(module->ctx, sub);
3180 continue;
3181 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 GETVAL(value, sub, "value");
3184 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003185 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003187 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003189 } /* else system is the default value, so we can ignore it */
3190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003191 } else if (!strcmp(sub->name, "must")) {
3192 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003193 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003194 } else if (!strcmp(sub->name, "if-feature")) {
3195 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 } else if (!strcmp(sub->name, "min-elements")) {
3199 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003200 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003201 goto error;
3202 }
3203 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003204
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003205 GETVAL(value, sub, "value");
3206 while (isspace(value[0])) {
3207 value++;
3208 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 /* convert it to uint32_t */
3211 errno = 0;
3212 endptr = NULL;
3213 val = strtoul(value, &endptr, 10);
3214 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003215 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 goto error;
3217 }
3218 llist->min = (uint32_t) val;
3219 } else if (!strcmp(sub->name, "max-elements")) {
3220 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003221 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003222 goto error;
3223 }
3224 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003226 GETVAL(value, sub, "value");
3227 while (isspace(value[0])) {
3228 value++;
3229 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 /* convert it to uint32_t */
3232 errno = 0;
3233 endptr = NULL;
3234 val = strtoul(value, &endptr, 10);
3235 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003236 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 goto error;
3238 }
3239 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003240 } else if (!strcmp(sub->name, "when")) {
3241 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003242 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003243 goto error;
3244 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003245
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003246 llist->when = read_yin_when(module, sub);
3247 if (!llist->when) {
3248 goto error;
3249 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003250 if (unres_schema_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003251 goto error;
3252 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003254 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 lyxml_free_elem(module->ctx, sub);
3259 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003262 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003263 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003264 goto error;
3265 }
3266 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003267 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 goto error;
3269 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 /* middle part - process nodes with cardinality of 0..n */
3272 if (c_must) {
3273 llist->must = calloc(c_must, sizeof *llist->must);
3274 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003275 if (c_ftrs) {
3276 llist->features = calloc(c_ftrs, sizeof *llist->features);
3277 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003278
Radek Krejci73adb602015-07-02 18:07:40 +02003279 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003281 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003282 if (r) {
3283 goto error;
3284 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003285 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 +02003286 goto error;
3287 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003288 } else if (!strcmp(sub->name, "if-feature")) {
3289 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003290 if (unres_schema_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003291 LOGLINE(sub)) == -1) {
3292 goto error;
3293 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003294 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003295 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003296
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003298
3299error:
3300
Radek Krejci1d82ef62015-08-07 14:44:40 +02003301 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003302
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003303 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003304}
3305
Michal Vasko0d343d12015-08-24 14:57:36 +02003306/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003307static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003308read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3309 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003310{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003311 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003312 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003314 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003315 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003316 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003317 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 char *auxs;
3319 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 /* init */
3322 memset(&root, 0, sizeof root);
3323 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003326 list->nodetype = LYS_LIST;
3327 list->prev = (struct lys_node *)list;
3328 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003329
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003330 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3331 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003334
Radek Krejcia9544502015-08-14 08:24:29 +02003335 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003337 /* process list's specific children */
3338 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003339 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3340 /* garbage */
3341 lyxml_free_elem(module->ctx, sub);
3342 continue;
3343 }
3344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 /* data statements */
3346 if (!strcmp(sub->name, "container") ||
3347 !strcmp(sub->name, "leaf-list") ||
3348 !strcmp(sub->name, "leaf") ||
3349 !strcmp(sub->name, "list") ||
3350 !strcmp(sub->name, "choice") ||
3351 !strcmp(sub->name, "uses") ||
3352 !strcmp(sub->name, "grouping") ||
3353 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003354 lyxml_unlink_elem(module->ctx, sub, 1);
3355 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 /* array counters */
3358 } else if (!strcmp(sub->name, "key")) {
3359 /* check cardinality 0..1 */
3360 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003361 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003362 goto error;
3363 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003365 /* count the number of keys */
3366 GETVAL(value, sub, "value");
3367 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003368 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 while ((value = strpbrk(value, " \t\n"))) {
3370 list->keys_size++;
3371 while (isspace(*value)) {
3372 value++;
3373 }
3374 }
3375 list->keys_size++;
3376 list->keys = calloc(list->keys_size, sizeof *list->keys);
3377 } else if (!strcmp(sub->name, "unique")) {
3378 c_uniq++;
Michal Vaskof8879c22015-08-21 09:07:36 +02003379 lyxml_unlink_elem(module->ctx, sub, 1);
3380 lyxml_add_child(module->ctx, &uniq, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003381 } else if (!strcmp(sub->name, "typedef")) {
3382 c_tpdf++;
3383 } else if (!strcmp(sub->name, "must")) {
3384 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003385 } else if (!strcmp(sub->name, "if-feature")) {
3386 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003388 /* optional stetments */
3389 } else if (!strcmp(sub->name, "ordered-by")) {
3390 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003391 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003392 goto error;
3393 }
3394 /* just checking the flags in llist is not sufficient, we would
3395 * allow multiple ordered-by statements with the "system" value
3396 */
3397 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003398
Radek Krejci1574a8d2015-08-03 14:16:52 +02003399 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3401 * state data
3402 */
3403 lyxml_free_elem(module->ctx, sub);
3404 continue;
3405 }
Radek Krejci345ad742015-06-03 11:04:18 +02003406
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003407 GETVAL(value, sub, "value");
3408 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003409 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003410 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003411 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 goto error;
3413 }
3414 /* else system is the default value, so we can ignore it */
3415 lyxml_free_elem(module->ctx, sub);
3416 } else if (!strcmp(sub->name, "min-elements")) {
3417 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003418 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003419 goto error;
3420 }
3421 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003422
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003423 GETVAL(value, sub, "value");
3424 while (isspace(value[0])) {
3425 value++;
3426 }
Radek Krejci345ad742015-06-03 11:04:18 +02003427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 /* convert it to uint32_t */
3429 errno = 0;
3430 auxs = NULL;
3431 val = strtoul(value, &auxs, 10);
3432 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003433 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 goto error;
3435 }
3436 list->min = (uint32_t) val;
3437 lyxml_free_elem(module->ctx, sub);
3438 } else if (!strcmp(sub->name, "max-elements")) {
3439 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003440 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003441 goto error;
3442 }
3443 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003444
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 GETVAL(value, sub, "value");
3446 while (isspace(value[0])) {
3447 value++;
3448 }
Radek Krejci345ad742015-06-03 11:04:18 +02003449
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 /* convert it to uint32_t */
3451 errno = 0;
3452 auxs = NULL;
3453 val = strtoul(value, &auxs, 10);
3454 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003455 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
3458 list->max = (uint32_t) val;
3459 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003460 } else if (!strcmp(sub->name, "when")) {
3461 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003462 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003463 goto error;
3464 }
3465
3466 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003467 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003468 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003469 goto error;
3470 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003471 if (unres_schema_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003472 goto error;
3473 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003474 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003475 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003476 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003477 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003478 }
3479 }
Radek Krejci345ad742015-06-03 11:04:18 +02003480
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003481 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003482 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003483 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 goto error;
3485 }
3486 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003487 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 goto error;
3489 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003491 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3492 if (c_tpdf) {
3493 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3494 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003495 if (c_must) {
3496 list->must = calloc(c_must, sizeof *list->must);
3497 }
3498 if (c_ftrs) {
3499 list->features = calloc(c_ftrs, sizeof *list->features);
3500 }
Radek Krejci73adb602015-07-02 18:07:40 +02003501 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003503 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003504
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 if (r) {
3506 goto error;
3507 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003508 } else if (!strcmp(sub->name, "if-feature")) {
3509 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003510 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 +02003511 goto error;
3512 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003513 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003514 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003515 if (r) {
3516 goto error;
3517 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003518 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 +02003519 goto error;
3520 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 }
3522 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003523
Radek Krejci10c760e2015-08-14 14:45:43 +02003524 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003525 goto error;
3526 }
3527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 /* last part - process data nodes */
3529 LY_TREE_FOR_SAFE(root.child, next, sub) {
3530 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003531 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003533 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003535 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003536 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003537 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003538 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003539 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003541 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003543 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003544 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003545 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003546 } else {
3547 LOGINT;
3548 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003550 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003551 goto error;
3552 }
Radek Krejci73adb602015-07-02 18:07:40 +02003553
3554 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003557 if (!key_str) {
3558 /* config false list without a key */
3559 return retval;
3560 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003561 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003562 goto error;
3563 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003564
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 /* process unique statements */
3566 if (c_uniq) {
3567 list->unique = calloc(c_uniq, sizeof *list->unique);
3568 }
3569 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003570 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003571 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003572 GETVAL(value, sub, "tag");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003573 if (unres_schema_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003574 LOGLINE(sub)) == -1) {
3575 goto error;
3576 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003577
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003578 lyxml_free_elem(module->ctx, sub);
3579 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003581 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003582
3583error:
3584
Radek Krejci1d82ef62015-08-07 14:44:40 +02003585 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003586 while (root.child) {
3587 lyxml_free_elem(module->ctx, root.child);
3588 }
3589 while (uniq.child) {
3590 lyxml_free_elem(module->ctx, uniq.child);
3591 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003592
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003593 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003594}
3595
Michal Vasko0d343d12015-08-24 14:57:36 +02003596/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003597static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003598read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3599 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003600{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003602 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003603 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003604 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 const char *value;
3606 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003607 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003608
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 /* init */
3610 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003613 cont->nodetype = LYS_CONTAINER;
3614 cont->prev = (struct lys_node *)cont;
3615 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003616
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003617 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3618 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 goto error;
3620 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003621
Radek Krejcia9544502015-08-14 08:24:29 +02003622 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 /* process container's specific children */
3625 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003626 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003627 /* garbage */
3628 lyxml_free_elem(module->ctx, sub);
3629 continue;
3630 }
3631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 if (!strcmp(sub->name, "presence")) {
3633 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003634 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 goto error;
3636 }
3637 GETVAL(value, sub, "value");
3638 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003639
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003640 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003641 } else if (!strcmp(sub->name, "when")) {
3642 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003643 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003644 goto error;
3645 }
3646
3647 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003648 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003649 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003650 goto error;
3651 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003652 if (unres_schema_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003653 goto error;
3654 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003655 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 /* data statements */
3658 } else if (!strcmp(sub->name, "container") ||
3659 !strcmp(sub->name, "leaf-list") ||
3660 !strcmp(sub->name, "leaf") ||
3661 !strcmp(sub->name, "list") ||
3662 !strcmp(sub->name, "choice") ||
3663 !strcmp(sub->name, "uses") ||
3664 !strcmp(sub->name, "grouping") ||
3665 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003666 lyxml_unlink_elem(module->ctx, sub, 1);
3667 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003668
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 /* array counters */
3670 } else if (!strcmp(sub->name, "typedef")) {
3671 c_tpdf++;
3672 } else if (!strcmp(sub->name, "must")) {
3673 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003674 } else if (!strcmp(sub->name, "if-feature")) {
3675 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003677 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003678 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 }
3680 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3683 if (c_tpdf) {
3684 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3685 }
3686 if (c_must) {
3687 cont->must = calloc(c_must, sizeof *cont->must);
3688 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003689 if (c_ftrs) {
3690 cont->features = calloc(c_ftrs, sizeof *cont->features);
3691 }
Radek Krejci800af702015-06-02 13:46:01 +02003692
Radek Krejci73adb602015-07-02 18:07:40 +02003693 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003695 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 if (r) {
3697 goto error;
3698 }
3699 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003700 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 if (r) {
3702 goto error;
3703 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02003704 if (unres_schema_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003705 LOGLINE(sub)) == -1) {
3706 goto error;
3707 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003708 } else if (!strcmp(sub->name, "if-feature")) {
3709 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02003710 if (unres_schema_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003711 LOGLINE(sub)) == -1) {
3712 goto error;
3713 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003715 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003716
Radek Krejci10c760e2015-08-14 14:45:43 +02003717 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003718 goto error;
3719 }
3720
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 /* last part - process data nodes */
3722 LY_TREE_FOR_SAFE(root.child, next, sub) {
3723 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003724 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003726 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003728 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003730 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003731 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003732 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003733 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003734 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003735 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003736 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003737 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003738 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003740 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 goto error;
3742 }
Radek Krejci73adb602015-07-02 18:07:40 +02003743
3744 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003745 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003746
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003747 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003748
3749error:
3750
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 while (root.child) {
3753 lyxml_free_elem(module->ctx, root.child);
3754 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757}
3758
Michal Vasko0d343d12015-08-24 14:57:36 +02003759/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003760static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003761read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003762 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003765 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003766 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003767 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003768 int r;
3769 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 /* init */
3772 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003775 grp->nodetype = LYS_GROUPING;
3776 grp->prev = (struct lys_node *)grp;
3777 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003778
Michal Vasko71e1aa82015-08-12 12:17:51 +02003779 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 goto error;
3781 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003782
Radek Krejcia9544502015-08-14 08:24:29 +02003783 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3784
Radek Krejci1d82ef62015-08-07 14:44:40 +02003785 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003786 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3787 /* garbage */
3788 lyxml_free_elem(module->ctx, sub);
3789 continue;
3790 }
3791
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003792 /* data statements */
3793 if (!strcmp(sub->name, "container") ||
3794 !strcmp(sub->name, "leaf-list") ||
3795 !strcmp(sub->name, "leaf") ||
3796 !strcmp(sub->name, "list") ||
3797 !strcmp(sub->name, "choice") ||
3798 !strcmp(sub->name, "uses") ||
3799 !strcmp(sub->name, "grouping") ||
3800 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003801 lyxml_unlink_elem(module->ctx, sub, 1);
3802 lyxml_add_child(module->ctx, &root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003804 /* array counters */
3805 } else if (!strcmp(sub->name, "typedef")) {
3806 c_tpdf++;
3807 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003808 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 goto error;
3810 }
3811 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003813 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3814 if (c_tpdf) {
3815 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3816 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003817 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003818 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003819
Radek Krejci73adb602015-07-02 18:07:40 +02003820 if (r) {
3821 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003822 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003823 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003824
Radek Krejci10c760e2015-08-14 14:45:43 +02003825 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003826 goto error;
3827 }
3828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003829 /* last part - process data nodes */
3830 LY_TREE_FOR_SAFE(root.child, next, sub) {
3831 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003832 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003833 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003834 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003835 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003837 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003838 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003839 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003841 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003843 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003844 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003846 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003847 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003848 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 goto error;
3850 }
Radek Krejci73adb602015-07-02 18:07:40 +02003851
3852 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003853 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003856
3857error:
3858
Radek Krejci1d82ef62015-08-07 14:44:40 +02003859 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003860 while (root.child) {
3861 lyxml_free_elem(module->ctx, root.child);
3862 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003864 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003865}
3866
Michal Vasko0d343d12015-08-24 14:57:36 +02003867/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003868static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003869read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3870 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003871{
Radek Krejcie0674f82015-06-15 13:58:51 +02003872 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003873 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003874 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003875 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003876 int r;
3877 int c_tpdf = 0;
3878
Radek Krejcie0674f82015-06-15 13:58:51 +02003879 /* init */
3880 memset(&root, 0, sizeof root);
3881
Michal Vasko38d01f72015-06-15 09:41:06 +02003882 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003883 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003884
3885 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003886 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003887 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003888 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003889 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003890 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003891 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003892 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003893 }
3894
Radek Krejci76512572015-08-04 09:47:08 +02003895 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003896
Radek Krejci6a113852015-07-03 16:04:20 +02003897 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003898 goto error;
3899 }
3900
Radek Krejcia9544502015-08-14 08:24:29 +02003901 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3902
Michal Vasko38d01f72015-06-15 09:41:06 +02003903 /* data statements */
3904 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003905 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3906 /* garbage */
3907 lyxml_free_elem(module->ctx, sub);
3908 continue;
3909 }
3910
Michal Vasko38d01f72015-06-15 09:41:06 +02003911 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003912 !strcmp(sub->name, "leaf-list") ||
3913 !strcmp(sub->name, "leaf") ||
3914 !strcmp(sub->name, "list") ||
3915 !strcmp(sub->name, "choice") ||
3916 !strcmp(sub->name, "uses") ||
3917 !strcmp(sub->name, "grouping") ||
3918 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02003919 lyxml_unlink_elem(module->ctx, sub, 1);
3920 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003921
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003923 } else if (!strcmp(sub->name, "typedef")) {
3924 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003925
Michal Vasko38d01f72015-06-15 09:41:06 +02003926 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003927 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003928 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003929 }
3930 }
3931
3932 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3933 if (c_tpdf) {
3934 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3935 }
3936
Radek Krejci73adb602015-07-02 18:07:40 +02003937 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003938 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003939
Radek Krejci73adb602015-07-02 18:07:40 +02003940 if (r) {
3941 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003942 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003943 }
3944
Radek Krejci10c760e2015-08-14 14:45:43 +02003945 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003946 goto error;
3947 }
3948
Michal Vasko38d01f72015-06-15 09:41:06 +02003949 /* last part - process data nodes */
3950 LY_TREE_FOR_SAFE(root.child, next, sub) {
3951 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003952 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003953 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003954 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003955 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003956 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003957 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003958 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003959 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003961 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003962 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003963 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003964 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003965 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003966 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003967 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003968 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003969 goto error;
3970 }
Radek Krejci73adb602015-07-02 18:07:40 +02003971
3972 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003973 }
3974
Michal Vasko38d01f72015-06-15 09:41:06 +02003975 return retval;
3976
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003977error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003978
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003980 while (root.child) {
3981 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003982 }
3983
3984 return NULL;
3985}
3986
Michal Vasko0d343d12015-08-24 14:57:36 +02003987/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02003988static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003989read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3990 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003991{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003992 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003993 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003994 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003995 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003996 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003997 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003998 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003999
Michal Vaskoc6551b32015-06-16 10:51:43 +02004000 memset(&root, 0, sizeof root);
4001
Michal Vasko0ea41032015-06-16 08:53:55 +02004002 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004003 notif->nodetype = LYS_NOTIF;
4004 notif->prev = (struct lys_node *)notif;
4005 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004006
Radek Krejci6a113852015-07-03 16:04:20 +02004007 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004008 goto error;
4009 }
4010
Radek Krejcia9544502015-08-14 08:24:29 +02004011 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4012
Michal Vasko0ea41032015-06-16 08:53:55 +02004013 /* process rpc's specific children */
4014 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004015 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4016 /* garbage */
4017 lyxml_free_elem(module->ctx, sub);
4018 continue;
4019 }
4020
Michal Vasko0ea41032015-06-16 08:53:55 +02004021 /* data statements */
4022 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004023 !strcmp(sub->name, "leaf-list") ||
4024 !strcmp(sub->name, "leaf") ||
4025 !strcmp(sub->name, "list") ||
4026 !strcmp(sub->name, "choice") ||
4027 !strcmp(sub->name, "uses") ||
4028 !strcmp(sub->name, "grouping") ||
4029 !strcmp(sub->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004030 lyxml_unlink_elem(module->ctx, sub, 1);
4031 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004032
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004033 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004034 } else if (!strcmp(sub->name, "typedef")) {
4035 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004036 } else if (!strcmp(sub->name, "if-feature")) {
4037 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004038 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004039 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004040 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004041 }
4042 }
4043
4044 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4045 if (c_tpdf) {
4046 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4047 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004048 if (c_ftrs) {
4049 notif->features = calloc(c_ftrs, sizeof *notif->features);
4050 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004051
Radek Krejci73adb602015-07-02 18:07:40 +02004052 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004053 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004054 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004055
4056 if (r) {
4057 goto error;
4058 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004059 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004060 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004061 if (unres_schema_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004062 LOGLINE(sub)) == -1) {
4063 goto error;
4064 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004065 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004066 }
4067
Radek Krejci10c760e2015-08-14 14:45:43 +02004068 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004069 goto error;
4070 }
4071
Michal Vasko0ea41032015-06-16 08:53:55 +02004072 /* last part - process data nodes */
4073 LY_TREE_FOR_SAFE(root.child, next, sub) {
4074 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004075 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004076 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004077 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004078 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004079 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004080 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004081 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004082 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004084 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004086 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004087 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004088 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004089 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004090 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004091 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004092 goto error;
4093 }
Radek Krejci73adb602015-07-02 18:07:40 +02004094
4095 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004096 }
4097
Michal Vasko0ea41032015-06-16 08:53:55 +02004098 return retval;
4099
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004100error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004101
Radek Krejci1d82ef62015-08-07 14:44:40 +02004102 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004103 while (root.child) {
4104 lyxml_free_elem(module->ctx, root.child);
4105 }
4106
4107 return NULL;
4108}
4109
Michal Vasko0d343d12015-08-24 14:57:36 +02004110/* logs directly */
Radek Krejci76512572015-08-04 09:47:08 +02004111static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004112read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4113 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004114{
Radek Krejcie0674f82015-06-15 13:58:51 +02004115 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004116 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004117 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004118 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004119 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004120 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004121 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004122
Radek Krejcie0674f82015-06-15 13:58:51 +02004123 /* init */
4124 memset(&root, 0, sizeof root);
4125
Michal Vasko38d01f72015-06-15 09:41:06 +02004126 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004127 rpc->nodetype = LYS_RPC;
4128 rpc->prev = (struct lys_node *)rpc;
4129 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004130
Radek Krejci6a113852015-07-03 16:04:20 +02004131 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004132 goto error;
4133 }
4134
Radek Krejcia9544502015-08-14 08:24:29 +02004135 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4136
Michal Vasko38d01f72015-06-15 09:41:06 +02004137 /* process rpc's specific children */
4138 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004139 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4140 /* garbage */
4141 lyxml_free_elem(module->ctx, sub);
4142 continue;
4143 }
4144
Michal Vasko38d01f72015-06-15 09:41:06 +02004145 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004146 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004147 && (rpc->child->nodetype == LYS_INPUT
4148 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004149 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004150 goto error;
4151 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004152 lyxml_unlink_elem(module->ctx, sub, 1);
4153 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004154 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004155 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004156 && (rpc->child->nodetype == LYS_INPUT
4157 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004158 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004159 goto error;
4160 }
Michal Vaskof8879c22015-08-21 09:07:36 +02004161 lyxml_unlink_elem(module->ctx, sub, 1);
4162 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004164 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 } else if (!strcmp(sub->name, "grouping")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004166 lyxml_unlink_elem(module->ctx, sub, 1);
4167 lyxml_add_child(module->ctx, &root, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004169 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004170 } else if (!strcmp(sub->name, "typedef")) {
4171 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004172 } else if (!strcmp(sub->name, "if-feature")) {
4173 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004174 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004175 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004176 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004177 }
4178 }
4179
4180 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4181 if (c_tpdf) {
4182 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4183 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004184 if (c_ftrs) {
4185 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4186 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004187
Radek Krejci73adb602015-07-02 18:07:40 +02004188 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004189 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004190 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004191
4192 if (r) {
4193 goto error;
4194 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004195 } else if (!strcmp(sub->name, "if-feature")) {
4196 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004197 if (unres_schema_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004198 LOGLINE(sub)) == -1) {
4199 goto error;
4200 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004201 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004202 }
4203
Radek Krejci10c760e2015-08-14 14:45:43 +02004204 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004205 goto error;
4206 }
4207
Michal Vasko38d01f72015-06-15 09:41:06 +02004208 /* last part - process data nodes */
4209 LY_TREE_FOR_SAFE(root.child, next, sub) {
4210 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004211 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004212 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004213 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004214 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004215 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004216 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004218 goto error;
4219 }
Radek Krejci73adb602015-07-02 18:07:40 +02004220
4221 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004222 }
4223
Michal Vasko38d01f72015-06-15 09:41:06 +02004224 return retval;
4225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004226error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004227
Radek Krejci1d82ef62015-08-07 14:44:40 +02004228 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004229 while (root.child) {
4230 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004231 }
4232
4233 return NULL;
4234}
4235
Michal Vasko0d343d12015-08-24 14:57:36 +02004236/* logs directly
4237 *
Radek Krejci74705112015-06-05 10:25:44 +02004238 * resolve - referenced grouping should be bounded to the namespace (resolved)
4239 * only when uses does not appear in grouping. In a case of grouping's uses,
4240 * we just get information but we do not apply augment or refine to it.
4241 */
Radek Krejci76512572015-08-04 09:47:08 +02004242static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004243read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004244 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004245{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004246 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004247 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004248 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004249 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004250 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004251 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004253 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004254 uses->nodetype = LYS_USES;
4255 uses->prev = (struct lys_node *)uses;
4256 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004257
Radek Krejcia9544502015-08-14 08:24:29 +02004258 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004259 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004260
Radek Krejcia9544502015-08-14 08:24:29 +02004261 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004262 goto error;
4263 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004264
Radek Krejcia9544502015-08-14 08:24:29 +02004265 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4266
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004268 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004269 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4270 /* garbage */
4271 lyxml_free_elem(module->ctx, sub);
4272 continue;
4273 }
4274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004275 if (!strcmp(sub->name, "refine")) {
4276 c_ref++;
4277 } else if (!strcmp(sub->name, "augment")) {
4278 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004279 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004280 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004281 } else if (!strcmp(sub->name, "when")) {
4282 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004283 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004284 goto error;
4285 }
4286
4287 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004288 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004289 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004290 goto error;
4291 }
Michal Vasko0bd29d12015-08-19 11:45:49 +02004292 if (unres_schema_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004293 goto error;
4294 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004295 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004296 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004297 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004299 }
4300 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004302 /* process properties with cardinality 0..n */
4303 if (c_ref) {
4304 uses->refine = calloc(c_ref, sizeof *uses->refine);
4305 }
4306 if (c_aug) {
4307 uses->augment = calloc(c_aug, sizeof *uses->augment);
4308 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004309 if (c_ftrs) {
4310 uses->features = calloc(c_ftrs, sizeof *uses->features);
4311 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004312
Radek Krejci10c760e2015-08-14 14:45:43 +02004313 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004314 goto error;
4315 }
4316
Radek Krejcia9544502015-08-14 08:24:29 +02004317 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004319 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4320 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004321 goto error;
4322 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004323 } else if (!strcmp(sub->name, "augment")) {
4324 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4325 if (r) {
4326 goto error;
4327 }
4328 } else if (!strcmp(sub->name, "if-feature")) {
4329 GETVAL(value, sub, "name");
Michal Vasko0bd29d12015-08-19 11:45:49 +02004330 if (unres_schema_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004331 LOGLINE(sub)) == -1) {
4332 goto error;
4333 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004334 }
4335 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004336
Michal Vasko0bd29d12015-08-19 11:45:49 +02004337 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004338 goto error;
4339 }
Radek Krejci74705112015-06-05 10:25:44 +02004340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 if (resolve) {
4342 /* inherit config flag */
4343 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004344 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004345 } else {
4346 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004347 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 }
4349 }
Radek Krejcib388c152015-06-04 17:03:03 +02004350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004352
4353error:
4354
Radek Krejci1d82ef62015-08-07 14:44:40 +02004355 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004356
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004358}
4359
Michal Vasko0d343d12015-08-24 14:57:36 +02004360/* logs directly
4361 *
4362 * common code for yin_read_module() and yin_read_submodule()
4363 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004365read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004366{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004368 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004369 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4370 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004372 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004374 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004375 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 +02004376
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004377 /* init */
4378 memset(&root, 0, sizeof root);
4379 memset(&grps, 0, sizeof grps);
4380 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004381 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383 /*
4384 * in the first run, we process elements with cardinality of 1 or 0..1 and
4385 * count elements with cardinality 0..n. Data elements (choices, containers,
4386 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4387 * need have all top-level and groupings already prepared at that time. In
4388 * the middle loop, we process other elements with carinality of 0..n since
4389 * we need to allocate arrays to store them.
4390 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004391 LY_TREE_FOR_SAFE(yin->child, next, child) {
4392 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004393 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004394 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004395 continue;
4396 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004397
Radek Krejci1d82ef62015-08-07 14:44:40 +02004398 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004399 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004400 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004401 goto error;
4402 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004403 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004405 lyxml_free_elem(ctx, child);
4406 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004408 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 goto error;
4410 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004411 GETVAL(value, child, "value");
4412 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 goto error;
4414 }
4415 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004416 lyxml_free_elem(ctx, child);
4417 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004418 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004419 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004420 goto error;
4421 }
4422 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004423 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004424 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004425 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 }
4427 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004428 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004429 goto error;
4430 }
Radek Krejcif3886932015-06-04 17:36:06 +02004431
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004433 if (!child->child) {
4434 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004436 } else if (strcmp(child->child->name, "prefix")) {
4437 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004439 } else if (child->child->next) {
4440 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 goto error;
4442 }
4443 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004444 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004445 /* check here differs from a generic prefix check, since this prefix
4446 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004447 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004448 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004449 goto error;
4450 }
4451 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004453 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004454 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004455
4456 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004457 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004459 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004461 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004462 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004463 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004465 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004467 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004468 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004469 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004470 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004471 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004472 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004475 } else if (!strcmp(child->name, "container") ||
4476 !strcmp(child->name, "leaf-list") ||
4477 !strcmp(child->name, "leaf") ||
4478 !strcmp(child->name, "list") ||
4479 !strcmp(child->name, "choice") ||
4480 !strcmp(child->name, "uses") ||
4481 !strcmp(child->name, "anyxml")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004482 lyxml_unlink_elem(module->ctx, child, 1);
4483 lyxml_add_child(module->ctx, &root, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004484 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004485 /* keep groupings separated and process them before other data statements */
Michal Vaskof8879c22015-08-21 09:07:36 +02004486 lyxml_unlink_elem(module->ctx, child, 1);
4487 lyxml_add_child(module->ctx, &grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004490 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004492 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 goto error;
4494 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004495 module->dsc = read_yin_subnode(ctx, child, "text");
4496 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 if (!module->dsc) {
4498 goto error;
4499 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004500 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004501 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004502 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004503 goto error;
4504 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004505 module->ref = read_yin_subnode(ctx, child, "text");
4506 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 if (!module->ref) {
4508 goto error;
4509 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004510 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004512 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 goto error;
4514 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004515 module->org = read_yin_subnode(ctx, child, "text");
4516 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004517 if (!module->org) {
4518 goto error;
4519 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004520 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004521 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004522 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004523 goto error;
4524 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004525 module->contact = read_yin_subnode(ctx, child, "text");
4526 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 if (!module->contact) {
4528 goto error;
4529 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004530 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 /* TODO: support YANG 1.1 ? */
4532 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004533 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004534 goto error;
4535 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004536 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004537 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004538 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004539 goto error;
4540 }
4541 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004542 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004545 } else if (!strcmp(child->name, "rpc")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004546 lyxml_unlink_elem(module->ctx, child, 1);
4547 lyxml_add_child(module->ctx, &rpcs, child);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004548 } else if (!strcmp(child->name, "notification")) {
Michal Vaskof8879c22015-08-21 09:07:36 +02004549 lyxml_unlink_elem(module->ctx, child, 1);
4550 lyxml_add_child(module->ctx, &notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004551
Radek Krejci1d82ef62015-08-07 14:44:40 +02004552 } else if (!strcmp(child->name, "extension")) {
4553 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004554
Radek Krejci6764bb32015-07-03 15:16:04 +02004555 /* we have 2 supported (hardcoded) extensions:
4556 * NACM's default-deny-write and default-deny-all
4557 */
4558 if (strcmp(module->ns, LY_NSNACM) ||
4559 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4560 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004561 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004562 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004564 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004565 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004566 }
4567 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 if (!submodule) {
4570 /* check for mandatory statements */
4571 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004572 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004573 goto error;
4574 }
4575 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004576 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 goto error;
4578 }
4579 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004580
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 /* allocate arrays for elements with cardinality of 0..n */
4582 if (c_imp) {
4583 module->imp = calloc(c_imp, sizeof *module->imp);
4584 }
4585 if (c_rev) {
4586 module->rev = calloc(c_rev, sizeof *module->rev);
4587 }
4588 if (c_tpdf) {
4589 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4590 }
4591 if (c_ident) {
4592 module->ident = calloc(c_ident, sizeof *module->ident);
4593 }
4594 if (c_inc) {
4595 module->inc = calloc(c_inc, sizeof *module->inc);
4596 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004597 if (c_aug) {
4598 module->augment = calloc(c_aug, sizeof *module->augment);
4599 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004600 if (c_ftrs) {
4601 module->features = calloc(c_ftrs, sizeof *module->features);
4602 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004603 if (c_dev) {
4604 module->deviation = calloc(c_dev, sizeof *module->deviation);
4605 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004607 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 LY_TREE_FOR(yin->child, child) {
4609 if (!strcmp(child->name, "import")) {
4610 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004611 module->imp_size++;
4612 if (r) {
4613 goto error;
4614 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004615
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004616 /* check duplicities in imported modules */
4617 for (i = 0; i < module->imp_size - 1; i++) {
4618 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 goto error;
4621 }
4622 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004623 } else if (!strcmp(child->name, "include")) {
4624 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004625 module->inc_size++;
4626 if (r) {
4627 goto error;
4628 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004629
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 /* check duplications in include submodules */
4631 for (i = 0; i < module->inc_size - 1; i++) {
4632 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 module->inc[i].submodule->name);
4635 goto error;
4636 }
4637 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004638 } else if (!strcmp(child->name, "revision")) {
4639 GETVAL(value, child, "date");
4640 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004641 goto error;
4642 }
4643 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4644 /* check uniqueness of the revision date - not required by RFC */
4645 for (i = 0; i < module->rev_size; i++) {
4646 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004647 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004648 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004649 }
4650 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004651
Radek Krejci1d82ef62015-08-07 14:44:40 +02004652 LY_TREE_FOR(child->child, child2) {
4653 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004654 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004655 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 goto error;
4657 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004658 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 if (!module->rev[module->rev_size].dsc) {
4660 goto error;
4661 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004662 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004663 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004664 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004665 goto error;
4666 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004667 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004668 if (!module->rev[module->rev_size].ref) {
4669 goto error;
4670 }
4671 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004672 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004673 goto error;
4674 }
4675 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004676
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004677 /* keep the latest revision at position 0 */
4678 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4679 /* switch their position */
4680 value = strdup(module->rev[0].date);
4681 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4682 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4683 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004684
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4686 value = module->rev[0].dsc;
4687 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4688 module->rev[module->rev_size].dsc = value;
4689 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4692 value = module->rev[0].ref;
4693 module->rev[0].ref = module->rev[module->rev_size].ref;
4694 module->rev[module->rev_size].ref = value;
4695 }
4696 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004698 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004699 } else if (!strcmp(child->name, "typedef")) {
4700 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004701 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004703 if (r) {
4704 goto error;
4705 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004706 } else if (!strcmp(child->name, "identity")) {
4707 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004708 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 if (r) {
4711 goto error;
4712 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004713 } else if (!strcmp(child->name, "feature")) {
4714 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004715 module->features_size++;
4716
4717 if (r) {
4718 goto error;
4719 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004720 } else if (!strcmp(child->name, "augment")) {
4721 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004722 module->augment_size++;
4723
4724 if (r) {
4725 goto error;
4726 }
4727
4728 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4729 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004730 } else if (!strcmp(child->name, "deviation")) {
4731 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004732 module->deviation_size++;
4733
4734 if (r) {
4735 goto error;
4736 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004737 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004738 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004739
Radek Krejcif5be10f2015-06-16 13:29:36 +02004740 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004741 * refer to them
4742 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004743 LY_TREE_FOR_SAFE(grps.child, next, child) {
4744 node = read_yin_grouping(module, NULL, child, 0, unres);
4745 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 goto error;
4747 }
Radek Krejci74705112015-06-05 10:25:44 +02004748
Radek Krejci1d82ef62015-08-07 14:44:40 +02004749 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 }
Radek Krejci74705112015-06-05 10:25:44 +02004751
Radek Krejcif5be10f2015-06-16 13:29:36 +02004752 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004753 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004754
Radek Krejci1d82ef62015-08-07 14:44:40 +02004755 if (!strcmp(child->name, "container")) {
4756 node = read_yin_container(module, NULL, child, 1, unres);
4757 } else if (!strcmp(child->name, "leaf-list")) {
4758 node = read_yin_leaflist(module, NULL, child, 1, unres);
4759 } else if (!strcmp(child->name, "leaf")) {
4760 node = read_yin_leaf(module, NULL, child, 1, unres);
4761 } else if (!strcmp(child->name, "list")) {
4762 node = read_yin_list(module, NULL, child, 1, unres);
4763 } else if (!strcmp(child->name, "choice")) {
4764 node = read_yin_choice(module, NULL, child, 1, unres);
4765 } else if (!strcmp(child->name, "uses")) {
4766 node = read_yin_uses(module, NULL, child, 1, unres);
4767 } else if (!strcmp(child->name, "anyxml")) {
4768 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004769 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004770 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004771 goto error;
4772 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004773
Radek Krejci1d82ef62015-08-07 14:44:40 +02004774 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004775 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004776
4777 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004778 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4779 node = read_yin_rpc(module, NULL, child, 0, unres);
4780 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004781 goto error;
4782 }
4783
Radek Krejci1d82ef62015-08-07 14:44:40 +02004784 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004785 }
4786
4787 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004788 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4789 node = read_yin_notif(module, NULL, child, 0, unres);
4790 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004791 goto error;
4792 }
4793
Radek Krejci1d82ef62015-08-07 14:44:40 +02004794 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004795 }
4796
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004798
4799error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004800 /* cleanup */
4801 while (root.child) {
4802 lyxml_free_elem(module->ctx, root.child);
4803 }
4804 while (grps.child) {
4805 lyxml_free_elem(module->ctx, grps.child);
4806 }
4807 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004808 lyxml_free_elem(module->ctx, rpcs.child);
4809 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004810
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004811 free(unres->item);
4812 unres->item = NULL;
4813 free(unres->type);
4814 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004815 free(unres->str_snode);
4816 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004817#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004818 free(unres->line);
4819 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004820#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004821 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004822
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004824}
4825
Michal Vasko0d343d12015-08-24 14:57:36 +02004826/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004827struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004828yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004829{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004830 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004831 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004832 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004835
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 yin = lyxml_read(module->ctx, data, 0);
4837 if (!yin) {
4838 return NULL;
4839 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004841 /* check root element */
4842 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004843 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004844 goto error;
4845 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004847 GETVAL(value, yin, "name");
4848 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4849 goto error;
4850 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004851
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004852 submodule = calloc(1, sizeof *submodule);
4853 if (!submodule) {
4854 LOGMEM;
4855 goto error;
4856 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004857
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004858 submodule->ctx = module->ctx;
4859 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4860 submodule->type = 1;
4861 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004862 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004863
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004865 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004866 goto error;
4867 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004868
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 /* cleanup */
4870 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004871
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004872 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004874 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004875
4876error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004877 /* cleanup */
4878 lyxml_free_elem(module->ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004879 lys_submodule_free(submodule, 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004880
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004881 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004882}
4883
Michal Vasko0d343d12015-08-24 14:57:36 +02004884/* logs directly */
Radek Krejcib8048692015-08-05 13:36:34 +02004885struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004886yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004887{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004888 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004889 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004890 const char *value;
4891 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004892
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004893 yin = lyxml_read(ctx, data, 0);
4894 if (!yin) {
4895 return NULL;
4896 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004897
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004898 /* check root element */
4899 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004900 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 goto error;
4902 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004904 GETVAL(value, yin, "name");
4905 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4906 goto error;
4907 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004909 module = calloc(1, sizeof *module);
4910 if (!module) {
4911 LOGMEM;
4912 goto error;
4913 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004915 module->ctx = ctx;
4916 module->name = lydict_insert(ctx, value, strlen(value));
4917 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004918 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004921 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004922 goto error;
4923 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004925 /* add to the context's list of modules */
4926 if (ctx->models.used == ctx->models.size) {
4927 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4928 if (!newlist) {
4929 LOGMEM;
4930 goto error;
4931 }
4932 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4933 newlist[i] = NULL;
4934 }
4935 ctx->models.size *= 2;
4936 ctx->models.list = newlist;
4937 }
4938 for (i = 0; ctx->models.list[i]; i++) {
4939 /* check name (name/revision) and namespace uniqueness */
4940 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004941 if (ctx->models.list[i]->rev_size == module->rev_size) {
4942 /* both have the same number of revisions */
4943 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4944 /* both have the same revision -> we already have the same module */
4945 /* so free the new one and update the old one's implement flag if needed */
4946 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004947 lys_free(module, 0);
Michal Vaskoaa211572015-08-13 13:55:39 +02004948 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004949
4950 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4951
4952 if (implement && !ctx->models.list[i]->implemented) {
4953 lyp_set_implemented(ctx->models.list[i]);
4954 }
4955 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004956 }
4957 }
Radek Krejcif647e612015-07-30 11:36:07 +02004958 /* else (both elses) keep searching, for now the caller is just adding
4959 * another revision of an already present schema
4960 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004961 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4962 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4963 ctx->models.list[i]->name, module->name, module->ns);
4964 goto error;
4965 }
4966 }
4967 ctx->models.list[i] = module;
4968 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004969 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004970
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004971 /* cleanup */
4972 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004974 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004975
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004976 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004977
4978error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004979 /* cleanup */
4980 lyxml_free_elem(ctx, yin);
Michal Vasko13b15832015-08-19 11:04:48 +02004981 lys_free(module, 0);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004982
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004983 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004984}