blob: 7e3288b67a6301f011beee2bd6ab9911029bbccb [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>
31#include <regex.h>
Radek Krejcida04f4a2015-05-21 12:54:09 +020032
Radek Krejciefdd0ce2015-05-26 16:48:29 +020033#include "../libyang.h"
34#include "../common.h"
35#include "../context.h"
36#include "../dict.h"
37#include "../parser.h"
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020038#include "../parse.h"
39#include "../resolve.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020040#include "../tree_internal.h"
41#include "../xml.h"
42
Radek Krejcice7fb782015-05-29 16:52:34 +020043enum LY_IDENT {
Radek Krejci994b6f62015-06-18 16:47:27 +020044 LY_IDENT_SIMPLE, /* only syntax rules */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020045 LY_IDENT_FEATURE,
46 LY_IDENT_IDENTITY,
47 LY_IDENT_TYPE,
48 LY_IDENT_NODE,
Radek Krejci994b6f62015-06-18 16:47:27 +020049 LY_IDENT_NAME, /* uniqueness across the siblings */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020050 LY_IDENT_PREFIX
Radek Krejcice7fb782015-05-29 16:52:34 +020051};
52
Radek Krejciefdd0ce2015-05-26 16:48:29 +020053#define LY_NSYIN "urn:ietf:params:xml:ns:yang:yin:1"
Radek Krejci6764bb32015-07-03 15:16:04 +020054#define LY_NSNACM "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
Radek Krejcida04f4a2015-05-21 12:54:09 +020055
Radek Krejcice7fb782015-05-29 16:52:34 +020056#define GETVAL(value, node, arg) \
57 value = lyxml_get_attr(node, arg, NULL); \
58 if (!value) { \
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020059 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
Radek Krejcice7fb782015-05-29 16:52:34 +020060 goto error; \
61 }
62
Radek Krejcib388c152015-06-04 17:03:03 +020063#define OPT_IDENT 0x01
64#define OPT_CONFIG 0x02
65#define OPT_MODULE 0x04
66#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020067#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020068static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020069
Radek Krejcib8048692015-08-05 13:36:34 +020070static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020071 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020072static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020073 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020074static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020075 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020076static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020077 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020078static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020079 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020080static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020081 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020082static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020083 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020084static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *node,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020085 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020086static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *node,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +020087 int resolve, struct unres_item *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020088static struct lys_when *read_yin_when(struct lys_module *module,struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020089
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
Radek Krejcib05774c2015-06-18 13:52:59 +0200105static int
Radek Krejcib8048692015-08-05 13:36:34 +0200106dup_feature_check(const char *id, struct lys_module *module)
Radek Krejcib05774c2015-06-18 13:52:59 +0200107{
108 int i;
109
110 for (i = 0; i < module->features_size; i++) {
111 if (!strcmp(id, module->features[i].name)) {
112 return EXIT_FAILURE;
113 }
114 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200115
116 return EXIT_SUCCESS;
Radek Krejcib05774c2015-06-18 13:52:59 +0200117}
118
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200119static int
Radek Krejcib8048692015-08-05 13:36:34 +0200120dup_prefix_check(const char *prefix, struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200121{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200122 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200124 if (!module->type && module->prefix && !strcmp(module->prefix, prefix)) {
125 return EXIT_FAILURE;
126 }
127 for (i = 0; i < module->imp_size; i++) {
128 if (!strcmp(module->imp[i].prefix, prefix)) {
129 return EXIT_FAILURE;
130 }
131 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200133 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200134}
135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200136static int
137check_identifier(const char *id, enum LY_IDENT type, unsigned int line,
Radek Krejcib8048692015-08-05 13:36:34 +0200138 struct lys_module *module, struct lys_node *parent)
Radek Krejcice7fb782015-05-29 16:52:34 +0200139{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200140 int i;
141 int size;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200142 struct lys_tpdf *tpdf;
Radek Krejci76512572015-08-04 09:47:08 +0200143 struct lys_node *mnode;
Radek Krejcice7fb782015-05-29 16:52:34 +0200144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200145 assert(id);
Radek Krejcice7fb782015-05-29 16:52:34 +0200146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200147 /* check id syntax */
148 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200149 LOGVAL(LYE_INID, line, id, "invalid start character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200150 return EXIT_FAILURE;
151 }
152 for (i = 1; id[i]; i++) {
153 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
154 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200155 LOGVAL(LYE_INID, line, id, "invalid character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200156 return EXIT_FAILURE;
157 }
158 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200159
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200160 if (i > 64) {
161 LOGWRN("Identifier \"%s\" is long, you should use something shorter.", id);
162 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200164 switch (type) {
165 case LY_IDENT_NAME:
166 /* check uniqueness of the node within its siblings */
167 if (!parent) {
168 break;
169 }
Radek Krejcib4cf2022015-06-03 14:40:05 +0200170
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200171 LY_TREE_FOR(parent->child, mnode) {
172 if (mnode->name == id) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200173 LOGVAL(LYE_INID, line, id, "name duplication");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200174 return EXIT_FAILURE;
175 }
176 }
177 break;
178 case LY_IDENT_TYPE:
179 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200180
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200181 /* check collision with the built-in types */
182 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
183 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
184 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
185 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
186 !strcmp(id, "int8") || !strcmp(id, "int16") ||
187 !strcmp(id, "int32") || !strcmp(id, "int64") ||
188 !strcmp(id, "leafref") || !strcmp(id, "string") ||
189 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
190 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200191 LOGVAL(LYE_SPEC, line, "Typedef name duplicates built-in type.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200192 return EXIT_FAILURE;
193 }
Radek Krejcieac35532015-05-31 19:09:15 +0200194
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200195 /* check locally scoped typedefs (avoid name shadowing) */
196 for (; parent; parent = parent->parent) {
197 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200198 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +0200199 size = ((struct lys_node_container *)parent)->tpdf_size;
200 tpdf = ((struct lys_node_container *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200201 break;
Radek Krejci76512572015-08-04 09:47:08 +0200202 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +0200203 size = ((struct lys_node_list *)parent)->tpdf_size;
204 tpdf = ((struct lys_node_list *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200205 break;
Radek Krejci76512572015-08-04 09:47:08 +0200206 case LYS_GROUPING:
Radek Krejcib8048692015-08-05 13:36:34 +0200207 size = ((struct lys_node_grp *)parent)->tpdf_size;
208 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200209 break;
210 default:
211 continue;
212 }
Radek Krejcieac35532015-05-31 19:09:15 +0200213
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200214 if (dup_typedef_check(id, tpdf, size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200215 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200216 return EXIT_FAILURE;
217 }
218 }
Radek Krejcieac35532015-05-31 19:09:15 +0200219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200220 /* check top-level names */
221 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200222 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200223 return EXIT_FAILURE;
224 }
Radek Krejcieac35532015-05-31 19:09:15 +0200225
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200226 /* check submodule's top-level names */
227 for (i = 0; i < module->inc_size; i++) {
228 if (dup_typedef_check(id, module->inc[i].submodule->tpdf, module->inc[i].submodule->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200229 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200230 return EXIT_FAILURE;
231 }
232 }
Radek Krejcieac35532015-05-31 19:09:15 +0200233
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200234 /* check top-level names in the main module */
235 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +0200236 if (dup_typedef_check(id, ((struct lys_submodule *)module)->belongsto->tpdf,
237 ((struct lys_submodule *)module)->belongsto->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200238 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200239 return EXIT_FAILURE;
240 }
241 }
Radek Krejcieac35532015-05-31 19:09:15 +0200242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200243 break;
244 case LY_IDENT_PREFIX:
245 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200246
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200247 if (module->type) {
248 /* go to the main module */
Radek Krejcib8048692015-08-05 13:36:34 +0200249 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200250 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200252 /* check the main module itself */
253 if (dup_prefix_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200254 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200255 return EXIT_FAILURE;
256 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200258 /* and all its submodules */
259 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200260 if (dup_prefix_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200261 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200262 return EXIT_FAILURE;
263 }
264 }
265 break;
Radek Krejcib05774c2015-06-18 13:52:59 +0200266 case LY_IDENT_FEATURE:
267 assert(module);
268
269 /* check feature name uniqness*/
Radek Krejci49babf32015-06-18 13:56:17 +0200270 /* check features in the current module */
Radek Krejcib05774c2015-06-18 13:52:59 +0200271 if (dup_feature_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200272 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200273 return EXIT_FAILURE;
274 }
275
276 /* and all its submodules */
277 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200278 if (dup_feature_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200279 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200280 return EXIT_FAILURE;
281 }
282 }
283 break;
284
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200285 default:
286 /* no check required */
287 break;
288 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200289
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200290 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200291}
292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200293static int
Radek Krejci76512572015-08-04 09:47:08 +0200294check_mandatory(struct lys_node *mnode)
Radek Krejci3de29a72015-06-16 15:23:03 +0200295{
Radek Krejci76512572015-08-04 09:47:08 +0200296 struct lys_node *child;
Radek Krejci3de29a72015-06-16 15:23:03 +0200297
298 assert(mnode);
299
Radek Krejci1574a8d2015-08-03 14:16:52 +0200300 if (mnode->flags & LYS_MAND_TRUE) {
Radek Krejci3de29a72015-06-16 15:23:03 +0200301 return EXIT_FAILURE;
302 }
303
Radek Krejci76512572015-08-04 09:47:08 +0200304 if (mnode->nodetype == LYS_CASE || mnode->nodetype == LYS_CHOICE) {
Radek Krejcifd0bb0a2015-06-18 13:18:24 +0200305 LY_TREE_FOR(mnode->child, child) {
306 if (check_mandatory(child)) {
307 return EXIT_FAILURE;
308 }
Radek Krejci3de29a72015-06-16 15:23:03 +0200309 }
310 }
311
312 return EXIT_SUCCESS;
313}
314
315static int
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200316check_date(const char *date, unsigned int line)
Radek Krejcice7fb782015-05-29 16:52:34 +0200317{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200318 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200320 assert(date);
Radek Krejcice7fb782015-05-29 16:52:34 +0200321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200322 if (strlen(date) != LY_REV_SIZE - 1) {
323 goto error;
324 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200326 for (i = 0; i < LY_REV_SIZE - 1; i++) {
327 if (i == 4 || i == 7) {
328 if (date[i] != '-') {
329 goto error;
330 }
331 } else if (!isdigit(date[i])) {
332 goto error;
333 }
334 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200335
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200336 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200337
338error:
339
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200340 LOGVAL(LYE_INDATE, line, date);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200341 return EXIT_FAILURE;
Radek Krejcice7fb782015-05-29 16:52:34 +0200342}
343
Radek Krejci41726f92015-06-19 13:11:05 +0200344static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200345check_length_range(const char *expr, struct lys_type *type, unsigned int line)
Radek Krejci41726f92015-06-19 13:11:05 +0200346{
Michal Vasko9286afd2015-07-14 15:27:59 +0200347 struct len_ran_intv *intv = NULL, *tmp_intv;
Radek Krejci41726f92015-06-19 13:11:05 +0200348 const char *c = expr;
349 char *tail;
Michal Vasko9286afd2015-07-14 15:27:59 +0200350 int ret = EXIT_FAILURE, flg = 1; /* first run flag */
Radek Krejci41726f92015-06-19 13:11:05 +0200351
352 assert(expr);
353
Radek Krejci41726f92015-06-19 13:11:05 +0200354lengthpart:
355
356 while (isspace(*c)) {
357 c++;
358 }
359
360 /* lower boundary or explicit number */
361 if (!strncmp(c, "max", 3)) {
362max:
363 c += 3;
364 while (isspace(*c)) {
365 c++;
366 }
367 if (*c != '\0') {
368 goto error;
369 }
370
Michal Vasko9286afd2015-07-14 15:27:59 +0200371 goto syntax_ok;
Radek Krejci41726f92015-06-19 13:11:05 +0200372
373 } else if (!strncmp(c, "min", 3)) {
374 if (!flg) {
375 /* min cannot be used elsewhere than in the first length-part */
376 goto error;
377 } else {
378 flg = 0;
Radek Krejci41726f92015-06-19 13:11:05 +0200379 }
380 c += 3;
381 while (isspace(*c)) {
382 c++;
383 }
384
385 if (*c == '|') {
386 c++;
387 /* process next length-parth */
388 goto lengthpart;
389 } else if (*c == '\0') {
Michal Vasko9286afd2015-07-14 15:27:59 +0200390 goto syntax_ok;
Radek Krejci41726f92015-06-19 13:11:05 +0200391 } else if (!strncmp(c, "..", 2)) {
392upper:
393 c += 2;
394 while (isspace(*c)) {
395 c++;
396 }
397 if (*c == '\0') {
398 goto error;
399 }
400
401 /* upper boundary */
402 if (!strncmp(c, "max", 3)) {
403 goto max;
404 }
405
Michal Vasko8548cf92015-07-20 15:17:53 +0200406 if (!isdigit(*c) && (*c != '+') && (*c != '-')) {
Radek Krejci41726f92015-06-19 13:11:05 +0200407 goto error;
408 }
409
Radek Krejcib8ca1082015-07-10 11:24:11 +0200410 errno = 0;
Michal Vasko8548cf92015-07-20 15:17:53 +0200411 strtoll(c, &tail, 10);
Radek Krejcib8ca1082015-07-10 11:24:11 +0200412 if (errno) {
413 goto error;
414 }
Radek Krejci41726f92015-06-19 13:11:05 +0200415 c = tail;
416 while (isspace(*c)) {
417 c++;
418 }
Radek Krejci41726f92015-06-19 13:11:05 +0200419 if (*c == '\0') {
Michal Vasko9286afd2015-07-14 15:27:59 +0200420 goto syntax_ok;
Radek Krejci41726f92015-06-19 13:11:05 +0200421 } else if (*c == '|') {
422 c++;
Radek Krejci41726f92015-06-19 13:11:05 +0200423 /* process next length-parth */
424 goto lengthpart;
425 } else {
426 goto error;
427 }
428 } else {
429 goto error;
430 }
431
Michal Vasko8548cf92015-07-20 15:17:53 +0200432 } else if (isdigit(*c) || (*c == '-') || (*c == '+')) {
Radek Krejci41726f92015-06-19 13:11:05 +0200433 /* number */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200434 errno = 0;
Michal Vasko8548cf92015-07-20 15:17:53 +0200435 strtoll(c, &tail, 10);
Radek Krejcib8ca1082015-07-10 11:24:11 +0200436 if (errno) {
437 /* out of range value */
438 goto error;
439 }
Radek Krejci41726f92015-06-19 13:11:05 +0200440 c = tail;
441 while (isspace(*c)) {
442 c++;
443 }
Radek Krejci41726f92015-06-19 13:11:05 +0200444
445 if (*c == '|') {
446 c++;
447 /* process next length-parth */
448 goto lengthpart;
449 } else if (*c == '\0') {
Michal Vasko9286afd2015-07-14 15:27:59 +0200450 goto syntax_ok;
Radek Krejci41726f92015-06-19 13:11:05 +0200451 } else if (!strncmp(c, "..", 2)) {
452 goto upper;
453 }
Michal Vasko9286afd2015-07-14 15:27:59 +0200454
455 } else {
456 goto error;
457 }
458
459syntax_ok:
460
Michal Vasko020404f2015-07-15 15:45:42 +0200461 if (get_len_ran_interval(expr, type, 1, &intv)) {
Michal Vasko9286afd2015-07-14 15:27:59 +0200462 goto error;
463 }
464
465 ret = EXIT_SUCCESS;
Radek Krejci41726f92015-06-19 13:11:05 +0200466
467error:
468
Michal Vasko9286afd2015-07-14 15:27:59 +0200469 while (intv) {
470 tmp_intv = intv->next;
471 free(intv);
472 intv = tmp_intv;
473 }
474
475 if (ret) {
476 LOGVAL(VE_INARG, line, expr, "length");
477 }
478
479 return ret;
Radek Krejci41726f92015-06-19 13:11:05 +0200480}
481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200482static const char *
483read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200484{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200485 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200487 /* there should be <text> child */
488 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
489 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
490 } else if (node->child->content) {
491 len = strlen(node->child->content);
492 return lydict_insert(ctx, node->child->content, len);
493 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200494
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200495 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200497}
498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200499static int
Radek Krejcia52656e2015-08-05 13:41:50 +0200500fill_yin_identity(struct lys_module *module, struct lyxml_elem *yin, struct lys_ident *ident, struct unres_item *unres)
Radek Krejci04581c62015-05-22 21:24:00 +0200501{
Radek Krejci73adb602015-07-02 18:07:40 +0200502 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200503 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200504
Michal Vasko4cfcd252015-08-03 14:31:10 +0200505 GETVAL(value, yin, "name");
506 ident->name = lydict_insert(module->ctx, value, 0);
507
Radek Krejci76512572015-08-04 09:47:08 +0200508 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200509 return EXIT_FAILURE;
510 }
Radek Krejci04581c62015-05-22 21:24:00 +0200511
Radek Krejci73adb602015-07-02 18:07:40 +0200512 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200513 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
514 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200515 continue;
516 }
517
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200518 if (!strcmp(node->name, "base")) {
519 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200520 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200521 return EXIT_FAILURE;
522 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200523 GETVAL(value, node, "name");
Michal Vasko4cfcd252015-08-03 14:31:10 +0200524 add_unres_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200525 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200526 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200527 return EXIT_FAILURE;
528 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200529 }
Radek Krejci04581c62015-05-22 21:24:00 +0200530
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200531error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200532 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200533}
534
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200535static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200536read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200537{
Radek Krejci73adb602015-07-02 18:07:40 +0200538 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200539 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200540
Radek Krejci73adb602015-07-02 18:07:40 +0200541 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200542 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
543 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200544 continue;
545 }
546
Radek Krejci41726f92015-06-19 13:11:05 +0200547 if (!strcmp(child->name, "description")) {
548 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200549 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200550 return EXIT_FAILURE;
551 }
552 restr->dsc = read_yin_subnode(ctx, child, "text");
553 if (!restr->dsc) {
554 return EXIT_FAILURE;
555 }
556 } else if (!strcmp(child->name, "reference")) {
557 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200558 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200559 return EXIT_FAILURE;
560 }
561 restr->ref = read_yin_subnode(ctx, child, "text");
562 if (!restr->ref) {
563 return EXIT_FAILURE;
564 }
565 } else if (!strcmp(child->name, "error-app-tag")) {
566 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200567 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200568 return EXIT_FAILURE;
569 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200570 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200571 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200572 } else if (!strcmp(child->name, "error-message")) {
573 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200574 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200575 return EXIT_FAILURE;
576 }
577 restr->emsg = read_yin_subnode(ctx, child, "value");
578 if (!restr->emsg) {
579 return EXIT_FAILURE;
580 }
581 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200582 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200583 return EXIT_FAILURE;
584 }
Radek Krejci41726f92015-06-19 13:11:05 +0200585 }
586
587 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200588
589error:
590 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200591}
592
593static int
Radek Krejcib8048692015-08-05 13:36:34 +0200594fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200595 struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200596{
Michal Vasko69068852015-07-13 14:34:31 +0200597#define REGEX_ERR_LEN 128
Radek Krejcif2860132015-06-20 12:37:20 +0200598 const char *value, *delim, *name;
Michal Vasko69068852015-07-13 14:34:31 +0200599 char regex_err[REGEX_ERR_LEN];
Radek Krejci5fbc9162015-06-19 14:11:11 +0200600 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200601 struct lys_restr **restr;
602 struct lys_type_bit bit;
Michal Vasko69068852015-07-13 14:34:31 +0200603 regex_t preq;
604 int i, j, ret;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200605 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200606 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200607
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200608 GETVAL(value, yin, "name");
609
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200610 delim = strchr(value, ':');
611 if (delim) {
612 type->prefix = lydict_insert(module->ctx, value, delim - value);
613 delim++;
614 value += delim-value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200615 }
Radek Krejci667b97f2015-05-25 15:03:30 +0200616
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200617 type->der = resolve_superior_type(value, type->prefix, module, parent);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200618 if (!type->der) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200619 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200620 type->der = (struct lys_tpdf *)parent;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200621 add_unres_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
622 return EXIT_SUCCESS;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200623 }
624 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200625
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200626 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200627 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200628 /* RFC 6020 9.7.4 - bit */
629
630 /* get bit specifications, at least one must be present */
631 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200632 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
633 /* garbage */
634 lyxml_free_elem(module->ctx, node);
635 continue;
636 }
637
Radek Krejci994b6f62015-06-18 16:47:27 +0200638 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200639 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200640 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200641 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200642 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200643 }
644 }
Radek Krejciac781922015-07-09 15:35:14 +0200645 if (!type->der->type.der && !type->info.bits.count) {
646 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200647 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200648 goto error;
649 }
Radek Krejciac781922015-07-09 15:35:14 +0200650 if (type->der->type.der && type->info.bits.count) {
651 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200652 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200653 goto error;
654 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200655
656 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200657 p = 0;
658 i = -1;
659 LY_TREE_FOR(yin->child, next) {
660 i++;
661
662 GETVAL(value, next, "name");
663 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200664 goto error;
665 }
666 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200667 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200668 type->info.bits.count = i + 1;
669 goto error;
670 }
671
672 /* check the name uniqueness */
673 for (j = 0; j < i; j++) {
674 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200675 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200676 type->info.bits.count = i + 1;
677 goto error;
678 }
679 }
680
Radek Krejci0d70c372015-07-02 16:23:10 +0200681 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200682 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200683 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
684 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200685 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200686 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200687
Radek Krejci0d70c372015-07-02 16:23:10 +0200688 if (!strcmp(node->name, "position")) {
689 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200690 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200691
692 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200693 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200694 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200695 type->info.bits.count = i + 1;
696 goto error;
697 }
698 type->info.bits.bit[i].pos = (uint32_t)p_;
699
700 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200701 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200702 p = type->info.bits.bit[i].pos;
703 p++;
704 } else {
705 /* check that the value is unique */
706 for (j = 0; j < i; j++) {
707 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200708 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 +0200709 type->info.bits.count = i + 1;
710 goto error;
711 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200712 }
713 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200714 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200715 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200716 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200717 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200718 }
719 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200720 /* assign value automatically */
721 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200722 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200723 type->info.bits.count = i + 1;
724 goto error;
725 }
726 type->info.bits.bit[i].pos = (uint32_t)p;
727 p++;
728 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200729
730 /* keep them ordered by position */
731 j = i;
732 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
733 /* switch them */
734 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
735 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
736 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
737 j--;
738 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200739 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200740 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200741
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200742 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200743 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200744 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200745 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
746 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200747 continue;
748 }
749
Radek Krejcif9401c32015-06-26 16:47:36 +0200750 if (!strcmp(node->name, "range")) {
751 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200752 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200753 goto error;
754 }
755
756 GETVAL(value, node, "value");
Michal Vasko8548cf92015-07-20 15:17:53 +0200757 if (check_length_range(value, type, LOGLINE(node))) {
Radek Krejcif9401c32015-06-26 16:47:36 +0200758 goto error;
759 }
760 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
761 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
762
763 /* get possible substatements */
764 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
765 goto error;
766 }
767 } else if (!strcmp(node->name, "fraction-digits")) {
768 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200769 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200770 goto error;
771 }
772 GETVAL(value, node, "value");
773 v = strtol(value, NULL, 10);
774
775 /* range check */
776 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200777 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200778 goto error;
779 }
780 type->info.dec64.dig = (uint8_t)v;
781 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200782 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200783 goto error;
784 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200785 }
786
787 /* mandatory sub-statement(s) check */
788 if (!type->info.dec64.dig && !type->der->type.der) {
789 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200790 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200791 goto error;
792 }
Radek Krejci7511f402015-07-10 09:56:30 +0200793 if (type->info.dec64.dig && type->der->type.der) {
794 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200795 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200796 goto error;
797 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200798 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200801 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200802
Radek Krejci994b6f62015-06-18 16:47:27 +0200803 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200804 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200805 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
806 /* garbage */
807 lyxml_free_elem(module->ctx, node);
808 continue;
809 }
810
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200812 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200813 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200814 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200815 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200816 }
817 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200818 if (!type->der->type.der && !type->info.enums.count) {
819 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200820 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200821 goto error;
822 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200823 if (type->der->type.der && type->info.enums.count) {
824 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200825 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200826 goto error;
827 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200828
Radek Krejci1574a8d2015-08-03 14:16:52 +0200829 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200830 v = 0;
831 i = -1;
832 LY_TREE_FOR(yin->child, next) {
833 i++;
834
835 GETVAL(value, next, "name");
836 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200837 goto error;
838 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200839 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200840 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200841 type->info.enums.count = i + 1;
842 goto error;
843 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200844
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200845 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200846 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200847 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200848 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200849 type->info.enums.count = i + 1;
850 goto error;
851 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200852
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200853 /* check the name uniqueness */
854 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200855 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200856 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200857 type->info.enums.count = i + 1;
858 goto error;
859 }
860 }
Radek Krejci04581c62015-05-22 21:24:00 +0200861
Radek Krejci0d70c372015-07-02 16:23:10 +0200862 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200863 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200864 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
865 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200866 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200867 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200868
Radek Krejci0d70c372015-07-02 16:23:10 +0200869 if (!strcmp(node->name, "value")) {
870 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200871 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200872
873 /* range check */
874 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200875 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200876 type->info.enums.count = i + 1;
877 goto error;
878 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200879 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200880
881 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200882 if (type->info.enums.enm[i].value > v) {
883 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200884 v++;
885 } else {
886 /* check that the value is unique */
887 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200888 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200889 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200890 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200891 type->info.enums.count = i + 1;
892 goto error;
893 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200894 }
895 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200896 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200897 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200898 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200899 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200900 }
901 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 /* assign value automatically */
903 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200904 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200905 type->info.enums.count = i + 1;
906 goto error;
907 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200908 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200909 v++;
910 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200911 }
912 break;
913
914 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200915 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200916
917 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200918 LY_TREE_FOR_SAFE(yin->child, next, node) {
919 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
920 /* garbage */
921 lyxml_free_elem(module->ctx, node);
922 continue;
923 }
924
925 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200926 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200927 goto error;
928 }
929 }
930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200931 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200932 if (type->der->type.der) {
933 /* this is just a derived type with no base specified/required */
934 break;
935 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200936 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200937 goto error;
938 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200939 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200940 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200941 goto error;
942 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200943 GETVAL(value, yin->child, "name");
944 add_unres_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200945 break;
946
947 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200948 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200949 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200950 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
951 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200952 continue;
953 }
954
Radek Krejciaf351422015-06-19 14:49:38 +0200955 if (!strcmp(node->name, "require-instance")) {
956 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200957 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200958 goto error;
959 }
960 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200961 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200962 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200963 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200964 type->info.inst.req = -1;
965 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200966 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200967 goto error;
968 }
969 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200970 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200971 goto error;
972 }
Radek Krejciaf351422015-06-19 14:49:38 +0200973 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200974
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200975 break;
976
Radek Krejcif2860132015-06-20 12:37:20 +0200977 case LY_TYPE_BINARY:
978 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200979 case LY_TYPE_INT8:
980 case LY_TYPE_INT16:
981 case LY_TYPE_INT32:
982 case LY_TYPE_INT64:
983 case LY_TYPE_UINT8:
984 case LY_TYPE_UINT16:
985 case LY_TYPE_UINT32:
986 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200987 /* RFC 6020 9.2.4 - range */
988
989 /* length and range are actually the same restriction, so process
990 * them by this common code, we just need to differ the name and
991 * structure where the information will be stored
992 */
993 if (type->base == LY_TYPE_BINARY) {
994 restr = &type->info.binary.length;
995 name = "length";
996 } else {
997 restr = &type->info.num.range;
998 name = "range";
999 }
1000
Radek Krejci73adb602015-07-02 18:07:40 +02001001 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001002 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1003 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001004 continue;
1005 }
1006
Radek Krejcif2860132015-06-20 12:37:20 +02001007 if (!strcmp(node->name, name)) {
1008 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001009 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001010 goto error;
1011 }
1012
1013 GETVAL(value, node, "value");
Michal Vasko8548cf92015-07-20 15:17:53 +02001014 if (check_length_range(value, type, LOGLINE(node))) {
Radek Krejcif2860132015-06-20 12:37:20 +02001015 goto error;
1016 }
1017 *restr = calloc(1, sizeof **restr);
1018 (*restr)->expr = lydict_insert(module->ctx, value, 0);
1019
1020 /* get possible substatements */
1021 if (read_restr_substmt(module->ctx, *restr, node)) {
1022 goto error;
1023 }
1024 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001025 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +02001026 goto error;
1027 }
Radek Krejcif2860132015-06-20 12:37:20 +02001028 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001029 break;
1030
1031 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +02001032 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +02001033 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001034 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1035 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001036 continue;
1037 }
1038
Radek Krejcidc4c1412015-06-19 15:39:54 +02001039 if (!strcmp(node->name, "path")) {
1040 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001041 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001042 goto error;
1043 }
1044
1045 GETVAL(value, node, "value");
Radek Krejcidc4c1412015-06-19 15:39:54 +02001046 type->info.lref.path = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001047 add_unres_mnode(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin));
1048
Radek Krejcidc4c1412015-06-19 15:39:54 +02001049 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001050 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +02001051 goto error;
1052 }
Radek Krejci73adb602015-07-02 18:07:40 +02001053 }
1054
1055 if (!type->info.lref.path) {
1056 if (type->der->type.der) {
1057 /* this is just a derived type with no path specified/required */
1058 break;
1059 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001060 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +02001061 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +02001062 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 break;
1064
1065 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +02001066 /* RFC 6020 9.4.4 - length */
1067 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +02001068 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +02001069 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001070 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1071 /* garbage */
1072 lyxml_free_elem(module->ctx, node);
1073 continue;
1074 }
1075
Radek Krejci3733a802015-06-19 13:43:21 +02001076 if (!strcmp(node->name, "length")) {
1077 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001078 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001079 goto error;
1080 }
1081
1082 GETVAL(value, node, "value");
Michal Vasko8548cf92015-07-20 15:17:53 +02001083 if (check_length_range(value, type, LOGLINE(node))) {
Radek Krejci3733a802015-06-19 13:43:21 +02001084 goto error;
1085 }
1086 type->info.str.length = calloc(1, sizeof *type->info.str.length);
1087 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
1088
Radek Krejci5fbc9162015-06-19 14:11:11 +02001089 /* get possible sub-statements */
1090 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +02001091 goto error;
1092 }
Radek Krejci82d971d2015-06-19 14:20:50 +02001093 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +02001094 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +02001095 i++;
Radek Krejci3733a802015-06-19 13:43:21 +02001096 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001097 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +02001098 goto error;
1099 }
1100 }
Radek Krejci5fbc9162015-06-19 14:11:11 +02001101 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +02001102 if (i) {
1103 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
1104 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +02001105 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +02001106
1107 /* check that the regex is valid */
1108 if ((ret = regcomp(&preq, value, REG_EXTENDED | REG_NOSUB)) != 0) {
1109 regerror(ret, &preq, regex_err, REGEX_ERR_LEN);
1110 regfree(&preq);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001111 LOGVAL(LYE_INREGEX, LOGLINE(node), value, regex_err);
Michal Vasko69068852015-07-13 14:34:31 +02001112 free(type->info.str.patterns);
1113 goto error;
1114 }
1115 regfree(&preq);
1116
Radek Krejci73adb602015-07-02 18:07:40 +02001117 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001118
1119 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +02001120 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +02001121 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +02001122 goto error;
1123 }
Radek Krejci73adb602015-07-02 18:07:40 +02001124 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001125 }
1126 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 break;
1128
1129 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001130 /* RFC 6020 7.4 - type */
1131 /* count number of types in union */
1132 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001133 LY_TREE_FOR_SAFE(yin->child, next, node) {
1134 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1135 /* garbage */
1136 lyxml_free_elem(module->ctx, node);
1137 continue;
1138 }
1139
Radek Krejcie4c366b2015-07-02 10:11:31 +02001140 if (!strcmp(node->name, "type")) {
1141 i++;
1142 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001143 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001144 goto error;
1145 }
1146 }
1147
1148 if (!i) {
1149 if (type->der->type.der) {
1150 /* this is just a derived type with no base specified/required */
1151 break;
1152 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001153 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001154 goto error;
1155 }
1156
1157 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001158 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001159 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001160 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001161 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001162 goto error;
1163 }
1164 type->info.uni.count++;
1165
1166 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001167 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001168 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001169 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001170 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001171 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001172 goto error;
1173 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001174 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001175 break;
1176
1177 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001178 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001179 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1180 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001181 LY_TREE_FOR(yin->child, node) {
1182 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001183 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001184 goto error;
1185 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001186 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 break;
1188 }
1189
1190 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001191
1192error:
1193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001195}
1196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001197static int
Radek Krejcib8048692015-08-05 13:36:34 +02001198fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001199{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001200 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001201 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001202 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001204 GETVAL(value, yin, "name");
1205 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1206 goto error;
1207 }
1208 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001210 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001211 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001212 goto error;
1213 }
Radek Krejcieac35532015-05-31 19:09:15 +02001214
Radek Krejci73adb602015-07-02 18:07:40 +02001215 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001216 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1217 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001218 continue;
1219 }
1220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001221 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001222 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001223 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001224 goto error;
1225 }
Radek Krejci73adb602015-07-02 18:07:40 +02001226 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1227 goto error;
1228 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001229 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001230 } else if (!strcmp(node->name, "default")) {
1231 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001232 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001233 goto error;
1234 }
1235 GETVAL(value, node, "value");
1236 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001237 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001238 } else if (!strcmp(node->name, "units")) {
1239 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001240 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001241 goto error;
1242 }
1243 GETVAL(value, node, "name");
1244 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1245 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001246 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001247 goto error;
1248 }
1249 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001251 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001252 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001253 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001254 goto error;
1255 }
Radek Krejcieac35532015-05-31 19:09:15 +02001256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001257 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001258 if (tpdf->dflt) {
1259 add_unres_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001260 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001262 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001263
1264error:
1265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001266 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001267}
1268
Radek Krejci3cf9e222015-06-18 11:37:50 +02001269static int
Radek Krejcib8048692015-08-05 13:36:34 +02001270fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_item *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001271{
1272 const char *value;
1273 struct lyxml_elem *child, *next;
1274 int c = 0;
1275
Radek Krejcib05774c2015-06-18 13:52:59 +02001276 GETVAL(value, yin, "name");
1277 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1278 goto error;
1279 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001280 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001281 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001282
Radek Krejci76512572015-08-04 09:47:08 +02001283 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001284 goto error;
1285 }
1286
1287 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001288 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1289 /* garbage */
1290 lyxml_free_elem(module->ctx, child);
1291 continue;
1292 }
1293
Radek Krejci3cf9e222015-06-18 11:37:50 +02001294 if (!strcmp(child->name, "if-feature")) {
1295 c++;
1296 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001297 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001298 goto error;
1299 }
1300 }
1301
1302 if (c) {
1303 f->features = calloc(c, sizeof *f->features);
1304 }
Radek Krejci73adb602015-07-02 18:07:40 +02001305 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001306 GETVAL(value, child, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001307 add_unres_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child));
Radek Krejci3cf9e222015-06-18 11:37:50 +02001308 }
1309
Radek Krejci3cf9e222015-06-18 11:37:50 +02001310 return EXIT_SUCCESS;
1311
1312error:
1313
1314 return EXIT_FAILURE;
1315}
1316
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001317static int
Radek Krejcib8048692015-08-05 13:36:34 +02001318fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001319{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001320 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001322 GETVAL(value, yin, "condition");
Radek Krejci0bd5db42015-06-19 13:30:07 +02001323 must->expr = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02001324
Radek Krejci41726f92015-06-19 13:11:05 +02001325 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001326
Radek Krejci41726f92015-06-19 13:11:05 +02001327error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001329 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001330}
1331
Radek Krejcieb00f512015-07-01 16:44:58 +02001332/*
1333 * type: 0 - min, 1 - max
1334 */
1335static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001336deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001337{
1338 const char *value;
1339 char *endptr;
1340 unsigned long val;
1341 uint32_t *ui32val;
1342
1343 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001344 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001345 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001346 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001347 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001348 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001349 }
Radek Krejci76512572015-08-04 09:47:08 +02001350 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001351 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001352 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001353 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001354 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001355 }
1356 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001357 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1358 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001359 goto error;
1360 }
1361
1362 GETVAL(value, node, "value");
1363 while (isspace(value[0])) {
1364 value++;
1365 }
1366
1367 /* convert it to uint32_t */
1368 errno = 0;
1369 endptr = NULL;
1370 val = strtoul(value, &endptr, 10);
1371 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001372 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001373 goto error;
1374 }
1375 if (type) {
1376 d->max = (uint32_t)val;
1377 } else {
1378 d->min = (uint32_t)val;
1379 }
1380
1381 if (d->mod == LY_DEVIATE_ADD) {
1382 /* check that there is no current value */
1383 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001384 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1385 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001386 goto error;
1387 }
1388 }
1389
1390 if (d->mod == LY_DEVIATE_DEL) {
1391 /* check values */
1392 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001393 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1394 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001395 goto error;
1396 }
1397 /* remove current min-elements value of the target */
1398 *ui32val = 0;
1399 } else { /* add (already checked) and replace */
1400 /* set new value specified in deviation */
1401 *ui32val = (uint32_t)val;
1402 }
1403
1404 return EXIT_SUCCESS;
1405
1406error:
1407
1408 return EXIT_FAILURE;
1409}
1410
1411static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001412fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001413{
1414 const char *value, **stritem;
1415 struct lyxml_elem *next, *child, *develem;
1416 int c_dev = 0, c_must, c_uniq;
1417 int f_min = 0; /* flags */
1418 int i, j;
Radek Krejcia52656e2015-08-05 13:41:50 +02001419 struct lys_deviate *d = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02001420 struct lys_node *mnode = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001421 struct lys_node_choice *choice = NULL;
1422 struct lys_node_leaf *leaf = NULL;
1423 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001424 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001425 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001426 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001427
1428 GETVAL(value, yin, "target-node");
1429 dev->target_name = lydict_insert(module->ctx, value, 0);
1430
1431 /* resolve target node */
Radek Krejci76512572015-08-04 09:47:08 +02001432 dev->target = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT);
Radek Krejcieb00f512015-07-01 16:44:58 +02001433 if (!dev->target) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001434 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 goto error;
1436 }
1437 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001438 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001439 goto error;
1440 }
1441 /* mark the target module as deviated */
1442 dev->target->module->deviated = 1;
1443
1444 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001445 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1446 /* garbage */
1447 lyxml_free_elem(module->ctx, child);
1448 continue;
1449 }
1450
Radek Krejcieb00f512015-07-01 16:44:58 +02001451 if (!strcmp(child->name, "description")) {
1452 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001453 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001454 goto error;
1455 }
1456 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1457 if (!dev->dsc) {
1458 goto error;
1459 }
1460 } else if (!strcmp(child->name, "reference")) {
1461 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001462 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001463 goto error;
1464 }
1465 dev->ref = read_yin_subnode(module->ctx, child, "text");
1466 if (!dev->ref) {
1467 goto error;
1468 }
1469 } else if (!strcmp(child->name, "deviate")) {
1470 c_dev++;
1471
1472 /* skip lyxml_free_elem() at the end of the loop, node will be
1473 * further processed later
1474 */
1475 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001476
Radek Krejcieb00f512015-07-01 16:44:58 +02001477 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001478 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001479 goto error;
1480 }
1481
1482 lyxml_free_elem(module->ctx, child);
1483 }
1484
1485 if (c_dev) {
1486 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1487 }
1488
1489 LY_TREE_FOR(yin->child, develem) {
1490 /* init */
1491 f_min = 0;
1492 c_must = 0;
1493 c_uniq = 0;
1494
1495 /* get deviation type */
1496 GETVAL(value, develem, "value");
1497 if (!strcmp(value, "not-supported")) {
1498 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1499 /* no property expected in this case */
1500 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001501 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
1504
Radek Krejci5b917642015-07-02 09:03:13 +02001505 /* and neither any other deviate statement is expected,
1506 * not-supported deviation must be the only deviation of the target
1507 */
1508 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001509 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1510 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001511 goto error;
1512 }
1513
1514
Radek Krejcieb00f512015-07-01 16:44:58 +02001515 /* remove target node */
1516 ly_mnode_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001517 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001518
Radek Krejci5b917642015-07-02 09:03:13 +02001519 dev->deviate_size = 1;
1520 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 } else if (!strcmp(value, "add")) {
1522 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1523 } else if (!strcmp(value, "replace")) {
1524 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1525 } else if (!strcmp(value, "delete")) {
1526 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1527 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001528 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001529 goto error;
1530 }
1531 d = &dev->deviate[dev->deviate_size];
1532
1533 /* process deviation properties */
1534 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001535 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1536 /* garbage */
1537 lyxml_free_elem(module->ctx, child);
1538 continue;
1539 }
1540
Radek Krejcieb00f512015-07-01 16:44:58 +02001541 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001542 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001543 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001544 goto error;
1545 }
1546
1547 /* for we deviate from RFC 6020 and allow config property even it is/is not
1548 * specified in the target explicitly since config property inherits. So we expect
1549 * that config is specified in every node. But for delete, we check that the value
1550 * is the same as here in deviation
1551 */
1552 GETVAL(value, child, "value");
1553 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001554 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001556 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001558 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 goto error;
1560 }
1561
1562 if (d->mod == LY_DEVIATE_DEL) {
1563 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001564 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001565 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1566 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 goto error;
1568 }
1569 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001570 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001571
1572 /* ... and inherit config value from the target's parent */
1573 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001574 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001575 } else {
1576 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001577 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001578 }
1579 } else { /* add and replace are the same in this case */
1580 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001581 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001582
1583 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001584 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001585 }
1586 } else if (!strcmp(child->name, "default")) {
1587 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001588 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 goto error;
1590 }
1591 GETVAL(value, child, "value");
1592 d->dflt = lydict_insert(module->ctx, value, 0);
1593
Radek Krejci76512572015-08-04 09:47:08 +02001594 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001595 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001596
1597 if (d->mod == LY_DEVIATE_ADD) {
1598 /* check that there is no current value */
1599 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001600 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1601 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001602 goto error;
1603 }
1604 }
1605
Radek Krejci76512572015-08-04 09:47:08 +02001606 mnode = resolve_schema_nodeid(d->dflt, (struct lys_node *)choice, choice->module, LYS_CHOICE);
Radek Krejcieb00f512015-07-01 16:44:58 +02001607 if (d->mod == LY_DEVIATE_DEL) {
1608 if (!choice->dflt || choice->dflt != mnode) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001609 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1610 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001611 goto error;
1612 }
1613 } else { /* add (already checked) and replace */
1614 choice->dflt = mnode;
1615 if (!choice->dflt) {
1616 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001617 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001618 goto error;
1619 }
1620 }
Radek Krejci76512572015-08-04 09:47:08 +02001621 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001622 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001623
1624 if (d->mod == LY_DEVIATE_ADD) {
1625 /* check that there is no current value */
1626 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001627 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1628 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001629 goto error;
1630 }
1631 }
1632
1633 if (d->mod == LY_DEVIATE_DEL) {
1634 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001635 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1636 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001637 goto error;
1638 }
1639 /* remove value */
1640 lydict_remove(leaf->module->ctx, leaf->dflt);
1641 leaf->dflt = NULL;
1642 } else { /* add (already checked) and replace */
1643 /* remove value */
1644 lydict_remove(leaf->module->ctx, leaf->dflt);
1645
1646 /* set new value */
1647 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1648 }
1649 } else {
1650 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001651 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1652 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001653 goto error;
1654 }
1655 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001656 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001657 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001658 goto error;
1659 }
1660
1661 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001662 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001663 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1664 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001665 goto error;
1666 }
1667
1668 GETVAL(value, child, "value");
1669 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001670 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001671 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001672 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001673 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001674 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001675 goto error;
1676 }
1677
1678 if (d->mod == LY_DEVIATE_ADD) {
1679 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001680 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001681 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1682 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001683 goto error;
1684 }
1685 }
1686
1687 if (d->mod == LY_DEVIATE_DEL) {
1688 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001689 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001690 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1691 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001692 goto error;
1693 }
1694 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001695 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001696 } else { /* add (already checked) and replace */
1697 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001698 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001699
1700 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001701 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 }
1703 } else if (!strcmp(child->name, "min-elements")) {
1704 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001705 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001706 goto error;
1707 }
1708 f_min = 1;
1709
1710 if (deviate_minmax(dev->target, child, d, 0)) {
1711 goto error;
1712 }
1713 } else if (!strcmp(child->name, "max-elements")) {
1714 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001715 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001716 goto error;
1717 }
1718
1719 if (deviate_minmax(dev->target, child, d, 1)) {
1720 goto error;
1721 }
1722 } else if (!strcmp(child->name, "must")) {
1723 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001724 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1725 continue;
1726 } else if (!strcmp(child->name, "type")) {
1727 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001728 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 goto error;
1730 }
1731
1732 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001733 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001734 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001735 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001736 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001737 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001738 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1739 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001740 goto error;
1741 }
1742
1743 if (d->mod == LY_DEVIATE_ADD) {
1744 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001745 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1746 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 goto error;
1748 } else if (d->mod == LY_DEVIATE_DEL) {
1749 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001750 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1751 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001752 goto error;
1753 }
1754
1755 /* replace */
1756 /* remove current units value of the target ... */
1757 ly_type_free(dev->target->module->ctx, t);
1758
1759 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001760 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001761 goto error;
1762 }
1763 d->type = t;
1764 } else if (!strcmp(child->name, "unique")) {
1765 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001766 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1767 continue;
1768 } else if (!strcmp(child->name, "units")) {
1769 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001770 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001771 goto error;
1772 }
1773
1774 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001775 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001776 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001777 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001778 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001780 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1781 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001782 goto error;
1783 }
1784
1785 /* get units value */
1786 GETVAL(value, child, "name");
1787 d->units = lydict_insert(module->ctx, value, 0);
1788
1789 /* apply to target */
1790 if (d->mod == LY_DEVIATE_ADD) {
1791 /* check that there is no current value */
1792 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001793 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1794 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001795 goto error;
1796 }
1797 }
1798
1799 if (d->mod == LY_DEVIATE_DEL) {
1800 /* check values */
1801 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001802 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1803 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001804 goto error;
1805 }
1806 /* remove current units value of the target */
1807 lydict_remove(dev->target->module->ctx, *stritem);
1808 } else { /* add (already checked) and replace */
1809 /* remove current units value of the target ... */
1810 lydict_remove(dev->target->module->ctx, *stritem);
1811
1812 /* ... and replace it with the value specified in deviation */
1813 *stritem = lydict_insert(module->ctx, value, 0);
1814 }
1815 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001816 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001817 goto error;
1818 }
1819
1820 lyxml_free_elem(module->ctx, child);
1821 }
1822
1823 if (c_must) {
1824 /* check target node type */
1825 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001826 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001827 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1828 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001829 break;
Radek Krejci76512572015-08-04 09:47:08 +02001830 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001831 trg_must = &((struct lys_node_container *)dev->target)->must;
1832 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001833 break;
Radek Krejci76512572015-08-04 09:47:08 +02001834 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001835 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1836 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001837 break;
Radek Krejci76512572015-08-04 09:47:08 +02001838 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001839 trg_must = &((struct lys_node_list *)dev->target)->must;
1840 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001841 break;
Radek Krejci76512572015-08-04 09:47:08 +02001842 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001843 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1844 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001845 break;
1846 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001847 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1848 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001849 goto error;
1850 }
1851
1852 if (d->mod == LY_DEVIATE_RPL) {
1853 /* remove target's musts and allocate new array for it */
1854 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001855 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1856 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001857 goto error;
1858 }
1859
1860 for (i = 0; i < list->must_size; i++) {
1861 ly_restr_free(dev->target->module->ctx, &(*trg_must[i]));
1862 }
1863 free(*trg_must);
1864 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1865 d->must_size = c_must;
1866 *trg_must_size = 0;
1867 } else if (d->mod == LY_DEVIATE_ADD) {
1868 /* reallocate the must array of the target */
1869 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1870 *trg_must = d->must;
1871 d->must = &(*trg_must[*trg_must_size]);
1872 d->must_size = c_must;
1873 } else { /* LY_DEVIATE_DEL */
1874 d->must = calloc(c_must, sizeof *d->must);
1875 }
1876 }
1877 if (c_uniq) {
1878 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001879 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001880 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1881 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001882 goto error;
1883 }
1884
Radek Krejcib8048692015-08-05 13:36:34 +02001885 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001886 if (d->mod == LY_DEVIATE_RPL) {
1887 /* remove target's unique and allocate new array for it */
1888 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001889 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1890 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001891 goto error;
1892 }
1893
1894 for (i = 0; i < list->unique_size; i++) {
1895 free(list->unique[i].leafs);
1896 }
1897 free(list->unique);
1898 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1899 d->unique_size = c_uniq;
1900 list->unique_size = 0;
1901 } else if (d->mod == LY_DEVIATE_ADD) {
1902 /* reallocate the unique array of the target */
1903 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1904 list->unique = d->unique;
1905 d->unique = &list->unique[list->unique_size];
1906 d->unique_size = c_uniq;
1907 } else { /* LY_DEVIATE_DEL */
1908 d->unique = calloc(c_uniq, sizeof *d->unique);
1909 }
1910 }
1911
1912 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001913 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001914 if (!strcmp(child->name, "must")) {
1915 if (d->mod == LY_DEVIATE_DEL) {
1916 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1917 goto error;
1918 }
1919
1920 /* find must to delete, we are ok with just matching conditions */
1921 for (i = 0; i < *trg_must_size; i++) {
1922 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1923 /* we have a match, free the must structure ... */
1924 ly_restr_free(dev->target->module->ctx, &(*trg_must[i]));
1925 /* ... and maintain the array */
1926 (*trg_must_size)--;
1927 if (i != *trg_must_size) {
1928 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1929 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1930 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1931 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1932 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1933 }
1934 if (!(*trg_must_size)) {
1935 free(*trg_must);
1936 *trg_must = NULL;
1937 } else {
1938 (*trg_must)[*trg_must_size].expr = NULL;
1939 (*trg_must)[*trg_must_size].dsc = NULL;
1940 (*trg_must)[*trg_must_size].ref = NULL;
1941 (*trg_must)[*trg_must_size].eapptag = NULL;
1942 (*trg_must)[*trg_must_size].emsg = NULL;
1943 }
1944
1945 i = -1; /* set match flag */
1946 break;
1947 }
1948 }
1949 d->must_size++;
1950 if (i != -1) {
1951 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001952 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1953 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001954 goto error;
1955 }
1956 } else { /* replace or add */
1957 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1958 goto error;
1959 }
1960 (*trg_must_size)++;
1961 }
1962 } else if (!strcmp(child->name, "unique")) {
1963 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964 GETVAL(value, child, "tag");
1965 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001966 goto error;
1967 }
1968
1969 /* find unique structures to delete */
1970 for (i = 0; i < list->unique_size; i++) {
1971 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1972 continue;
1973 }
1974
1975 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1976 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1977 break;
1978 }
1979 }
1980
1981 if (j == d->unique[d->unique_size].leafs_size) {
1982 /* we have a match, free the unique structure ... */
1983 free(list->unique[i].leafs);
1984 /* ... and maintain the array */
1985 list->unique_size--;
1986 if (i != list->unique_size) {
1987 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1988 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1989 }
1990
1991 if (!list->unique_size) {
1992 free(list->unique);
1993 list->unique = NULL;
1994 } else {
1995 list->unique[list->unique_size].leafs_size = 0;
1996 list->unique[list->unique_size].leafs = NULL;
1997 }
1998
1999 i = -1; /* set match flag */
2000 break;
2001 }
2002 }
2003
2004 d->unique_size++;
2005 if (i != -1) {
2006 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002007 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
2008 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02002009 goto error;
2010 }
2011 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002012 GETVAL(value, child, "tag");
2013 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02002014 goto error;
2015 }
2016 list->unique_size++;
2017 }
2018 }
Radek Krejcieb00f512015-07-01 16:44:58 +02002019 }
Radek Krejci5b917642015-07-02 09:03:13 +02002020
2021 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02002022 }
2023
Radek Krejcieb00f512015-07-01 16:44:58 +02002024 return EXIT_SUCCESS;
2025
2026error:
2027
2028 if (dev->deviate) {
2029 for (i = 0; i < dev->deviate_size; i++) {
2030 lydict_remove(module->ctx, dev->deviate[i].dflt);
2031 lydict_remove(module->ctx, dev->deviate[i].units);
2032
2033 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
2034 for (j = 0; j < dev->deviate[i].must_size; j++) {
2035 ly_restr_free(module->ctx, &dev->deviate[i].must[j]);
2036 }
2037 free(dev->deviate[i].must);
2038
2039 for (j = 0; j < dev->deviate[i].unique_size; j++) {
2040 free(dev->deviate[i].unique[j].leafs);
2041 }
2042 free(dev->deviate[i].unique);
2043 }
2044 }
2045 free(dev->deviate);
2046 }
2047
2048 return EXIT_FAILURE;
2049}
2050
2051static int
Radek Krejcib8048692015-08-05 13:36:34 +02002052fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002053 struct unres_item *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02002054{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002056 struct lyxml_elem *child, *next;
Radek Krejci76512572015-08-04 09:47:08 +02002057 struct lys_node *mnode;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002058 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02002059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 GETVAL(value, yin, "target-node");
2061 aug->target_name = lydict_insert(module->ctx, value, 0);
2062 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02002063
Radek Krejci76512572015-08-04 09:47:08 +02002064 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002065 goto error;
2066 }
2067
2068 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002069 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2070 /* garbage */
2071 lyxml_free_elem(module->ctx, child);
2072 continue;
2073 }
2074
Radek Krejci3cf9e222015-06-18 11:37:50 +02002075 if (!strcmp(child->name, "if-feature")) {
2076 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002077 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002078 } else if (!strcmp(child->name, "when")) {
2079 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002080 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002081 goto error;
2082 }
2083
2084 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002085 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002086 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002087 goto error;
2088 }
Radek Krejci76512572015-08-04 09:47:08 +02002089 add_unres_mnode(module, unres, aug->when, UNRES_WHEN, (struct lys_node *)aug, LOGLINE(child));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002090 lyxml_free_elem(module->ctx, child);
2091 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002092
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002093 /* check allowed data sub-statements */
2094 } else if (!strcmp(child->name, "container")) {
Radek Krejci76512572015-08-04 09:47:08 +02002095 mnode = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002096 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci76512572015-08-04 09:47:08 +02002097 mnode = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002098 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci76512572015-08-04 09:47:08 +02002099 mnode = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002100 } else if (!strcmp(child->name, "list")) {
Radek Krejci76512572015-08-04 09:47:08 +02002101 mnode = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002102 } else if (!strcmp(child->name, "uses")) {
Radek Krejci76512572015-08-04 09:47:08 +02002103 mnode = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002104 } else if (!strcmp(child->name, "choice")) {
Radek Krejci76512572015-08-04 09:47:08 +02002105 mnode = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002106 } else if (!strcmp(child->name, "case")) {
Radek Krejci76512572015-08-04 09:47:08 +02002107 mnode = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002108 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci76512572015-08-04 09:47:08 +02002109 mnode = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002110 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002111 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002112 goto error;
2113 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002114
2115 if (!mnode) {
2116 goto error;
2117 }
2118
2119 /* check for mandatory nodes - if the target node is in another module
2120 * the added nodes cannot be mandatory
2121 */
Radek Krejci76512572015-08-04 09:47:08 +02002122 if ((parent->nodetype != LYS_USES) && check_mandatory(mnode)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002123 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002124 goto error;
2125 }
2126
2127 mnode = NULL;
2128 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002129 }
2130
2131 if (c) {
2132 aug->features = calloc(c, sizeof *aug->features);
2133 }
2134
2135 LY_TREE_FOR_SAFE(yin->child, next, child) {
2136 if (!strcmp(child->name, "if-feature")) {
2137 GETVAL(value, child, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002138 add_unres_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child));
Radek Krejci73adb602015-07-02 18:07:40 +02002139 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002140 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002141 }
2142
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002143 /* aug->child points to the parsed nodes, they must now be
2144 * connected to the tree and adjusted (if possible right now) */
2145 add_unres_mnode(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin));
Radek Krejci106efc02015-06-10 14:36:27 +02002146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002148
2149error:
2150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002152}
2153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154static int
Radek Krejcib8048692015-08-05 13:36:34 +02002155fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn, struct lys_node_uses *uses,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002156 struct unres_item *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002157{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 struct lyxml_elem *sub, *next;
2159 const char *value;
2160 char *endptr;
2161 int f_mand = 0, f_min = 0, f_max = 0;
2162 int c_must = 0;
2163 int r;
2164 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002165
Radek Krejci76512572015-08-04 09:47:08 +02002166 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 goto error;
2168 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002169
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002170 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002171 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002174 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2175 /* garbage */
2176 lyxml_free_elem(module->ctx, sub);
2177 continue;
2178 }
2179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002180 /* limited applicability */
2181 if (!strcmp(sub->name, "default")) {
2182 /* leaf or choice */
2183 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002184 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 goto error;
2186 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002188 /* check possibility of statements combination */
2189 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002190 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002192 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 goto error;
2194 }
2195 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002196 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002198
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002199 GETVAL(value, sub, "value");
2200 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2201 } else if (!strcmp(sub->name, "mandatory")) {
2202 /* leaf, choice or anyxml */
2203 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002204 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002205 goto error;
2206 }
2207 /* just checking the flags in leaf is not sufficient, we would allow
2208 * multiple mandatory statements with the "false" value
2209 */
2210 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 /* check possibility of statements combination */
2213 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002214 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002216 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 goto error;
2218 }
2219 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002220 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002221 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 GETVAL(value, sub, "value");
2224 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002225 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002226 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002227 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002228 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002229 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 goto error;
2231 }
2232 } else if (!strcmp(sub->name, "min-elements")) {
2233 /* list or leaf-list */
2234 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002235 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 goto error;
2237 }
2238 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 /* 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);
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;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 GETVAL(value, sub, "value");
2252 while (isspace(value[0])) {
2253 value++;
2254 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002255
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002256 /* convert it to uint32_t */
2257 errno = 0;
2258 endptr = NULL;
2259 val = strtoul(value, &endptr, 10);
2260 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002261 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002262 goto error;
2263 }
2264 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002265
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002266 /* magic - bit 3 in flags means min set */
2267 rfn->flags |= 0x04;
2268 } else if (!strcmp(sub->name, "max-elements")) {
2269 /* list or leaf-list */
2270 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002271 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002272 goto error;
2273 }
2274 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 /* check possibility of statements combination */
2277 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002278 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002280 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 goto error;
2282 }
2283 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002284 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002286
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002287 GETVAL(value, sub, "value");
2288 while (isspace(value[0])) {
2289 value++;
2290 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002292 /* convert it to uint32_t */
2293 errno = 0;
2294 endptr = NULL;
2295 val = strtoul(value, &endptr, 10);
2296 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002297 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 goto error;
2299 }
2300 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 /* magic - bit 4 in flags means min set */
2303 rfn->flags |= 0x08;
2304 } else if (!strcmp(sub->name, "presence")) {
2305 /* container */
2306 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002307 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 goto error;
2309 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002310
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002311 /* check possibility of statements combination */
2312 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002313 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002314 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002315 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 goto error;
2317 }
2318 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002319 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002321
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002322 GETVAL(value, sub, "value");
2323 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2324 } else if (!strcmp(sub->name, "must")) {
2325 /* leaf-list, list, container or anyxml */
2326 /* check possibility of statements combination */
2327 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002328 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002330 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 goto error;
2332 }
2333 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002334 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002338 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002339
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002341 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002342 goto error;
2343 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002345 lyxml_free_elem(module->ctx, sub);
2346 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 /* process nodes with cardinality of 0..n */
2349 if (c_must) {
2350 rfn->must = calloc(c_must, sizeof *rfn->must);
2351 }
Radek Krejci73adb602015-07-02 18:07:40 +02002352 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002353 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002354 if (r) {
2355 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 }
Radek Krejci76512572015-08-04 09:47:08 +02002357 add_unres_mnode(module, unres, &rfn->must[rfn->must_size-1], UNRES_MUST, (struct lys_node *)uses,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002358 LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002361 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002362
2363error:
2364
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002365 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002366}
2367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002368static int
Radek Krejcib8048692015-08-05 13:36:34 +02002369fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002370{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 struct lyxml_elem *child;
2372 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002373
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002374 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002375 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2376 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002377 continue;
2378 }
2379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 if (!strcmp(child->name, "prefix")) {
2381 GETVAL(value, child, "value");
2382 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2383 goto error;
2384 }
2385 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2386 } else if (!strcmp(child->name, "revision-date")) {
2387 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002388 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002389 goto error;
2390 }
2391 GETVAL(value, child, "date");
2392 if (check_date(value, LOGLINE(child))) {
2393 goto error;
2394 }
2395 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2396 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002397 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 goto error;
2399 }
2400 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002401
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002402 /* check mandatory information */
2403 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002404 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002405 goto error;
2406 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002407
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002408 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002409 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002410 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002411 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2412 if (!imp->module) {
2413 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2414 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002415 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002416 goto error;
2417 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002418 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002419
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002420 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002421
2422error:
2423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002424 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002425}
2426
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002427static int
Radek Krejcib8048692015-08-05 13:36:34 +02002428fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002429{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 struct lyxml_elem *child;
2431 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002432
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002433 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002434 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2435 /* garbage */
2436 continue;
2437 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 if (!strcmp(child->name, "revision-date")) {
2439 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002440 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 goto error;
2442 }
2443 GETVAL(value, child, "date");
2444 if (check_date(value, LOGLINE(child))) {
2445 goto error;
2446 }
2447 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2448 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002449 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 goto error;
2451 }
2452 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002453
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002454 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002455 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002457 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 +02002458 if (!inc->submodule) {
2459 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2460 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002461 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002462 goto error;
2463 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002464 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 /* check that belongs-to corresponds */
2467 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002468 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469 }
2470 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002471 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2472 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002473 goto error;
2474 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002475
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002476 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002477
2478error:
2479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002481}
2482
Radek Krejcida04f4a2015-05-21 12:54:09 +02002483/*
2484 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002485 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002486 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002487 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002488static int
Radek Krejcib8048692015-08-05 13:36:34 +02002489read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci76512572015-08-04 09:47:08 +02002490 struct lys_node *mnode, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002491{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002492 const char *value;
2493 struct lyxml_elem *sub, *next;
2494 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002495
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002496 if (opt & OPT_MODULE) {
2497 mnode->module = module;
2498 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 if (opt & OPT_IDENT) {
2501 GETVAL(value, xmlnode, "name");
2502 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2503 goto error;
2504 }
2505 mnode->name = lydict_insert(ctx, value, strlen(value));
2506 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002507
Radek Krejci6764bb32015-07-03 15:16:04 +02002508 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002509 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002510 mnode->nacm = parent->nacm;
2511 }
2512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002513 /* process local parameters */
2514 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002515 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002516 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002517 lyxml_free_elem(ctx, sub);
2518 continue;
2519 }
2520 if (strcmp(sub->ns->value, LY_NSYIN)) {
2521 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002522 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002523 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002524 mnode->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002525 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002526 mnode->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002527 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002528 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002529 goto error;
2530 }
2531 }
2532
2533 /* else garbage */
2534 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002535 continue;
2536 }
2537
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002538 if (!strcmp(sub->name, "description")) {
2539 if (mnode->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002540 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002541 goto error;
2542 }
2543 mnode->dsc = read_yin_subnode(ctx, sub, "text");
2544 if (!mnode->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002545 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002546 }
2547 } else if (!strcmp(sub->name, "reference")) {
2548 if (mnode->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002549 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002550 goto error;
2551 }
2552 mnode->ref = read_yin_subnode(ctx, sub, "text");
2553 if (!mnode->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002554 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 }
2556 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002557 if (mnode->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002558 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002559 goto error;
2560 }
2561 GETVAL(value, sub, "value");
2562 if (!strcmp(value, "current")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002563 mnode->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002565 mnode->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002567 mnode->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002568 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002569 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002570 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 }
2572 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002573 if (mnode->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002574 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 goto error;
2576 }
2577 GETVAL(value, sub, "value");
2578 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002579 mnode->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002581 mnode->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002582 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002583 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002584 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002585 }
2586 } else {
2587 /* skip the lyxml_free_elem */
2588 continue;
2589 }
2590 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002591 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002592
Radek Krejci1574a8d2015-08-03 14:16:52 +02002593 if ((opt & OPT_INHERIT) && !(mnode->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 /* get config flag from parent */
2595 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002596 mnode->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002597 } else {
2598 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002599 mnode->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 }
2601 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002603 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002604
2605error:
2606
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002608}
2609
Radek Krejci76512572015-08-04 09:47:08 +02002610static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002611read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002612{
Radek Krejci76512572015-08-04 09:47:08 +02002613 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002614 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002615 const char *value;
2616
2617 retval = calloc(1, sizeof *retval);
2618
2619 GETVAL(value, yin, "condition");
2620 retval->cond = lydict_insert(module->ctx, value, 0);
2621
Radek Krejci73adb602015-07-02 18:07:40 +02002622 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002623 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2624 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002625 continue;
2626 }
2627
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002628 if (!strcmp(child->name, "description")) {
2629 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002630 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002631 goto error;
2632 }
2633 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2634 if (!retval->dsc) {
2635 goto error;
2636 }
2637 } else if (!strcmp(child->name, "reference")) {
2638 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002639 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002640 goto error;
2641 }
2642 retval->ref = read_yin_subnode(module->ctx, child, "text");
2643 if (!retval->ref) {
2644 goto error;
2645 }
2646 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002647 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002648 goto error;
2649 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002650 }
2651
2652 return retval;
2653
2654error:
2655
Radek Krejci76512572015-08-04 09:47:08 +02002656 ly_mnode_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002657 return NULL;
2658}
2659
Radek Krejcib4cf2022015-06-03 14:40:05 +02002660/* additional check in case statement - the child must be unique across
2661 * all other case names and its data children
2662 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663static int
Radek Krejci76512572015-08-04 09:47:08 +02002664check_branch_id(struct lys_node *parent, struct lys_node *new, struct lys_node *excl, int line)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002665{
Radek Krejci76512572015-08-04 09:47:08 +02002666 struct lys_node *mnode, *submnode;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002667
Radek Krejci76512572015-08-04 09:47:08 +02002668 if (new->nodetype == LYS_CHOICE) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 /* we have nested choice in case, so we need recursion */
2670 LY_TREE_FOR(new->child, mnode) {
Radek Krejci76512572015-08-04 09:47:08 +02002671 if (mnode->nodetype == LYS_CASE) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002672 LY_TREE_FOR(mnode->child, submnode) {
2673 if (check_branch_id(parent, submnode, new, line)) {
2674 return EXIT_FAILURE;
2675 }
2676 }
2677 } else if (check_branch_id(parent, mnode, new, line)) {
2678 return EXIT_FAILURE;
2679 }
2680 }
2681 } else {
2682 LY_TREE_FOR(parent->child, mnode) {
2683 if (mnode == excl) {
2684 continue;
2685 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 if (!strcmp(new->name, mnode->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002688 LOGVAL(LYE_INID, line, new->name, "duplicated identifier within a choice's cases");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002689 return EXIT_FAILURE;
2690 }
Radek Krejci76512572015-08-04 09:47:08 +02002691 if (mnode->nodetype == LYS_CASE) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 LY_TREE_FOR(mnode->child, submnode) {
2693 if (!strcmp(new->name, submnode->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002694 LOGVAL(LYE_INID, line, new->name, "duplicated identifier within a choice's cases");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002695 return EXIT_FAILURE;
2696 }
2697 }
2698 }
2699 }
2700 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 return EXIT_SUCCESS;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002703}
2704
Radek Krejci76512572015-08-04 09:47:08 +02002705static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002706read_yin_case(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02002707 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002708{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002709 struct lyxml_elem *sub, *next;
Radek Krejcib8048692015-08-05 13:36:34 +02002710 struct lys_node_case *mcase;
Radek Krejci76512572015-08-04 09:47:08 +02002711 struct lys_node *retval, *mnode = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002712 int c_ftrs = 0;
2713 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002714
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002715 mcase = calloc(1, sizeof *mcase);
Radek Krejci76512572015-08-04 09:47:08 +02002716 mcase->nodetype = LYS_CASE;
2717 mcase->prev = (struct lys_node *)mcase;
2718 retval = (struct lys_node *)mcase;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002719
Radek Krejci6a113852015-07-03 16:04:20 +02002720 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002721 goto error;
2722 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002723
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")) {
2733 mnode = read_yin_container(module, retval, sub, resolve, unres);
2734 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002735 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002736 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002737 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 } else if (!strcmp(sub->name, "list")) {
2739 mnode = read_yin_list(module, retval, sub, resolve, unres);
2740 } else if (!strcmp(sub->name, "uses")) {
2741 mnode = read_yin_uses(module, retval, sub, resolve, unres);
2742 } else if (!strcmp(sub->name, "choice")) {
2743 mnode = read_yin_choice(module, retval, sub, resolve, unres);
2744 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002745 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002746 } else if (!strcmp(sub->name, "if-feature")) {
2747 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002748 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2749 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002750 } else if (!strcmp(sub->name, "when")) {
2751 if (mcase->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002752 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002753 goto error;
2754 }
2755
2756 mcase->when = read_yin_when(module, sub);
2757 if (!mcase->when) {
2758 goto error;
2759 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002760 add_unres_mnode(module, unres, mcase->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002762 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002763 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 if (!mnode) {
2767 goto error;
2768 } else if (check_branch_id(parent, mnode, mnode, LOGLINE(sub))) {
2769 goto error;
2770 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 mnode = NULL;
2773 lyxml_free_elem(module->ctx, sub);
2774 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002775
Radek Krejci3cf9e222015-06-18 11:37:50 +02002776 if (c_ftrs) {
2777 mcase->features = calloc(c_ftrs, sizeof *mcase->features);
2778 }
Radek Krejci73adb602015-07-02 18:07:40 +02002779 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002780 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002781 add_unres_str(module, unres, &mcase->features[mcase->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 }
Radek Krejcib388c152015-06-04 17:03:03 +02002783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002784 /* insert the node into the schema tree */
2785 if (ly_mnode_addchild(parent, retval)) {
2786 goto error;
2787 }
Radek Krejcib7155b52015-06-10 17:03:01 +02002788
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002789 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002790
2791error:
2792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 ly_mnode_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002796}
2797
Radek Krejci76512572015-08-04 09:47:08 +02002798static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002799read_yin_choice(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02002800 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002801{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 struct lyxml_elem *sub, *next;
2803 struct ly_ctx *const ctx = module->ctx;
Radek Krejci76512572015-08-04 09:47:08 +02002804 struct lys_node *retval, *mnode = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002805 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002806 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002807 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002809 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002810 choice->nodetype = LYS_CHOICE;
2811 choice->prev = (struct lys_node *)choice;
2812 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002813
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002814 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2815 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 goto error;
2817 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002818
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 /* process choice's specific children */
2820 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002821 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2822 /* garbage */
2823 lyxml_free_elem(module->ctx, sub);
2824 continue;
2825 }
2826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002827 if (!strcmp(sub->name, "container")) {
2828 if (!(mnode = read_yin_container(module, retval, sub, resolve, unres))) {
2829 goto error;
2830 }
2831 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002832 if (!(mnode = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002833 goto error;
2834 }
2835 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002836 if (!(mnode = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 goto error;
2838 }
2839 } else if (!strcmp(sub->name, "list")) {
2840 if (!(mnode = read_yin_list(module, retval, sub, resolve, unres))) {
2841 goto error;
2842 }
2843 } else if (!strcmp(sub->name, "case")) {
2844 if (!(mnode = read_yin_case(module, retval, sub, resolve, unres))) {
2845 goto error;
2846 }
2847 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002848 if (!(mnode = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 goto error;
2850 }
2851 } else if (!strcmp(sub->name, "default")) {
2852 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002853 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 goto error;
2855 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002856 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002857 } else if (!strcmp(sub->name, "mandatory")) {
2858 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002859 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002860 goto error;
2861 }
2862 /* just checking the flags in leaf is not sufficient, we would allow
2863 * multiple mandatory statements with the "false" value
2864 */
2865 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002866
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002867 GETVAL(value, sub, "value");
2868 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002869 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002870 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002871 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002872 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002873 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002874 goto error;
2875 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002876 } else if (!strcmp(sub->name, "when")) {
2877 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002878 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002879 goto error;
2880 }
2881
2882 choice->when = read_yin_when(module, sub);
2883 if (!choice->when) {
2884 goto error;
2885 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002886 add_unres_mnode(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002887 } else if (!strcmp(sub->name, "if-feature")) {
2888 c_ftrs++;
2889
2890 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2891 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002892 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002893 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002894 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002897 if (mnode && check_branch_id(retval, mnode, mnode, LOGLINE(sub))) {
2898 goto error;
2899 }
2900 mnode = NULL;
2901 lyxml_free_elem(ctx, sub);
2902 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002903
Radek Krejci3cf9e222015-06-18 11:37:50 +02002904 if (c_ftrs) {
2905 choice->features = calloc(c_ftrs, sizeof *choice->features);
2906 }
2907
Radek Krejci73adb602015-07-02 18:07:40 +02002908 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002909 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002910 add_unres_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002911 }
2912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002913 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002914 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002915 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002916 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2917 goto error;
2918 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 /* link default with the case */
2921 if (dflt_str) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002922 add_unres_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002925 /* insert the node into the schema tree */
2926 if (parent && ly_mnode_addchild(parent, retval)) {
2927 goto error;
2928 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002930 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002931
2932error:
2933
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002934 ly_mnode_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002937}
2938
Radek Krejci76512572015-08-04 09:47:08 +02002939static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002940read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002941 struct unres_item *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002942{
Radek Krejci76512572015-08-04 09:47:08 +02002943 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002944 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 struct lyxml_elem *sub, *next;
2946 const char *value;
2947 int r;
2948 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002949 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002950
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002951 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002952 anyxml->nodetype = LYS_ANYXML;
2953 anyxml->prev = (struct lys_node *)anyxml;
2954 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002955
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002956 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2957 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 goto error;
2959 }
Radek Krejci863c2852015-06-03 15:47:11 +02002960
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002962 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2963 /* garbage */
2964 lyxml_free_elem(module->ctx, sub);
2965 continue;
2966 }
2967
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002968 if (!strcmp(sub->name, "mandatory")) {
2969 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002970 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 goto error;
2972 }
2973 /* just checking the flags in leaf is not sufficient, we would allow
2974 * multiple mandatory statements with the "false" value
2975 */
2976 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 GETVAL(value, sub, "value");
2979 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002980 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002981 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002982 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002983 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002984 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002985 goto error;
2986 }
2987 /* else false is the default value, so we can ignore it */
2988 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002989 } else if (!strcmp(sub->name, "when")) {
2990 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002991 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002992 goto error;
2993 }
2994
2995 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002996 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002997 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002998 goto error;
2999 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003000 add_unres_mnode(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub));
3001 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003002 } else if (!strcmp(sub->name, "must")) {
3003 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003004 } else if (!strcmp(sub->name, "if-feature")) {
3005 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02003006
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003007 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003008 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 }
3011 }
Radek Krejci863c2852015-06-03 15:47:11 +02003012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 /* middle part - process nodes with cardinality of 0..n */
3014 if (c_must) {
3015 anyxml->must = calloc(c_must, sizeof *anyxml->must);
3016 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003017 if (c_ftrs) {
3018 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
3019 }
Radek Krejci863c2852015-06-03 15:47:11 +02003020
Radek Krejci73adb602015-07-02 18:07:40 +02003021 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003022 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003023 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 if (r) {
3025 goto error;
3026 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003027 add_unres_mnode(module, unres, &anyxml->must[anyxml->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci0b24d752015-07-02 15:02:27 +02003028 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003029 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003030 add_unres_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003031 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 }
Radek Krejci863c2852015-06-03 15:47:11 +02003033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 if (parent && ly_mnode_addchild(parent, retval)) {
3035 goto error;
3036 }
Radek Krejci863c2852015-06-03 15:47:11 +02003037
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003038 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02003039
3040error:
3041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003042 ly_mnode_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02003043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02003045}
3046
Radek Krejci76512572015-08-04 09:47:08 +02003047static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003048read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003049 struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003050{
Radek Krejci76512572015-08-04 09:47:08 +02003051 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003052 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003053 struct lyxml_elem *sub, *next;
3054 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003055 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003056 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003057
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02003059 leaf->nodetype = LYS_LEAF;
3060 leaf->prev = (struct lys_node *)leaf;
3061 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003062
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003063 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3064 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 goto error;
3066 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003067
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003068 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003069 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3070 /* garbage */
3071 lyxml_free_elem(module->ctx, sub);
3072 continue;
3073 }
3074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003076 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003077 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003078 goto error;
3079 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003080 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 goto error;
3082 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003083 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 } else if (!strcmp(sub->name, "default")) {
3085 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003086 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003087 goto error;
3088 }
3089 GETVAL(value, sub, "value");
3090 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003091 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003092 } else if (!strcmp(sub->name, "units")) {
3093 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003094 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003095 goto error;
3096 }
3097 GETVAL(value, sub, "name");
3098 leaf->units = lydict_insert(module->ctx, value, strlen(value));
3099 } else if (!strcmp(sub->name, "mandatory")) {
3100 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003101 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003102 goto error;
3103 }
3104 /* just checking the flags in leaf is not sufficient, we would allow
3105 * multiple mandatory statements with the "false" value
3106 */
3107 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02003108
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003109 GETVAL(value, sub, "value");
3110 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003111 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003112 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003113 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02003114 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003115 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003116 goto error;
3117 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003118 } else if (!strcmp(sub->name, "when")) {
3119 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003120 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003121 goto error;
3122 }
3123
3124 leaf->when = read_yin_when(module, sub);
3125 if (!leaf->when) {
3126 goto error;
3127 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003128 add_unres_mnode(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003129
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003131 c_must++;
3132 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003133 } else if (!strcmp(sub->name, "if-feature")) {
3134 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003135 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003137 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003138 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 lyxml_free_elem(module->ctx, sub);
3143 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003144
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003146 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003147 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 goto error;
3149 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003150 if (leaf->dflt) {
3151 add_unres_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003152 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003154 /* middle part - process nodes with cardinality of 0..n */
3155 if (c_must) {
3156 leaf->must = calloc(c_must, sizeof *leaf->must);
3157 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003158 if (c_ftrs) {
3159 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3160 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003161
Radek Krejci73adb602015-07-02 18:07:40 +02003162 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003164 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003165 if (r) {
3166 goto error;
3167 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003168 add_unres_mnode(module, unres, &leaf->must[leaf->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003169 } else if (!strcmp(sub->name, "if-feature")) {
3170 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003171 add_unres_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003174
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003175 if (parent && ly_mnode_addchild(parent, retval)) {
3176 goto error;
3177 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003178
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003180
3181error:
3182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 ly_mnode_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003185 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003186}
3187
Radek Krejci76512572015-08-04 09:47:08 +02003188static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003189read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003190 struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003191{
Radek Krejci76512572015-08-04 09:47:08 +02003192 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003193 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 struct lyxml_elem *sub, *next;
3195 const char *value;
3196 char *endptr;
3197 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003198 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003199 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003202 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003203 llist->nodetype = LYS_LEAFLIST;
3204 llist->prev = (struct lys_node *)llist;
3205 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003206
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003207 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3208 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003209 goto error;
3210 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003213 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3214 /* garbage */
3215 lyxml_free_elem(module->ctx, sub);
3216 continue;
3217 }
3218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003220 if (llist->type.der || has_type) {
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 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003224 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003227 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 } else if (!strcmp(sub->name, "units")) {
3229 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003230 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003231 goto error;
3232 }
3233 GETVAL(value, sub, "name");
3234 llist->units = lydict_insert(module->ctx, value, strlen(value));
3235 } else if (!strcmp(sub->name, "ordered-by")) {
3236 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003237 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003238 goto error;
3239 }
3240 /* just checking the flags in llist is not sufficient, we would
3241 * allow multiple ordered-by statements with the "system" value
3242 */
3243 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003244
Radek Krejci1574a8d2015-08-03 14:16:52 +02003245 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003246 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3247 * state data
3248 */
3249 lyxml_free_elem(module->ctx, sub);
3250 continue;
3251 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003252
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 GETVAL(value, sub, "value");
3254 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003255 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003256 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003257 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003259 } /* else system is the default value, so we can ignore it */
3260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003261 } else if (!strcmp(sub->name, "must")) {
3262 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003263 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003264 } else if (!strcmp(sub->name, "if-feature")) {
3265 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003266 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003268 } else if (!strcmp(sub->name, "min-elements")) {
3269 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003270 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003271 goto error;
3272 }
3273 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003274
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003275 GETVAL(value, sub, "value");
3276 while (isspace(value[0])) {
3277 value++;
3278 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 /* convert it to uint32_t */
3281 errno = 0;
3282 endptr = NULL;
3283 val = strtoul(value, &endptr, 10);
3284 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003285 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003286 goto error;
3287 }
3288 llist->min = (uint32_t) val;
3289 } else if (!strcmp(sub->name, "max-elements")) {
3290 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003291 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 goto error;
3293 }
3294 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003295
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003296 GETVAL(value, sub, "value");
3297 while (isspace(value[0])) {
3298 value++;
3299 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 /* convert it to uint32_t */
3302 errno = 0;
3303 endptr = NULL;
3304 val = strtoul(value, &endptr, 10);
3305 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003306 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 goto error;
3308 }
3309 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003310 } else if (!strcmp(sub->name, "when")) {
3311 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003312 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003313 goto error;
3314 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003315
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003316 llist->when = read_yin_when(module, sub);
3317 if (!llist->when) {
3318 goto error;
3319 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003320 add_unres_mnode(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003322 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003324 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003325
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003326 lyxml_free_elem(module->ctx, sub);
3327 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003329 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003330 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003331 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003332 goto error;
3333 }
3334 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003335 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003336 goto error;
3337 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003338
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003339 /* middle part - process nodes with cardinality of 0..n */
3340 if (c_must) {
3341 llist->must = calloc(c_must, sizeof *llist->must);
3342 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003343 if (c_ftrs) {
3344 llist->features = calloc(c_ftrs, sizeof *llist->features);
3345 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003346
Radek Krejci73adb602015-07-02 18:07:40 +02003347 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003349 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 if (r) {
3351 goto error;
3352 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003353 add_unres_mnode(module, unres, &llist->must[llist->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003354 } else if (!strcmp(sub->name, "if-feature")) {
3355 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003356 add_unres_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003357 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003360 if (parent && ly_mnode_addchild(parent, retval)) {
3361 goto error;
3362 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003364 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003365
3366error:
3367
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 ly_mnode_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003369
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003370 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003371}
3372
Radek Krejci76512572015-08-04 09:47:08 +02003373static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003374read_yin_list(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02003375 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003376{
Radek Krejci76512572015-08-04 09:47:08 +02003377 struct lys_node *retval, *mnode;
Radek Krejcib8048692015-08-05 13:36:34 +02003378 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003380 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003381 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003383 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 char *auxs;
3385 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003386
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003387 /* init */
3388 memset(&root, 0, sizeof root);
3389 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003390
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003392 list->nodetype = LYS_LIST;
3393 list->prev = (struct lys_node *)list;
3394 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003395
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003396 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3397 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003398 goto error;
3399 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 /* process list's specific children */
3402 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003403 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3404 /* garbage */
3405 lyxml_free_elem(module->ctx, sub);
3406 continue;
3407 }
3408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003409 /* data statements */
3410 if (!strcmp(sub->name, "container") ||
3411 !strcmp(sub->name, "leaf-list") ||
3412 !strcmp(sub->name, "leaf") ||
3413 !strcmp(sub->name, "list") ||
3414 !strcmp(sub->name, "choice") ||
3415 !strcmp(sub->name, "uses") ||
3416 !strcmp(sub->name, "grouping") ||
3417 !strcmp(sub->name, "anyxml")) {
3418 lyxml_unlink_elem(sub);
3419 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 /* array counters */
3422 } else if (!strcmp(sub->name, "key")) {
3423 /* check cardinality 0..1 */
3424 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003425 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 goto error;
3427 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003428
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003429 /* count the number of keys */
3430 GETVAL(value, sub, "value");
3431 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003432 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003433 while ((value = strpbrk(value, " \t\n"))) {
3434 list->keys_size++;
3435 while (isspace(*value)) {
3436 value++;
3437 }
3438 }
3439 list->keys_size++;
3440 list->keys = calloc(list->keys_size, sizeof *list->keys);
3441 } else if (!strcmp(sub->name, "unique")) {
3442 c_uniq++;
3443 lyxml_unlink_elem(sub);
3444 lyxml_add_child(&uniq, sub);
3445 } else if (!strcmp(sub->name, "typedef")) {
3446 c_tpdf++;
3447 } else if (!strcmp(sub->name, "must")) {
3448 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003449 } else if (!strcmp(sub->name, "if-feature")) {
3450 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003451
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003452 /* optional stetments */
3453 } else if (!strcmp(sub->name, "ordered-by")) {
3454 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003455 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003456 goto error;
3457 }
3458 /* just checking the flags in llist is not sufficient, we would
3459 * allow multiple ordered-by statements with the "system" value
3460 */
3461 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003462
Radek Krejci1574a8d2015-08-03 14:16:52 +02003463 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003464 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3465 * state data
3466 */
3467 lyxml_free_elem(module->ctx, sub);
3468 continue;
3469 }
Radek Krejci345ad742015-06-03 11:04:18 +02003470
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 GETVAL(value, sub, "value");
3472 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003473 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003474 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003475 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003476 goto error;
3477 }
3478 /* else system is the default value, so we can ignore it */
3479 lyxml_free_elem(module->ctx, sub);
3480 } else if (!strcmp(sub->name, "min-elements")) {
3481 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003482 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 goto error;
3484 }
3485 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003486
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003487 GETVAL(value, sub, "value");
3488 while (isspace(value[0])) {
3489 value++;
3490 }
Radek Krejci345ad742015-06-03 11:04:18 +02003491
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 /* convert it to uint32_t */
3493 errno = 0;
3494 auxs = NULL;
3495 val = strtoul(value, &auxs, 10);
3496 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003497 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 goto error;
3499 }
3500 list->min = (uint32_t) val;
3501 lyxml_free_elem(module->ctx, sub);
3502 } else if (!strcmp(sub->name, "max-elements")) {
3503 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003504 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 goto error;
3506 }
3507 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003508
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003509 GETVAL(value, sub, "value");
3510 while (isspace(value[0])) {
3511 value++;
3512 }
Radek Krejci345ad742015-06-03 11:04:18 +02003513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 /* convert it to uint32_t */
3515 errno = 0;
3516 auxs = NULL;
3517 val = strtoul(value, &auxs, 10);
3518 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003519 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 goto error;
3521 }
3522 list->max = (uint32_t) val;
3523 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003524 } else if (!strcmp(sub->name, "when")) {
3525 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003526 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003527 goto error;
3528 }
3529
3530 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003531 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003532 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003533 goto error;
3534 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003535 add_unres_mnode(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub));
3536 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003537 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003538 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003539 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003540 }
3541 }
Radek Krejci345ad742015-06-03 11:04:18 +02003542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003544 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003545 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003546 goto error;
3547 }
3548 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003549 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 goto error;
3551 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003552
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3554 if (c_tpdf) {
3555 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3556 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003557 if (c_must) {
3558 list->must = calloc(c_must, sizeof *list->must);
3559 }
3560 if (c_ftrs) {
3561 list->features = calloc(c_ftrs, sizeof *list->features);
3562 }
Radek Krejci73adb602015-07-02 18:07:40 +02003563 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003565 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 if (r) {
3568 goto error;
3569 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003570 } else if (!strcmp(sub->name, "if-feature")) {
3571 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003572 add_unres_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003573 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003574 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003575 if (r) {
3576 goto error;
3577 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003578 add_unres_mnode(module, unres, &list->must[list->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 }
3580 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003581
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 /* last part - process data nodes */
3583 LY_TREE_FOR_SAFE(root.child, next, sub) {
3584 if (!strcmp(sub->name, "container")) {
3585 mnode = read_yin_container(module, retval, sub, resolve, unres);
3586 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003587 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003588 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003589 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 } else if (!strcmp(sub->name, "list")) {
3591 mnode = read_yin_list(module, retval, sub, resolve, unres);
3592 } else if (!strcmp(sub->name, "choice")) {
3593 mnode = read_yin_choice(module, retval, sub, resolve, unres);
3594 } else if (!strcmp(sub->name, "uses")) {
3595 mnode = read_yin_uses(module, retval, sub, resolve, unres);
3596 } else if (!strcmp(sub->name, "grouping")) {
3597 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
3598 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003599 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003600 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 if (!mnode) {
3602 goto error;
3603 }
Radek Krejci73adb602015-07-02 18:07:40 +02003604
3605 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003606 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003607
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003608 if (parent && ly_mnode_addchild(parent, retval)) {
3609 goto error;
3610 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 if (!key_str) {
3613 /* config false list without a key */
3614 return retval;
3615 }
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003616 add_unres_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line);
Radek Krejci812b10a2015-05-28 16:48:25 +02003617
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003618 /* process unique statements */
3619 if (c_uniq) {
3620 list->unique = calloc(c_uniq, sizeof *list->unique);
3621 }
3622 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003623 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003624 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003625 GETVAL(value, sub, "tag");
3626 add_unres_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value, LOGLINE(sub));
Radek Krejci1e9b9992015-06-04 17:57:04 +02003627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003628 lyxml_free_elem(module->ctx, sub);
3629 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003630
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003632
3633error:
3634
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 ly_mnode_free(retval);
3636 while (root.child) {
3637 lyxml_free_elem(module->ctx, root.child);
3638 }
3639 while (uniq.child) {
3640 lyxml_free_elem(module->ctx, uniq.child);
3641 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003642
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003644}
3645
Radek Krejci76512572015-08-04 09:47:08 +02003646static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003647read_yin_container(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02003648 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003649{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 struct lyxml_elem *sub, *next, root;
Radek Krejci76512572015-08-04 09:47:08 +02003651 struct lys_node *mnode = NULL;
3652 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003653 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 const char *value;
3655 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003656 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003658 /* init */
3659 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003660
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003661 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003662 cont->nodetype = LYS_CONTAINER;
3663 cont->prev = (struct lys_node *)cont;
3664 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003665
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003666 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3667 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003668 goto error;
3669 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 /* process container's specific children */
3672 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003673 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003674 /* garbage */
3675 lyxml_free_elem(module->ctx, sub);
3676 continue;
3677 }
3678
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003679 if (!strcmp(sub->name, "presence")) {
3680 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003681 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 goto error;
3683 }
3684 GETVAL(value, sub, "value");
3685 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003686
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003687 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003688 } else if (!strcmp(sub->name, "when")) {
3689 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003690 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003691 goto error;
3692 }
3693
3694 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003695 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003696 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003697 goto error;
3698 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003699 add_unres_mnode(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub));
3700 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 /* data statements */
3703 } else if (!strcmp(sub->name, "container") ||
3704 !strcmp(sub->name, "leaf-list") ||
3705 !strcmp(sub->name, "leaf") ||
3706 !strcmp(sub->name, "list") ||
3707 !strcmp(sub->name, "choice") ||
3708 !strcmp(sub->name, "uses") ||
3709 !strcmp(sub->name, "grouping") ||
3710 !strcmp(sub->name, "anyxml")) {
3711 lyxml_unlink_elem(sub);
3712 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003713
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 /* array counters */
3715 } else if (!strcmp(sub->name, "typedef")) {
3716 c_tpdf++;
3717 } else if (!strcmp(sub->name, "must")) {
3718 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003719 } else if (!strcmp(sub->name, "if-feature")) {
3720 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003721 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003722 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003723 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 }
3725 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003727 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3728 if (c_tpdf) {
3729 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3730 }
3731 if (c_must) {
3732 cont->must = calloc(c_must, sizeof *cont->must);
3733 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003734 if (c_ftrs) {
3735 cont->features = calloc(c_ftrs, sizeof *cont->features);
3736 }
Radek Krejci800af702015-06-02 13:46:01 +02003737
Radek Krejci73adb602015-07-02 18:07:40 +02003738 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003740 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003741 if (r) {
3742 goto error;
3743 }
3744 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003745 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 if (r) {
3747 goto error;
3748 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003749 add_unres_mnode(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003750 } else if (!strcmp(sub->name, "if-feature")) {
3751 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003752 add_unres_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003753 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003754 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003755
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 /* last part - process data nodes */
3757 LY_TREE_FOR_SAFE(root.child, next, sub) {
3758 if (!strcmp(sub->name, "container")) {
3759 mnode = read_yin_container(module, retval, sub, resolve, unres);
3760 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003761 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003763 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003764 } else if (!strcmp(sub->name, "list")) {
3765 mnode = read_yin_list(module, retval, sub, resolve, unres);
3766 } else if (!strcmp(sub->name, "choice")) {
3767 mnode = read_yin_choice(module, retval, sub, resolve, unres);
3768 } else if (!strcmp(sub->name, "uses")) {
3769 mnode = read_yin_uses(module, retval, sub, resolve, unres);
3770 } else if (!strcmp(sub->name, "grouping")) {
3771 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
3772 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003773 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003774 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003775 if (!mnode) {
3776 goto error;
3777 }
Radek Krejci73adb602015-07-02 18:07:40 +02003778
3779 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003780 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003782 if (parent && ly_mnode_addchild(parent, retval)) {
3783 goto error;
3784 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003786 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003787
3788error:
3789
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 ly_mnode_free(retval);
3791 while (root.child) {
3792 lyxml_free_elem(module->ctx, root.child);
3793 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003796}
3797
Radek Krejci76512572015-08-04 09:47:08 +02003798static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003799read_yin_grouping(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02003800 struct lys_node *parent, struct lyxml_elem *node, int resolve, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003801{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003802 struct lyxml_elem *sub, *next, root;
Radek Krejci76512572015-08-04 09:47:08 +02003803 struct lys_node *mnode = NULL;
3804 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003805 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003806 int r;
3807 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 /* init */
3810 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003812 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003813 grp->nodetype = LYS_GROUPING;
3814 grp->prev = (struct lys_node *)grp;
3815 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003816
Radek Krejci6a113852015-07-03 16:04:20 +02003817 if (read_yin_common(module, parent, retval, node, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 goto error;
3819 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003820
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003821 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003822 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3823 /* garbage */
3824 lyxml_free_elem(module->ctx, sub);
3825 continue;
3826 }
3827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003828 /* data statements */
3829 if (!strcmp(sub->name, "container") ||
3830 !strcmp(sub->name, "leaf-list") ||
3831 !strcmp(sub->name, "leaf") ||
3832 !strcmp(sub->name, "list") ||
3833 !strcmp(sub->name, "choice") ||
3834 !strcmp(sub->name, "uses") ||
3835 !strcmp(sub->name, "grouping") ||
3836 !strcmp(sub->name, "anyxml")) {
3837 lyxml_unlink_elem(sub);
3838 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003840 /* array counters */
3841 } else if (!strcmp(sub->name, "typedef")) {
3842 c_tpdf++;
3843 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003844 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003845 goto error;
3846 }
3847 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003849 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3850 if (c_tpdf) {
3851 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3852 }
Radek Krejci73adb602015-07-02 18:07:40 +02003853 LY_TREE_FOR(node->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003854 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003855
Radek Krejci73adb602015-07-02 18:07:40 +02003856 if (r) {
3857 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003858 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003859 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003860
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003861 /* last part - process data nodes */
3862 LY_TREE_FOR_SAFE(root.child, next, sub) {
3863 if (!strcmp(sub->name, "container")) {
3864 mnode = read_yin_container(module, retval, sub, resolve, unres);
3865 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003866 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003867 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003868 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003869 } else if (!strcmp(sub->name, "list")) {
3870 mnode = read_yin_list(module, retval, sub, resolve, unres);
3871 } else if (!strcmp(sub->name, "choice")) {
3872 mnode = read_yin_choice(module, retval, sub, resolve, unres);
3873 } else if (!strcmp(sub->name, "uses")) {
3874 mnode = read_yin_uses(module, retval, sub, resolve, unres);
3875 } else if (!strcmp(sub->name, "grouping")) {
3876 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
3877 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003878 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003880 if (!mnode) {
3881 goto error;
3882 }
Radek Krejci73adb602015-07-02 18:07:40 +02003883
3884 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003885 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003886
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003887 if (parent && ly_mnode_addchild(parent, retval)) {
3888 goto error;
3889 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003891 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003892
3893error:
3894
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003895 ly_mnode_free(retval);
3896 while (root.child) {
3897 lyxml_free_elem(module->ctx, root.child);
3898 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003899
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003901}
3902
Radek Krejci76512572015-08-04 09:47:08 +02003903static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003904read_yin_input_output(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02003905 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003906{
Radek Krejcie0674f82015-06-15 13:58:51 +02003907 struct lyxml_elem *sub, *next, root;
Radek Krejci76512572015-08-04 09:47:08 +02003908 struct lys_node *mnode = NULL;
3909 struct lys_node *retval;
Radek Krejci4608ada2015-08-05 16:04:37 +02003910 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003911 int r;
3912 int c_tpdf = 0;
3913
Radek Krejcie0674f82015-06-15 13:58:51 +02003914 /* init */
3915 memset(&root, 0, sizeof root);
3916
Michal Vasko38d01f72015-06-15 09:41:06 +02003917 inout = calloc(1, sizeof *inout);
3918
3919 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003920 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003921 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003922 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003923 } else {
3924 assert(0);
3925 }
3926
Radek Krejci76512572015-08-04 09:47:08 +02003927 inout->prev = (struct lys_node *)inout;
3928 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003929
Radek Krejci6a113852015-07-03 16:04:20 +02003930 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003931 goto error;
3932 }
3933
Michal Vasko38d01f72015-06-15 09:41:06 +02003934 /* data statements */
3935 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003936 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3937 /* garbage */
3938 lyxml_free_elem(module->ctx, sub);
3939 continue;
3940 }
3941
Michal Vasko38d01f72015-06-15 09:41:06 +02003942 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003943 !strcmp(sub->name, "leaf-list") ||
3944 !strcmp(sub->name, "leaf") ||
3945 !strcmp(sub->name, "list") ||
3946 !strcmp(sub->name, "choice") ||
3947 !strcmp(sub->name, "uses") ||
3948 !strcmp(sub->name, "grouping") ||
3949 !strcmp(sub->name, "anyxml")) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003950 lyxml_unlink_elem(sub);
3951 lyxml_add_child(&root, sub);
3952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003953 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003954 } else if (!strcmp(sub->name, "typedef")) {
3955 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003956
Michal Vasko38d01f72015-06-15 09:41:06 +02003957 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003958 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003959 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003960 }
3961 }
3962
3963 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3964 if (c_tpdf) {
3965 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3966 }
3967
Radek Krejci73adb602015-07-02 18:07:40 +02003968 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003969 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003970
Radek Krejci73adb602015-07-02 18:07:40 +02003971 if (r) {
3972 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003973 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003974 }
3975
3976 /* last part - process data nodes */
3977 LY_TREE_FOR_SAFE(root.child, next, sub) {
3978 if (!strcmp(sub->name, "container")) {
3979 mnode = read_yin_container(module, retval, sub, resolve, unres);
3980 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003981 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003982 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003983 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003984 } else if (!strcmp(sub->name, "list")) {
3985 mnode = read_yin_list(module, retval, sub, resolve, unres);
3986 } else if (!strcmp(sub->name, "choice")) {
3987 mnode = read_yin_choice(module, retval, sub, resolve, unres);
3988 } else if (!strcmp(sub->name, "uses")) {
3989 mnode = read_yin_uses(module, retval, sub, resolve, unres);
3990 } else if (!strcmp(sub->name, "grouping")) {
3991 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
3992 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003993 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003994 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003995 if (!mnode) {
3996 goto error;
3997 }
Radek Krejci73adb602015-07-02 18:07:40 +02003998
3999 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004000 }
4001
4002 if (parent && ly_mnode_addchild(parent, retval)) {
4003 goto error;
4004 }
4005
4006 return retval;
4007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004008error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004009
4010 ly_mnode_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004011 while (root.child) {
4012 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004013 }
4014
4015 return NULL;
4016}
4017
Radek Krejci76512572015-08-04 09:47:08 +02004018static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02004019read_yin_notif(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02004020 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02004021{
Michal Vaskoc6551b32015-06-16 10:51:43 +02004022 struct lyxml_elem *sub, *next, root;
Radek Krejci76512572015-08-04 09:47:08 +02004023 struct lys_node *mnode = NULL;
4024 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004025 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004026 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02004027 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004028 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02004029
Michal Vaskoc6551b32015-06-16 10:51:43 +02004030 memset(&root, 0, sizeof root);
4031
Michal Vasko0ea41032015-06-16 08:53:55 +02004032 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02004033 notif->nodetype = LYS_NOTIF;
4034 notif->prev = (struct lys_node *)notif;
4035 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02004036
Radek Krejci6a113852015-07-03 16:04:20 +02004037 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004038 goto error;
4039 }
4040
4041 /* process rpc's specific children */
4042 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004043 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4044 /* garbage */
4045 lyxml_free_elem(module->ctx, sub);
4046 continue;
4047 }
4048
Michal Vasko0ea41032015-06-16 08:53:55 +02004049 /* data statements */
4050 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004051 !strcmp(sub->name, "leaf-list") ||
4052 !strcmp(sub->name, "leaf") ||
4053 !strcmp(sub->name, "list") ||
4054 !strcmp(sub->name, "choice") ||
4055 !strcmp(sub->name, "uses") ||
4056 !strcmp(sub->name, "grouping") ||
4057 !strcmp(sub->name, "anyxml")) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004058 lyxml_unlink_elem(sub);
4059 lyxml_add_child(&root, sub);
4060
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004061 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02004062 } else if (!strcmp(sub->name, "typedef")) {
4063 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004064 } else if (!strcmp(sub->name, "if-feature")) {
4065 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02004066 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004067 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02004068 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02004069 }
4070 }
4071
4072 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4073 if (c_tpdf) {
4074 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
4075 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004076 if (c_ftrs) {
4077 notif->features = calloc(c_ftrs, sizeof *notif->features);
4078 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004079
Radek Krejci73adb602015-07-02 18:07:40 +02004080 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004081 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004082 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004083
4084 if (r) {
4085 goto error;
4086 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004087 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004088 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004089 add_unres_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko0ea41032015-06-16 08:53:55 +02004090 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004091 }
4092
4093 /* last part - process data nodes */
4094 LY_TREE_FOR_SAFE(root.child, next, sub) {
4095 if (!strcmp(sub->name, "container")) {
4096 mnode = read_yin_container(module, retval, sub, resolve, unres);
4097 } else if (!strcmp(sub->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004098 mnode = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004099 } else if (!strcmp(sub->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004100 mnode = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004101 } else if (!strcmp(sub->name, "list")) {
4102 mnode = read_yin_list(module, retval, sub, resolve, unres);
4103 } else if (!strcmp(sub->name, "choice")) {
4104 mnode = read_yin_choice(module, retval, sub, resolve, unres);
4105 } else if (!strcmp(sub->name, "uses")) {
4106 mnode = read_yin_uses(module, retval, sub, resolve, unres);
4107 } else if (!strcmp(sub->name, "grouping")) {
4108 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
4109 } else if (!strcmp(sub->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004110 mnode = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004111 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004112 if (!mnode) {
4113 goto error;
4114 }
Radek Krejci73adb602015-07-02 18:07:40 +02004115
4116 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004117 }
4118
4119 if (parent && ly_mnode_addchild(parent, retval)) {
4120 goto error;
4121 }
4122
4123 return retval;
4124
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004125error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004126
4127 ly_mnode_free(retval);
4128 while (root.child) {
4129 lyxml_free_elem(module->ctx, root.child);
4130 }
4131
4132 return NULL;
4133}
4134
Radek Krejci76512572015-08-04 09:47:08 +02004135static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02004136read_yin_rpc(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02004137 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_item *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004138{
Radek Krejcie0674f82015-06-15 13:58:51 +02004139 struct lyxml_elem *sub, *next, root;
Radek Krejci76512572015-08-04 09:47:08 +02004140 struct lys_node *mnode = NULL;
4141 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004142 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004143 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004144 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004145 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004146
Radek Krejcie0674f82015-06-15 13:58:51 +02004147 /* init */
4148 memset(&root, 0, sizeof root);
4149
Michal Vasko38d01f72015-06-15 09:41:06 +02004150 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004151 rpc->nodetype = LYS_RPC;
4152 rpc->prev = (struct lys_node *)rpc;
4153 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004154
Radek Krejci6a113852015-07-03 16:04:20 +02004155 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004156 goto error;
4157 }
4158
4159 /* process rpc's specific children */
4160 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004161 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4162 /* garbage */
4163 lyxml_free_elem(module->ctx, sub);
4164 continue;
4165 }
4166
Michal Vasko38d01f72015-06-15 09:41:06 +02004167 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004168 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004169 && (rpc->child->nodetype == LYS_INPUT
4170 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004171 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004172 goto error;
4173 }
4174 lyxml_unlink_elem(sub);
4175 lyxml_add_child(&root, sub);
4176 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004178 && (rpc->child->nodetype == LYS_INPUT
4179 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004180 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004181 goto error;
4182 }
4183 lyxml_unlink_elem(sub);
4184 lyxml_add_child(&root, sub);
4185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004186 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004187 } else if (!strcmp(sub->name, "grouping")) {
4188 lyxml_unlink_elem(sub);
4189 lyxml_add_child(&root, sub);
4190
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004191 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004192 } else if (!strcmp(sub->name, "typedef")) {
4193 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004194 } else if (!strcmp(sub->name, "if-feature")) {
4195 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004196 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004197 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004198 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004199 }
4200 }
4201
4202 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4203 if (c_tpdf) {
4204 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4205 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004206 if (c_ftrs) {
4207 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4208 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004209
Radek Krejci73adb602015-07-02 18:07:40 +02004210 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004211 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004212 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004213
4214 if (r) {
4215 goto error;
4216 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004217 } else if (!strcmp(sub->name, "if-feature")) {
4218 GETVAL(value, sub, "name");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004219 add_unres_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko38d01f72015-06-15 09:41:06 +02004220 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004221 }
4222
4223 /* last part - process data nodes */
4224 LY_TREE_FOR_SAFE(root.child, next, sub) {
4225 if (!strcmp(sub->name, "grouping")) {
4226 mnode = read_yin_grouping(module, retval, sub, resolve, unres);
4227 } else if (!strcmp(sub->name, "input")) {
4228 mnode = read_yin_input_output(module, retval, sub, resolve, unres);
4229 } else if (!strcmp(sub->name, "output")) {
4230 mnode = read_yin_input_output(module, retval, sub, resolve, unres);
4231 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004232 if (!mnode) {
4233 goto error;
4234 }
Radek Krejci73adb602015-07-02 18:07:40 +02004235
4236 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004237 }
4238
4239 if (parent && ly_mnode_addchild(parent, retval)) {
4240 goto error;
4241 }
4242
4243 return retval;
4244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004245error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004246
4247 ly_mnode_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004248 while (root.child) {
4249 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004250 }
4251
4252 return NULL;
4253}
4254
Radek Krejci74705112015-06-05 10:25:44 +02004255/*
4256 * resolve - referenced grouping should be bounded to the namespace (resolved)
4257 * only when uses does not appear in grouping. In a case of grouping's uses,
4258 * we just get information but we do not apply augment or refine to it.
4259 */
Radek Krejci76512572015-08-04 09:47:08 +02004260static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02004261read_yin_uses(struct lys_module *module,
Radek Krejci76512572015-08-04 09:47:08 +02004262 struct lys_node *parent, struct lyxml_elem *node, int resolve, struct unres_item *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004263{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004264 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004265 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004266 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004267 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004268 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004269 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004270
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004271 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004272 uses->nodetype = LYS_USES;
4273 uses->prev = (struct lys_node *)uses;
4274 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004275
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 GETVAL(value, node, "name");
4277 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004278
Radek Krejci6a113852015-07-03 16:04:20 +02004279 if (read_yin_common(module, parent, retval, node, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004280 goto error;
4281 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 /* get other properties of uses */
4284 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004285 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4286 /* garbage */
4287 lyxml_free_elem(module->ctx, sub);
4288 continue;
4289 }
4290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004291 if (!strcmp(sub->name, "refine")) {
4292 c_ref++;
4293 } else if (!strcmp(sub->name, "augment")) {
4294 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004295 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004296 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004297 } else if (!strcmp(sub->name, "when")) {
4298 if (uses->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004299 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, node->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004300 goto error;
4301 }
4302
4303 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004304 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004305 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004306 goto error;
4307 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004308 add_unres_mnode(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub));
4309 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004310 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004311 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004312 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004313 }
4314 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004315
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004316 /* process properties with cardinality 0..n */
4317 if (c_ref) {
4318 uses->refine = calloc(c_ref, sizeof *uses->refine);
4319 }
4320 if (c_aug) {
4321 uses->augment = calloc(c_aug, sizeof *uses->augment);
4322 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004323 if (c_ftrs) {
4324 uses->features = calloc(c_ftrs, sizeof *uses->features);
4325 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004326
Radek Krejci73adb602015-07-02 18:07:40 +02004327 LY_TREE_FOR(node->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004328 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004329 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4330 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004331 goto error;
4332 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004333 } else if (!strcmp(sub->name, "augment")) {
4334 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4335 if (r) {
4336 goto error;
4337 }
4338 } else if (!strcmp(sub->name, "if-feature")) {
4339 GETVAL(value, sub, "name");
4340 add_unres_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 }
4342 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004343
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004344 add_unres_mnode(module, unres, uses, UNRES_USES, NULL, LOGLINE(node));
Radek Krejci74705112015-06-05 10:25:44 +02004345
Radek Krejci368c38f2015-06-15 15:09:55 +02004346 if (parent && ly_mnode_addchild(parent, retval)) {
4347 goto error;
4348 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 if (resolve) {
4351 /* inherit config flag */
4352 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004353 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 } else {
4355 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004356 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004357 }
4358 }
Radek Krejcib388c152015-06-04 17:03:03 +02004359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004361
4362error:
4363
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004364 ly_mnode_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004367}
4368
Radek Krejciefaeba32015-05-27 14:30:57 +02004369/* common code for yin_read_module() and yin_read_submodule() */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370static int
Radek Krejcib8048692015-08-05 13:36:34 +02004371read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_item *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004372{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004374 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004375 struct lyxml_elem *next, *node, *child, root, grps, rpcs, notifs;
Radek Krejci76512572015-08-04 09:47:08 +02004376 struct lys_node *mnode = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004377 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004378 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004380 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004381 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 +02004382
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004383 /* init */
4384 memset(&root, 0, sizeof root);
4385 memset(&grps, 0, sizeof grps);
4386 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004387 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004389 /*
4390 * in the first run, we process elements with cardinality of 1 or 0..1 and
4391 * count elements with cardinality 0..n. Data elements (choices, containers,
4392 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4393 * need have all top-level and groupings already prepared at that time. In
4394 * the middle loop, we process other elements with carinality of 0..n since
4395 * we need to allocate arrays to store them.
4396 */
4397 LY_TREE_FOR_SAFE(yin->child, next, node) {
4398 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004399 /* garbage */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 lyxml_free_elem(ctx, node);
4401 continue;
4402 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004403
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 if (!module->type && !strcmp(node->name, "namespace")) {
4405 if (module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004406 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 goto error;
4408 }
4409 GETVAL(value, node, "uri");
4410 module->ns = lydict_insert(ctx, value, strlen(value));
4411 lyxml_free_elem(ctx, node);
4412 } else if (!module->type && !strcmp(node->name, "prefix")) {
4413 if (module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004414 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004415 goto error;
4416 }
4417 GETVAL(value, node, "value");
4418 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(node), module, NULL)) {
4419 goto error;
4420 }
4421 module->prefix = lydict_insert(ctx, value, strlen(value));
4422 lyxml_free_elem(ctx, node);
4423 } else if (module->type && !strcmp(node->name, "belongs-to")) {
4424 if (belongsto_flag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004425 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004426 goto error;
4427 }
4428 belongsto_flag = 1;
4429 GETVAL(value, node, "module");
4430 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004431 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 }
4433 if (value != submodule->belongsto->name) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004434 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004435 goto error;
4436 }
Radek Krejcif3886932015-06-04 17:36:06 +02004437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 /* get the prefix substatement, start with checks */
4439 if (!node->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004440 LOGVAL(LYE_MISSSTMT2, LOGLINE(node), "prefix", node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004441 goto error;
4442 } else if (strcmp(node->child->name, "prefix")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004443 LOGVAL(LYE_INSTMT, LOGLINE(node->child), node->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 goto error;
4445 } else if (node->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004446 LOGVAL(LYE_INSTMT, LOGLINE(node->child->next), node->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004447 goto error;
4448 }
4449 /* and now finally get the value */
4450 GETVAL(value, node->child, "value");
4451 /* check here differs from a generic prefix check, since this prefix
4452 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004453 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(node->child), NULL, NULL)) {
4455 goto error;
4456 }
4457 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004458
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004459 /* we are done with belongs-to */
4460 lyxml_free_elem(ctx, node);
Radek Krejcieb00f512015-07-01 16:44:58 +02004461
4462 /* counters (statements with n..1 cardinality) */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004463 } else if (!strcmp(node->name, "import")) {
4464 c_imp++;
4465 } else if (!strcmp(node->name, "revision")) {
4466 c_rev++;
4467 } else if (!strcmp(node->name, "typedef")) {
4468 c_tpdf++;
4469 } else if (!strcmp(node->name, "identity")) {
4470 c_ident++;
4471 } else if (!strcmp(node->name, "include")) {
4472 c_inc++;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004473 } else if (!strcmp(node->name, "augment")) {
4474 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004475 } else if (!strcmp(node->name, "feature")) {
4476 c_ftrs++;
Radek Krejcieb00f512015-07-01 16:44:58 +02004477 } else if (!strcmp(node->name, "deviation")) {
4478 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004479
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004480 /* data statements */
4481 } else if (!strcmp(node->name, "container") ||
4482 !strcmp(node->name, "leaf-list") ||
4483 !strcmp(node->name, "leaf") ||
4484 !strcmp(node->name, "list") ||
4485 !strcmp(node->name, "choice") ||
4486 !strcmp(node->name, "uses") ||
4487 !strcmp(node->name, "anyxml")) {
4488 lyxml_unlink_elem(node);
4489 lyxml_add_child(&root, node);
4490 } else if (!strcmp(node->name, "grouping")) {
4491 /* keep groupings separated and process them before other data statements */
4492 lyxml_unlink_elem(node);
4493 lyxml_add_child(&grps, node);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004495 /* optional statements */
4496 } else if (!strcmp(node->name, "description")) {
4497 if (module->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004498 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004499 goto error;
4500 }
4501 module->dsc = read_yin_subnode(ctx, node, "text");
4502 lyxml_free_elem(ctx, node);
4503 if (!module->dsc) {
4504 goto error;
4505 }
4506 } else if (!strcmp(node->name, "reference")) {
4507 if (module->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004508 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004509 goto error;
4510 }
4511 module->ref = read_yin_subnode(ctx, node, "text");
4512 lyxml_free_elem(ctx, node);
4513 if (!module->ref) {
4514 goto error;
4515 }
4516 } else if (!strcmp(node->name, "organization")) {
4517 if (module->org) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004518 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004519 goto error;
4520 }
4521 module->org = read_yin_subnode(ctx, node, "text");
4522 lyxml_free_elem(ctx, node);
4523 if (!module->org) {
4524 goto error;
4525 }
4526 } else if (!strcmp(node->name, "contact")) {
4527 if (module->contact) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004528 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004529 goto error;
4530 }
4531 module->contact = read_yin_subnode(ctx, node, "text");
4532 lyxml_free_elem(ctx, node);
4533 if (!module->contact) {
4534 goto error;
4535 }
4536 } else if (!strcmp(node->name, "yang-version")) {
4537 /* TODO: support YANG 1.1 ? */
4538 if (module->version) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004539 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 goto error;
4541 }
4542 GETVAL(value, node, "value");
4543 if (strcmp(value, "1")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004544 LOGVAL(LYE_INARG, LOGLINE(node), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004545 goto error;
4546 }
4547 module->version = 1;
4548 lyxml_free_elem(ctx, node);
Michal Vasko38d01f72015-06-15 09:41:06 +02004549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 /* rpcs & notifications */
Michal Vasko38d01f72015-06-15 09:41:06 +02004551 } else if (!strcmp(node->name, "rpc")) {
4552 lyxml_unlink_elem(node);
4553 lyxml_add_child(&rpcs, node);
Michal Vasko0ea41032015-06-16 08:53:55 +02004554 } else if (!strcmp(node->name, "notification")) {
4555 lyxml_unlink_elem(node);
4556 lyxml_add_child(&notifs, node);
Radek Krejci5166a892015-07-02 16:44:24 +02004557
4558 } else if (!strcmp(node->name, "extension")) {
4559 GETVAL(value, node, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004560
Radek Krejci6764bb32015-07-03 15:16:04 +02004561 /* we have 2 supported (hardcoded) extensions:
4562 * NACM's default-deny-write and default-deny-all
4563 */
4564 if (strcmp(module->ns, LY_NSNACM) ||
4565 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4566 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
4567 lyxml_free_elem(ctx, node);
4568 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004570 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004571 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 }
4573 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575 if (!submodule) {
4576 /* check for mandatory statements */
4577 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004578 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004579 goto error;
4580 }
4581 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004582 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004583 goto error;
4584 }
4585 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004587 /* allocate arrays for elements with cardinality of 0..n */
4588 if (c_imp) {
4589 module->imp = calloc(c_imp, sizeof *module->imp);
4590 }
4591 if (c_rev) {
4592 module->rev = calloc(c_rev, sizeof *module->rev);
4593 }
4594 if (c_tpdf) {
4595 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4596 }
4597 if (c_ident) {
4598 module->ident = calloc(c_ident, sizeof *module->ident);
4599 }
4600 if (c_inc) {
4601 module->inc = calloc(c_inc, sizeof *module->inc);
4602 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004603 if (c_aug) {
4604 module->augment = calloc(c_aug, sizeof *module->augment);
4605 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004606 if (c_ftrs) {
4607 module->features = calloc(c_ftrs, sizeof *module->features);
4608 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004609 if (c_dev) {
4610 module->deviation = calloc(c_dev, sizeof *module->deviation);
4611 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004612
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004613 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci73adb602015-07-02 18:07:40 +02004614 LY_TREE_FOR(yin->child, node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 if (!strcmp(node->name, "import")) {
4616 r = fill_yin_import(module, node, &module->imp[module->imp_size]);
4617 module->imp_size++;
4618 if (r) {
4619 goto error;
4620 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004621
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004622 /* check duplicities in imported modules */
4623 for (i = 0; i < module->imp_size - 1; i++) {
4624 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004625 LOGVAL(LYE_SPEC, LOGLINE(node), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004626 goto error;
4627 }
4628 }
4629 } else if (!strcmp(node->name, "include")) {
4630 r = fill_yin_include(module, node, &module->inc[module->inc_size]);
4631 module->inc_size++;
4632 if (r) {
4633 goto error;
4634 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004636 /* check duplications in include submodules */
4637 for (i = 0; i < module->inc_size - 1; i++) {
4638 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004639 LOGVAL(LYE_SPEC, LOGLINE(node), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004640 module->inc[i].submodule->name);
4641 goto error;
4642 }
4643 }
4644 } else if (!strcmp(node->name, "revision")) {
4645 GETVAL(value, node, "date");
4646 if (check_date(value, LOGLINE(node))) {
4647 goto error;
4648 }
4649 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4650 /* check uniqueness of the revision date - not required by RFC */
4651 for (i = 0; i < module->rev_size; i++) {
4652 if (!strcmp(value, module->rev[i].date)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004653 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
4654 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 }
4656 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004657
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004658 LY_TREE_FOR(node->child, child) {
4659 if (!strcmp(child->name, "description")) {
4660 if (module->rev[module->rev_size].dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004661 LOGVAL(LYE_TOOMANY, LOGLINE(node), child->name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 goto error;
4663 }
4664 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child, "text");
4665 if (!module->rev[module->rev_size].dsc) {
4666 goto error;
4667 }
4668 } else if (!strcmp(child->name, "reference")) {
4669 if (module->rev[module->rev_size].ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004670 LOGVAL(LYE_TOOMANY, LOGLINE(node), child->name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004671 goto error;
4672 }
4673 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child, "text");
4674 if (!module->rev[module->rev_size].ref) {
4675 goto error;
4676 }
4677 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004678 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004679 goto error;
4680 }
4681 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004683 /* keep the latest revision at position 0 */
4684 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4685 /* switch their position */
4686 value = strdup(module->rev[0].date);
4687 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4688 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4689 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004690
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004691 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4692 value = module->rev[0].dsc;
4693 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4694 module->rev[module->rev_size].dsc = value;
4695 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004696
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4698 value = module->rev[0].ref;
4699 module->rev[0].ref = module->rev[module->rev_size].ref;
4700 module->rev[module->rev_size].ref = value;
4701 }
4702 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004703
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004704 module->rev_size++;
4705 } else if (!strcmp(node->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004706 r = fill_yin_typedef(module, NULL, node, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004707 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004708
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004709 if (r) {
4710 goto error;
4711 }
4712 } else if (!strcmp(node->name, "identity")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004713 r = fill_yin_identity(module, node, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004714 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 if (r) {
4717 goto error;
4718 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004719 } else if (!strcmp(node->name, "feature")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004720 r = fill_yin_feature(module, node, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004721 module->features_size++;
4722
4723 if (r) {
4724 goto error;
4725 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004726 } else if (!strcmp(node->name, "augment")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004727 r = fill_yin_augment(module, NULL, node, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004728 module->augment_size++;
4729
4730 if (r) {
4731 goto error;
4732 }
4733
4734 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4735 continue;
Radek Krejcieb00f512015-07-01 16:44:58 +02004736 } else if (!strcmp(node->name, "deviation")) {
4737 r = fill_yin_deviation(module, node, &module->deviation[module->deviation_size]);
4738 module->deviation_size++;
4739
4740 if (r) {
4741 goto error;
4742 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004743 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004745
Radek Krejcif5be10f2015-06-16 13:29:36 +02004746 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 * refer to them
4748 */
4749 LY_TREE_FOR_SAFE(grps.child, next, node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004750 mnode = read_yin_grouping(module, NULL, node, 0, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 if (!mnode) {
4752 goto error;
4753 }
Radek Krejci74705112015-06-05 10:25:44 +02004754
Radek Krejci73adb602015-07-02 18:07:40 +02004755 lyxml_free_elem(ctx, node);
4756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 /* include data element */
4758 if (module->data) {
4759 module->data->prev->next = mnode;
4760 mnode->prev = module->data->prev;
4761 module->data->prev = mnode;
4762 } else {
4763 module->data = mnode;
4764 }
4765 }
Radek Krejci74705112015-06-05 10:25:44 +02004766
Radek Krejcif5be10f2015-06-16 13:29:36 +02004767 /* parse data nodes, ... */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004768 LY_TREE_FOR_SAFE(root.child, next, node) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 if (!strcmp(node->name, "container")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004771 mnode = read_yin_container(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004772 } else if (!strcmp(node->name, "leaf-list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004773 mnode = read_yin_leaflist(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 } else if (!strcmp(node->name, "leaf")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004775 mnode = read_yin_leaf(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 } else if (!strcmp(node->name, "list")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004777 mnode = read_yin_list(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 } else if (!strcmp(node->name, "choice")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004779 mnode = read_yin_choice(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 } else if (!strcmp(node->name, "uses")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004781 mnode = read_yin_uses(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 } else if (!strcmp(node->name, "anyxml")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004783 mnode = read_yin_anyxml(module, NULL, node, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004784 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004785 if (!mnode) {
4786 goto error;
4787 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004788
Radek Krejci73adb602015-07-02 18:07:40 +02004789 lyxml_free_elem(ctx, node);
4790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 /* include data element */
4792 if (module->data) {
4793 module->data->prev->next = mnode;
4794 mnode->prev = module->data->prev;
4795 module->data->prev = mnode;
4796 } else {
4797 module->data = mnode;
4798 }
4799 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004800
4801 /* ... rpcs ... */
4802 LY_TREE_FOR_SAFE(rpcs.child, next, node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004803 mnode = read_yin_rpc(module, NULL, node, 0, unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004804 if (!mnode) {
4805 goto error;
4806 }
4807
Radek Krejci73adb602015-07-02 18:07:40 +02004808 lyxml_free_elem(ctx, node);
4809
Radek Krejcif5be10f2015-06-16 13:29:36 +02004810 /* include rpc element */
4811 if (module->rpc) {
4812 module->rpc->prev->next = mnode;
4813 mnode->prev = module->rpc->prev;
4814 module->rpc->prev = mnode;
4815 } else {
4816 module->rpc = mnode;
4817 }
4818 }
4819
4820 /* ... and notifications */
4821 LY_TREE_FOR_SAFE(notifs.child, next, node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004822 mnode = read_yin_notif(module, NULL, node, 0, unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004823 if (!mnode) {
4824 goto error;
4825 }
4826
Radek Krejci73adb602015-07-02 18:07:40 +02004827 lyxml_free_elem(ctx, node);
4828
Radek Krejcif5be10f2015-06-16 13:29:36 +02004829 /* include notification element */
4830 if (module->notif) {
4831 module->notif->prev->next = mnode;
4832 mnode->prev = module->notif->prev;
4833 module->notif->prev = mnode;
4834 } else {
4835 module->notif = mnode;
4836 }
4837 }
4838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004839 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004840
4841error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004842 /* cleanup */
4843 while (root.child) {
4844 lyxml_free_elem(module->ctx, root.child);
4845 }
4846 while (grps.child) {
4847 lyxml_free_elem(module->ctx, grps.child);
4848 }
4849 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004850 lyxml_free_elem(module->ctx, rpcs.child);
4851 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004852
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004853 free(unres->item);
4854 unres->item = NULL;
4855 free(unres->type);
4856 unres->type = NULL;
4857 free(unres->str_mnode);
4858 unres->str_mnode = NULL;
4859 free(unres->line);
4860 unres->line = NULL;
4861 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004862
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004863 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004864}
4865
Radek Krejcib8048692015-08-05 13:36:34 +02004866struct lys_submodule *
4867yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_item *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004868{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004870 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004871 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004872
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004873 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004875 yin = lyxml_read(module->ctx, data, 0);
4876 if (!yin) {
4877 return NULL;
4878 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004879
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004880 /* check root element */
4881 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004882 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004883 goto error;
4884 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004885
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004886 GETVAL(value, yin, "name");
4887 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4888 goto error;
4889 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 submodule = calloc(1, sizeof *submodule);
4892 if (!submodule) {
4893 LOGMEM;
4894 goto error;
4895 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004896
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004897 submodule->ctx = module->ctx;
4898 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4899 submodule->type = 1;
4900 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004901 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004902
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004903 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004904 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004905 goto error;
4906 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004907
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004908 /* cleanup */
4909 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004911 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004912
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004913 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004914
4915error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 /* cleanup */
4917 lyxml_free_elem(module->ctx, yin);
4918 ly_submodule_free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02004919
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004920 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004921}
4922
Radek Krejcib8048692015-08-05 13:36:34 +02004923struct lys_module *
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004924yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_item *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004925{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004926 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004927 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 const char *value;
4929 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004930
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004931 yin = lyxml_read(ctx, data, 0);
4932 if (!yin) {
4933 return NULL;
4934 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004935
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004936 /* check root element */
4937 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004938 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004939 goto error;
4940 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004941
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004942 GETVAL(value, yin, "name");
4943 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4944 goto error;
4945 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004946
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004947 module = calloc(1, sizeof *module);
4948 if (!module) {
4949 LOGMEM;
4950 goto error;
4951 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004952
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004953 module->ctx = ctx;
4954 module->name = lydict_insert(ctx, value, strlen(value));
4955 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004956 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004957
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004958 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004959 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004960 goto error;
4961 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004962
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004963 /* add to the context's list of modules */
4964 if (ctx->models.used == ctx->models.size) {
4965 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4966 if (!newlist) {
4967 LOGMEM;
4968 goto error;
4969 }
4970 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4971 newlist[i] = NULL;
4972 }
4973 ctx->models.size *= 2;
4974 ctx->models.list = newlist;
4975 }
4976 for (i = 0; ctx->models.list[i]; i++) {
4977 /* check name (name/revision) and namespace uniqueness */
4978 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004979 if (ctx->models.list[i]->rev_size == module->rev_size) {
4980 /* both have the same number of revisions */
4981 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4982 /* both have the same revision -> we already have the same module */
4983 /* so free the new one and update the old one's implement flag if needed */
4984 lyxml_free_elem(ctx, yin);
4985 lys_free(module);
4986
4987 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4988
4989 if (implement && !ctx->models.list[i]->implemented) {
4990 lyp_set_implemented(ctx->models.list[i]);
4991 }
4992 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004993 }
4994 }
Radek Krejcif647e612015-07-30 11:36:07 +02004995 /* else (both elses) keep searching, for now the caller is just adding
4996 * another revision of an already present schema
4997 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004998 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4999 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
5000 ctx->models.list[i]->name, module->name, module->ns);
5001 goto error;
5002 }
5003 }
5004 ctx->models.list[i] = module;
5005 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02005006 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005008 /* cleanup */
5009 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005011 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005013 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005014
5015error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005016 /* cleanup */
5017 lyxml_free_elem(ctx, yin);
Radek Krejci912da452015-07-29 14:10:06 +02005018 lys_free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02005019
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02005020 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02005021}