blob: 6dcc8aa0b086160186dedf412c5f9fd12705c560 [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 Vaskof02e3742015-08-05 16:27:02 +020071 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020073 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020075 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020077 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020079 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020081 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020083 int resolve, struct unres_schema *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 Vaskof02e3742015-08-05 16:27:02 +020085 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020086static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020087 int resolve, struct unres_schema *unres);
88static 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 Krejci1d82ef62015-08-07 14:44:40 +0200143 struct lys_node *node;
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 Krejci1d82ef62015-08-07 14:44:40 +0200171 LY_TREE_FOR(parent->child, node) {
172 if (node->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 Krejci1d82ef62015-08-07 14:44:40 +0200294check_mandatory(struct lys_node *node)
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
Radek Krejci1d82ef62015-08-07 14:44:40 +0200298 assert(node);
Radek Krejci3de29a72015-06-16 15:23:03 +0200299
Radek Krejci1d82ef62015-08-07 14:44:40 +0200300 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci3de29a72015-06-16 15:23:03 +0200301 return EXIT_FAILURE;
302 }
303
Radek Krejci1d82ef62015-08-07 14:44:40 +0200304 if (node->nodetype == LYS_CASE || node->nodetype == LYS_CHOICE) {
305 LY_TREE_FOR(node->child, child) {
Radek Krejcifd0bb0a2015-06-18 13:18:24 +0200306 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 Krejci6e4ffbb2015-06-16 10:34:41 +0200344static const char *
345read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200346{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200347 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200348
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200349 /* there should be <text> child */
350 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
351 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
352 } else if (node->child->content) {
353 len = strlen(node->child->content);
354 return lydict_insert(ctx, node->child->content, len);
355 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200356
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200357 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200358 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200359}
360
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200361static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200362fill_yin_identity(struct lys_module *module, struct lyxml_elem *yin, struct lys_ident *ident, struct unres_schema *unres)
Radek Krejci04581c62015-05-22 21:24:00 +0200363{
Radek Krejci73adb602015-07-02 18:07:40 +0200364 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200365 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200366
Michal Vasko4cfcd252015-08-03 14:31:10 +0200367 GETVAL(value, yin, "name");
368 ident->name = lydict_insert(module->ctx, value, 0);
369
Radek Krejci76512572015-08-04 09:47:08 +0200370 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200371 return EXIT_FAILURE;
372 }
Radek Krejci04581c62015-05-22 21:24:00 +0200373
Radek Krejci73adb602015-07-02 18:07:40 +0200374 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200375 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
376 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200377 continue;
378 }
379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200380 if (!strcmp(node->name, "base")) {
381 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200382 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200383 return EXIT_FAILURE;
384 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200385 GETVAL(value, node, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +0200386 unres_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200387 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200388 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200389 return EXIT_FAILURE;
390 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200391 }
Radek Krejci04581c62015-05-22 21:24:00 +0200392
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200393error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200394 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200395}
396
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200397static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200398read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200399{
Radek Krejci73adb602015-07-02 18:07:40 +0200400 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200401 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200402
Radek Krejci73adb602015-07-02 18:07:40 +0200403 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200404 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
405 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200406 continue;
407 }
408
Radek Krejci41726f92015-06-19 13:11:05 +0200409 if (!strcmp(child->name, "description")) {
410 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200411 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200412 return EXIT_FAILURE;
413 }
414 restr->dsc = read_yin_subnode(ctx, child, "text");
415 if (!restr->dsc) {
416 return EXIT_FAILURE;
417 }
418 } else if (!strcmp(child->name, "reference")) {
419 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200420 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200421 return EXIT_FAILURE;
422 }
423 restr->ref = read_yin_subnode(ctx, child, "text");
424 if (!restr->ref) {
425 return EXIT_FAILURE;
426 }
427 } else if (!strcmp(child->name, "error-app-tag")) {
428 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200429 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200430 return EXIT_FAILURE;
431 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200432 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200433 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200434 } else if (!strcmp(child->name, "error-message")) {
435 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200436 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200437 return EXIT_FAILURE;
438 }
439 restr->emsg = read_yin_subnode(ctx, child, "value");
440 if (!restr->emsg) {
441 return EXIT_FAILURE;
442 }
443 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200444 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200445 return EXIT_FAILURE;
446 }
Radek Krejci41726f92015-06-19 13:11:05 +0200447 }
448
449 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200450
451error:
452 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200453}
454
455static int
Radek Krejcib8048692015-08-05 13:36:34 +0200456fill_yin_type(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_type *type,
Michal Vaskof02e3742015-08-05 16:27:02 +0200457 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200458{
Michal Vasko69068852015-07-13 14:34:31 +0200459#define REGEX_ERR_LEN 128
Radek Krejcif2860132015-06-20 12:37:20 +0200460 const char *value, *delim, *name;
Michal Vasko69068852015-07-13 14:34:31 +0200461 char regex_err[REGEX_ERR_LEN];
Radek Krejci5fbc9162015-06-19 14:11:11 +0200462 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200463 struct lys_restr **restr;
464 struct lys_type_bit bit;
Michal Vasko69068852015-07-13 14:34:31 +0200465 regex_t preq;
466 int i, j, ret;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200467 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200468 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200469
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200470 GETVAL(value, yin, "name");
471
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200472 delim = strchr(value, ':');
473 if (delim) {
474 type->prefix = lydict_insert(module->ctx, value, delim - value);
475 delim++;
476 value += delim-value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200477 }
Radek Krejci667b97f2015-05-25 15:03:30 +0200478
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200479 type->der = resolve_superior_type(value, type->prefix, module, parent);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200480 if (!type->der) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200481 /* HACK for unres */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200482 type->der = (struct lys_tpdf *)parent;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200483 unres_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200484 return EXIT_SUCCESS;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200485 }
486 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200487
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200488 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200489 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200490 /* RFC 6020 9.7.4 - bit */
491
492 /* get bit specifications, at least one must be present */
493 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200494 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
495 /* garbage */
496 lyxml_free_elem(module->ctx, node);
497 continue;
498 }
499
Radek Krejci994b6f62015-06-18 16:47:27 +0200500 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200501 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200502 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200503 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200504 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200505 }
506 }
Radek Krejciac781922015-07-09 15:35:14 +0200507 if (!type->der->type.der && !type->info.bits.count) {
508 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200509 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200510 goto error;
511 }
Radek Krejciac781922015-07-09 15:35:14 +0200512 if (type->der->type.der && type->info.bits.count) {
513 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200514 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200515 goto error;
516 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200517
518 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200519 p = 0;
520 i = -1;
521 LY_TREE_FOR(yin->child, next) {
522 i++;
523
524 GETVAL(value, next, "name");
525 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200526 goto error;
527 }
528 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200529 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200530 type->info.bits.count = i + 1;
531 goto error;
532 }
533
534 /* check the name uniqueness */
535 for (j = 0; j < i; j++) {
536 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200537 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200538 type->info.bits.count = i + 1;
539 goto error;
540 }
541 }
542
Radek Krejci0d70c372015-07-02 16:23:10 +0200543 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200544 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200545 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
546 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200547 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200548 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200549
Radek Krejci0d70c372015-07-02 16:23:10 +0200550 if (!strcmp(node->name, "position")) {
551 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200552 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200553
554 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200555 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200556 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200557 type->info.bits.count = i + 1;
558 goto error;
559 }
560 type->info.bits.bit[i].pos = (uint32_t)p_;
561
562 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200563 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200564 p = type->info.bits.bit[i].pos;
565 p++;
566 } else {
567 /* check that the value is unique */
568 for (j = 0; j < i; j++) {
569 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200570 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 +0200571 type->info.bits.count = i + 1;
572 goto error;
573 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200574 }
575 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200576 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200577 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200578 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200579 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200580 }
581 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200582 /* assign value automatically */
583 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200584 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200585 type->info.bits.count = i + 1;
586 goto error;
587 }
588 type->info.bits.bit[i].pos = (uint32_t)p;
589 p++;
590 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200591
592 /* keep them ordered by position */
593 j = i;
594 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
595 /* switch them */
596 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
597 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
598 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
599 j--;
600 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200601 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200602 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200603
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200604 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200605 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200606 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200607 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
608 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200609 continue;
610 }
611
Radek Krejcif9401c32015-06-26 16:47:36 +0200612 if (!strcmp(node->name, "range")) {
613 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200614 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200615 goto error;
616 }
617
618 GETVAL(value, node, "value");
Michal Vasko9c1bc642015-08-05 16:25:53 +0200619 if (check_length_range(value, type)) {
620 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200621 goto error;
622 }
623 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
624 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
625
626 /* get possible substatements */
627 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
628 goto error;
629 }
630 } else if (!strcmp(node->name, "fraction-digits")) {
631 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200632 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200633 goto error;
634 }
635 GETVAL(value, node, "value");
636 v = strtol(value, NULL, 10);
637
638 /* range check */
639 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200640 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200641 goto error;
642 }
643 type->info.dec64.dig = (uint8_t)v;
644 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200645 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200646 goto error;
647 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200648 }
649
650 /* mandatory sub-statement(s) check */
651 if (!type->info.dec64.dig && !type->der->type.der) {
652 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200653 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200654 goto error;
655 }
Radek Krejci7511f402015-07-10 09:56:30 +0200656 if (type->info.dec64.dig && type->der->type.der) {
657 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200658 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200659 goto error;
660 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200661 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200663 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200664 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200665
Radek Krejci994b6f62015-06-18 16:47:27 +0200666 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200667 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200668 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
669 /* garbage */
670 lyxml_free_elem(module->ctx, node);
671 continue;
672 }
673
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200675 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200676 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200677 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200678 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200679 }
680 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200681 if (!type->der->type.der && !type->info.enums.count) {
682 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200683 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200684 goto error;
685 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200686 if (type->der->type.der && type->info.enums.count) {
687 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200688 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200689 goto error;
690 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200691
Radek Krejci1574a8d2015-08-03 14:16:52 +0200692 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200693 v = 0;
694 i = -1;
695 LY_TREE_FOR(yin->child, next) {
696 i++;
697
698 GETVAL(value, next, "name");
699 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200700 goto error;
701 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200702 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200703 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200704 type->info.enums.count = i + 1;
705 goto error;
706 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200708 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200709 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200710 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200711 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200712 type->info.enums.count = i + 1;
713 goto error;
714 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200716 /* check the name uniqueness */
717 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200718 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200719 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200720 type->info.enums.count = i + 1;
721 goto error;
722 }
723 }
Radek Krejci04581c62015-05-22 21:24:00 +0200724
Radek Krejci0d70c372015-07-02 16:23:10 +0200725 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200726 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200727 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
728 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200729 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200730 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200731
Radek Krejci0d70c372015-07-02 16:23:10 +0200732 if (!strcmp(node->name, "value")) {
733 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200734 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200735
736 /* range check */
737 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200738 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200739 type->info.enums.count = i + 1;
740 goto error;
741 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200742 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200743
744 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200745 if (type->info.enums.enm[i].value > v) {
746 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200747 v++;
748 } else {
749 /* check that the value is unique */
750 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200751 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200752 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200753 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200754 type->info.enums.count = i + 1;
755 goto error;
756 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200757 }
758 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200759 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200760 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200761 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200762 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200763 }
764 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200765 /* assign value automatically */
766 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200767 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200768 type->info.enums.count = i + 1;
769 goto error;
770 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200771 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200772 v++;
773 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200774 }
775 break;
776
777 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200778 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779
780 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200781 LY_TREE_FOR_SAFE(yin->child, next, node) {
782 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
783 /* garbage */
784 lyxml_free_elem(module->ctx, node);
785 continue;
786 }
787
788 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200789 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200790 goto error;
791 }
792 }
793
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200794 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200795 if (type->der->type.der) {
796 /* this is just a derived type with no base specified/required */
797 break;
798 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200799 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200800 goto error;
801 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200802 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200803 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200804 goto error;
805 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200806 GETVAL(value, yin->child, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +0200807 unres_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200808 break;
809
810 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200811 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200812 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200813 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
814 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200815 continue;
816 }
817
Radek Krejciaf351422015-06-19 14:49:38 +0200818 if (!strcmp(node->name, "require-instance")) {
819 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200820 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200821 goto error;
822 }
823 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200824 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200825 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200826 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200827 type->info.inst.req = -1;
828 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200829 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200830 goto error;
831 }
832 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200833 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200834 goto error;
835 }
Radek Krejciaf351422015-06-19 14:49:38 +0200836 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200838 break;
839
Radek Krejcif2860132015-06-20 12:37:20 +0200840 case LY_TYPE_BINARY:
841 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200842 case LY_TYPE_INT8:
843 case LY_TYPE_INT16:
844 case LY_TYPE_INT32:
845 case LY_TYPE_INT64:
846 case LY_TYPE_UINT8:
847 case LY_TYPE_UINT16:
848 case LY_TYPE_UINT32:
849 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200850 /* RFC 6020 9.2.4 - range */
851
852 /* length and range are actually the same restriction, so process
853 * them by this common code, we just need to differ the name and
854 * structure where the information will be stored
855 */
856 if (type->base == LY_TYPE_BINARY) {
857 restr = &type->info.binary.length;
858 name = "length";
859 } else {
860 restr = &type->info.num.range;
861 name = "range";
862 }
863
Radek Krejci73adb602015-07-02 18:07:40 +0200864 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200865 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
866 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200867 continue;
868 }
869
Radek Krejcif2860132015-06-20 12:37:20 +0200870 if (!strcmp(node->name, name)) {
871 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200872 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200873 goto error;
874 }
875
876 GETVAL(value, node, "value");
Michal Vasko9c1bc642015-08-05 16:25:53 +0200877 if (check_length_range(value, type)) {
878 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200879 goto error;
880 }
881 *restr = calloc(1, sizeof **restr);
882 (*restr)->expr = lydict_insert(module->ctx, value, 0);
883
884 /* get possible substatements */
885 if (read_restr_substmt(module->ctx, *restr, node)) {
886 goto error;
887 }
888 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200889 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200890 goto error;
891 }
Radek Krejcif2860132015-06-20 12:37:20 +0200892 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200893 break;
894
895 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200896 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200897 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200898 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
899 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200900 continue;
901 }
902
Radek Krejcidc4c1412015-06-19 15:39:54 +0200903 if (!strcmp(node->name, "path")) {
904 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200905 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200906 goto error;
907 }
908
909 GETVAL(value, node, "value");
Radek Krejcidc4c1412015-06-19 15:39:54 +0200910 type->info.lref.path = lydict_insert(module->ctx, value, 0);
Radek Krejci1d82ef62015-08-07 14:44:40 +0200911 unres_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200912
Radek Krejcidc4c1412015-06-19 15:39:54 +0200913 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200914 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200915 goto error;
916 }
Radek Krejci73adb602015-07-02 18:07:40 +0200917 }
918
919 if (!type->info.lref.path) {
920 if (type->der->type.der) {
921 /* this is just a derived type with no path specified/required */
922 break;
923 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200924 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200925 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200926 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200927 break;
928
929 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200930 /* RFC 6020 9.4.4 - length */
931 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200932 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200933 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200934 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
935 /* garbage */
936 lyxml_free_elem(module->ctx, node);
937 continue;
938 }
939
Radek Krejci3733a802015-06-19 13:43:21 +0200940 if (!strcmp(node->name, "length")) {
941 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200942 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200943 goto error;
944 }
945
946 GETVAL(value, node, "value");
Michal Vasko9c1bc642015-08-05 16:25:53 +0200947 if (check_length_range(value, type)) {
948 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200949 goto error;
950 }
951 type->info.str.length = calloc(1, sizeof *type->info.str.length);
952 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
953
Radek Krejci5fbc9162015-06-19 14:11:11 +0200954 /* get possible sub-statements */
955 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200956 goto error;
957 }
Radek Krejci82d971d2015-06-19 14:20:50 +0200958 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200959 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200960 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200961 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200962 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200963 goto error;
964 }
965 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200966 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200967 if (i) {
968 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
969 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +0200970 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200971
972 /* check that the regex is valid */
973 if ((ret = regcomp(&preq, value, REG_EXTENDED | REG_NOSUB)) != 0) {
974 regerror(ret, &preq, regex_err, REGEX_ERR_LEN);
975 regfree(&preq);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200976 LOGVAL(LYE_INREGEX, LOGLINE(node), value, regex_err);
Michal Vasko69068852015-07-13 14:34:31 +0200977 free(type->info.str.patterns);
978 goto error;
979 }
980 regfree(&preq);
981
Radek Krejci73adb602015-07-02 18:07:40 +0200982 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200983
984 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +0200985 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +0200986 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200987 goto error;
988 }
Radek Krejci73adb602015-07-02 18:07:40 +0200989 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200990 }
991 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200992 break;
993
994 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +0200995 /* RFC 6020 7.4 - type */
996 /* count number of types in union */
997 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +0200998 LY_TREE_FOR_SAFE(yin->child, next, node) {
999 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1000 /* garbage */
1001 lyxml_free_elem(module->ctx, node);
1002 continue;
1003 }
1004
Radek Krejcie4c366b2015-07-02 10:11:31 +02001005 if (!strcmp(node->name, "type")) {
1006 i++;
1007 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001008 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001009 goto error;
1010 }
1011 }
1012
1013 if (!i) {
1014 if (type->der->type.der) {
1015 /* this is just a derived type with no base specified/required */
1016 break;
1017 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001018 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001019 goto error;
1020 }
1021
1022 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001023 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001024 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001025 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001026 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001027 goto error;
1028 }
1029 type->info.uni.count++;
1030
1031 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001032 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001033 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001034 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001035 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001036 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001037 goto error;
1038 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001039 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001040 break;
1041
1042 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001043 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001044 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1045 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001046 LY_TREE_FOR(yin->child, node) {
1047 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001048 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001049 goto error;
1050 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001051 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001052 break;
1053 }
1054
1055 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001056
1057error:
1058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001059 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001060}
1061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001062static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001063fill_yin_typedef(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_tpdf *tpdf, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02001064{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001065 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001066 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001067 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001068
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001069 GETVAL(value, yin, "name");
1070 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1071 goto error;
1072 }
1073 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001074
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001075 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001076 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001077 goto error;
1078 }
Radek Krejcieac35532015-05-31 19:09:15 +02001079
Radek Krejci73adb602015-07-02 18:07:40 +02001080 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001081 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1082 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001083 continue;
1084 }
1085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001087 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001088 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001089 goto error;
1090 }
Radek Krejci73adb602015-07-02 18:07:40 +02001091 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1092 goto error;
1093 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001094 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001095 } else if (!strcmp(node->name, "default")) {
1096 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001097 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001098 goto error;
1099 }
1100 GETVAL(value, node, "value");
1101 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001102 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001103 } else if (!strcmp(node->name, "units")) {
1104 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001105 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 goto error;
1107 }
1108 GETVAL(value, node, "name");
1109 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1110 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001111 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001112 goto error;
1113 }
1114 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001116 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001117 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001118 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001119 goto error;
1120 }
Radek Krejcieac35532015-05-31 19:09:15 +02001121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001122 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001123 if (tpdf->dflt) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001124 unres_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001125 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001128
1129error:
1130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001131 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001132}
1133
Radek Krejci3cf9e222015-06-18 11:37:50 +02001134static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001135fill_yin_feature(struct lys_module *module, struct lyxml_elem *yin, struct lys_feature *f, struct unres_schema *unres)
Radek Krejci3cf9e222015-06-18 11:37:50 +02001136{
1137 const char *value;
1138 struct lyxml_elem *child, *next;
1139 int c = 0;
1140
Radek Krejcib05774c2015-06-18 13:52:59 +02001141 GETVAL(value, yin, "name");
1142 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1143 goto error;
1144 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001145 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001146 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001147
Radek Krejci76512572015-08-04 09:47:08 +02001148 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001149 goto error;
1150 }
1151
1152 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001153 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1154 /* garbage */
1155 lyxml_free_elem(module->ctx, child);
1156 continue;
1157 }
1158
Radek Krejci3cf9e222015-06-18 11:37:50 +02001159 if (!strcmp(child->name, "if-feature")) {
1160 c++;
1161 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001162 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001163 goto error;
1164 }
1165 }
1166
1167 if (c) {
1168 f->features = calloc(c, sizeof *f->features);
1169 }
Radek Krejci73adb602015-07-02 18:07:40 +02001170 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001171 GETVAL(value, child, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02001172 unres_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child));
Radek Krejci3cf9e222015-06-18 11:37:50 +02001173 }
1174
Radek Krejci3cf9e222015-06-18 11:37:50 +02001175 return EXIT_SUCCESS;
1176
1177error:
1178
1179 return EXIT_FAILURE;
1180}
1181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001182static int
Radek Krejcib8048692015-08-05 13:36:34 +02001183fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001184{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001185 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001187 GETVAL(value, yin, "condition");
Radek Krejci0bd5db42015-06-19 13:30:07 +02001188 must->expr = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02001189
Radek Krejci41726f92015-06-19 13:11:05 +02001190 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001191
Radek Krejci41726f92015-06-19 13:11:05 +02001192error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001194 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001195}
1196
Radek Krejcieb00f512015-07-01 16:44:58 +02001197/*
1198 * type: 0 - min, 1 - max
1199 */
1200static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001201deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001202{
1203 const char *value;
1204 char *endptr;
1205 unsigned long val;
1206 uint32_t *ui32val;
1207
1208 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001209 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001210 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001211 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001212 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001213 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001214 }
Radek Krejci76512572015-08-04 09:47:08 +02001215 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001216 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001217 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001218 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001219 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001220 }
1221 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001222 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1223 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001224 goto error;
1225 }
1226
1227 GETVAL(value, node, "value");
1228 while (isspace(value[0])) {
1229 value++;
1230 }
1231
1232 /* convert it to uint32_t */
1233 errno = 0;
1234 endptr = NULL;
1235 val = strtoul(value, &endptr, 10);
1236 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001237 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001238 goto error;
1239 }
1240 if (type) {
1241 d->max = (uint32_t)val;
1242 } else {
1243 d->min = (uint32_t)val;
1244 }
1245
1246 if (d->mod == LY_DEVIATE_ADD) {
1247 /* check that there is no current value */
1248 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001249 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1250 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001251 goto error;
1252 }
1253 }
1254
1255 if (d->mod == LY_DEVIATE_DEL) {
1256 /* check values */
1257 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001258 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1259 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001260 goto error;
1261 }
1262 /* remove current min-elements value of the target */
1263 *ui32val = 0;
1264 } else { /* add (already checked) and replace */
1265 /* set new value specified in deviation */
1266 *ui32val = (uint32_t)val;
1267 }
1268
1269 return EXIT_SUCCESS;
1270
1271error:
1272
1273 return EXIT_FAILURE;
1274}
1275
1276static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001277fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001278{
1279 const char *value, **stritem;
1280 struct lyxml_elem *next, *child, *develem;
1281 int c_dev = 0, c_must, c_uniq;
1282 int f_min = 0; /* flags */
1283 int i, j;
Radek Krejcia52656e2015-08-05 13:41:50 +02001284 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001285 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001286 struct lys_node_choice *choice = NULL;
1287 struct lys_node_leaf *leaf = NULL;
1288 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001289 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001290 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001291 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001292
1293 GETVAL(value, yin, "target-node");
1294 dev->target_name = lydict_insert(module->ctx, value, 0);
1295
1296 /* resolve target node */
Radek Krejci76512572015-08-04 09:47:08 +02001297 dev->target = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT);
Radek Krejcieb00f512015-07-01 16:44:58 +02001298 if (!dev->target) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001299 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001300 goto error;
1301 }
1302 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001303 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001304 goto error;
1305 }
1306 /* mark the target module as deviated */
1307 dev->target->module->deviated = 1;
1308
1309 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001310 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1311 /* garbage */
1312 lyxml_free_elem(module->ctx, child);
1313 continue;
1314 }
1315
Radek Krejcieb00f512015-07-01 16:44:58 +02001316 if (!strcmp(child->name, "description")) {
1317 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001318 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001319 goto error;
1320 }
1321 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1322 if (!dev->dsc) {
1323 goto error;
1324 }
1325 } else if (!strcmp(child->name, "reference")) {
1326 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001327 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001328 goto error;
1329 }
1330 dev->ref = read_yin_subnode(module->ctx, child, "text");
1331 if (!dev->ref) {
1332 goto error;
1333 }
1334 } else if (!strcmp(child->name, "deviate")) {
1335 c_dev++;
1336
1337 /* skip lyxml_free_elem() at the end of the loop, node will be
1338 * further processed later
1339 */
1340 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001341
Radek Krejcieb00f512015-07-01 16:44:58 +02001342 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001343 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001344 goto error;
1345 }
1346
1347 lyxml_free_elem(module->ctx, child);
1348 }
1349
1350 if (c_dev) {
1351 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1352 }
1353
1354 LY_TREE_FOR(yin->child, develem) {
1355 /* init */
1356 f_min = 0;
1357 c_must = 0;
1358 c_uniq = 0;
1359
1360 /* get deviation type */
1361 GETVAL(value, develem, "value");
1362 if (!strcmp(value, "not-supported")) {
1363 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1364 /* no property expected in this case */
1365 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001366 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001367 goto error;
1368 }
1369
Radek Krejci5b917642015-07-02 09:03:13 +02001370 /* and neither any other deviate statement is expected,
1371 * not-supported deviation must be the only deviation of the target
1372 */
1373 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001374 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1375 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001376 goto error;
1377 }
1378
1379
Radek Krejcieb00f512015-07-01 16:44:58 +02001380 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001381 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001382 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001383
Radek Krejci5b917642015-07-02 09:03:13 +02001384 dev->deviate_size = 1;
1385 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001386 } else if (!strcmp(value, "add")) {
1387 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1388 } else if (!strcmp(value, "replace")) {
1389 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1390 } else if (!strcmp(value, "delete")) {
1391 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1392 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001393 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001394 goto error;
1395 }
1396 d = &dev->deviate[dev->deviate_size];
1397
1398 /* process deviation properties */
1399 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001400 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1401 /* garbage */
1402 lyxml_free_elem(module->ctx, child);
1403 continue;
1404 }
1405
Radek Krejcieb00f512015-07-01 16:44:58 +02001406 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001407 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001408 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001409 goto error;
1410 }
1411
1412 /* for we deviate from RFC 6020 and allow config property even it is/is not
1413 * specified in the target explicitly since config property inherits. So we expect
1414 * that config is specified in every node. But for delete, we check that the value
1415 * is the same as here in deviation
1416 */
1417 GETVAL(value, child, "value");
1418 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001419 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001420 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001421 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001422 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001423 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001424 goto error;
1425 }
1426
1427 if (d->mod == LY_DEVIATE_DEL) {
1428 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001429 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001430 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1431 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001432 goto error;
1433 }
1434 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001435 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001436
1437 /* ... and inherit config value from the target's parent */
1438 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001439 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001440 } else {
1441 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001442 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001443 }
1444 } else { /* add and replace are the same in this case */
1445 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001446 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001447
1448 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001449 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001450 }
1451 } else if (!strcmp(child->name, "default")) {
1452 if (d->dflt) {
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 GETVAL(value, child, "value");
1457 d->dflt = lydict_insert(module->ctx, value, 0);
1458
Radek Krejci76512572015-08-04 09:47:08 +02001459 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001460 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001461
1462 if (d->mod == LY_DEVIATE_ADD) {
1463 /* check that there is no current value */
1464 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001465 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1466 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001467 goto error;
1468 }
1469 }
1470
Radek Krejci1d82ef62015-08-07 14:44:40 +02001471 node = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE);
Radek Krejcieb00f512015-07-01 16:44:58 +02001472 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001473 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001474 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1475 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001476 goto error;
1477 }
1478 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001479 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001480 if (!choice->dflt) {
1481 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001482 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001483 goto error;
1484 }
1485 }
Radek Krejci76512572015-08-04 09:47:08 +02001486 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001487 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001488
1489 if (d->mod == LY_DEVIATE_ADD) {
1490 /* check that there is no current value */
1491 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001492 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1493 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001494 goto error;
1495 }
1496 }
1497
1498 if (d->mod == LY_DEVIATE_DEL) {
1499 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001500 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1501 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
1504 /* remove value */
1505 lydict_remove(leaf->module->ctx, leaf->dflt);
1506 leaf->dflt = NULL;
1507 } else { /* add (already checked) and replace */
1508 /* remove value */
1509 lydict_remove(leaf->module->ctx, leaf->dflt);
1510
1511 /* set new value */
1512 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1513 }
1514 } else {
1515 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001516 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1517 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001518 goto error;
1519 }
1520 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001521 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001522 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001523 goto error;
1524 }
1525
1526 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001527 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001528 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1529 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001530 goto error;
1531 }
1532
1533 GETVAL(value, child, "value");
1534 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001535 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001536 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001537 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001538 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001539 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001540 goto error;
1541 }
1542
1543 if (d->mod == LY_DEVIATE_ADD) {
1544 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001545 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001546 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1547 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001548 goto error;
1549 }
1550 }
1551
1552 if (d->mod == LY_DEVIATE_DEL) {
1553 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001554 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001555 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1556 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 goto error;
1558 }
1559 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001560 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001561 } else { /* add (already checked) and replace */
1562 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001563 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001564
1565 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001566 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 }
1568 } else if (!strcmp(child->name, "min-elements")) {
1569 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001570 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001571 goto error;
1572 }
1573 f_min = 1;
1574
1575 if (deviate_minmax(dev->target, child, d, 0)) {
1576 goto error;
1577 }
1578 } else if (!strcmp(child->name, "max-elements")) {
1579 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001580 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001581 goto error;
1582 }
1583
1584 if (deviate_minmax(dev->target, child, d, 1)) {
1585 goto error;
1586 }
1587 } else if (!strcmp(child->name, "must")) {
1588 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001589 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1590 continue;
1591 } else if (!strcmp(child->name, "type")) {
1592 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001593 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001594 goto error;
1595 }
1596
1597 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001598 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001599 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001600 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001601 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001602 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001603 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1604 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001605 goto error;
1606 }
1607
1608 if (d->mod == LY_DEVIATE_ADD) {
1609 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001610 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1611 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001612 goto error;
1613 } else if (d->mod == LY_DEVIATE_DEL) {
1614 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001615 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1616 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001617 goto error;
1618 }
1619
1620 /* replace */
1621 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001622 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001623
1624 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001625 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001626 goto error;
1627 }
1628 d->type = t;
1629 } else if (!strcmp(child->name, "unique")) {
1630 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001631 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1632 continue;
1633 } else if (!strcmp(child->name, "units")) {
1634 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001635 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001636 goto error;
1637 }
1638
1639 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001640 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001641 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001642 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001643 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001644 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001645 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1646 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001647 goto error;
1648 }
1649
1650 /* get units value */
1651 GETVAL(value, child, "name");
1652 d->units = lydict_insert(module->ctx, value, 0);
1653
1654 /* apply to target */
1655 if (d->mod == LY_DEVIATE_ADD) {
1656 /* check that there is no current value */
1657 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001658 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1659 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001660 goto error;
1661 }
1662 }
1663
1664 if (d->mod == LY_DEVIATE_DEL) {
1665 /* check values */
1666 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001667 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1668 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001669 goto error;
1670 }
1671 /* remove current units value of the target */
1672 lydict_remove(dev->target->module->ctx, *stritem);
1673 } else { /* add (already checked) and replace */
1674 /* remove current units value of the target ... */
1675 lydict_remove(dev->target->module->ctx, *stritem);
1676
1677 /* ... and replace it with the value specified in deviation */
1678 *stritem = lydict_insert(module->ctx, value, 0);
1679 }
1680 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001681 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001682 goto error;
1683 }
1684
1685 lyxml_free_elem(module->ctx, child);
1686 }
1687
1688 if (c_must) {
1689 /* check target node type */
1690 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001691 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001692 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1693 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001694 break;
Radek Krejci76512572015-08-04 09:47:08 +02001695 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001696 trg_must = &((struct lys_node_container *)dev->target)->must;
1697 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001698 break;
Radek Krejci76512572015-08-04 09:47:08 +02001699 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001700 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1701 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001702 break;
Radek Krejci76512572015-08-04 09:47:08 +02001703 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001704 trg_must = &((struct lys_node_list *)dev->target)->must;
1705 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001706 break;
Radek Krejci76512572015-08-04 09:47:08 +02001707 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001708 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1709 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001710 break;
1711 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001712 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1713 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001714 goto error;
1715 }
1716
1717 if (d->mod == LY_DEVIATE_RPL) {
1718 /* remove target's musts and allocate new array for it */
1719 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001720 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1721 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001722 goto error;
1723 }
1724
1725 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001726 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001727 }
1728 free(*trg_must);
1729 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1730 d->must_size = c_must;
1731 *trg_must_size = 0;
1732 } else if (d->mod == LY_DEVIATE_ADD) {
1733 /* reallocate the must array of the target */
1734 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1735 *trg_must = d->must;
1736 d->must = &(*trg_must[*trg_must_size]);
1737 d->must_size = c_must;
1738 } else { /* LY_DEVIATE_DEL */
1739 d->must = calloc(c_must, sizeof *d->must);
1740 }
1741 }
1742 if (c_uniq) {
1743 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001744 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001745 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1746 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001747 goto error;
1748 }
1749
Radek Krejcib8048692015-08-05 13:36:34 +02001750 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001751 if (d->mod == LY_DEVIATE_RPL) {
1752 /* remove target's unique and allocate new array for it */
1753 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001754 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1755 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001756 goto error;
1757 }
1758
1759 for (i = 0; i < list->unique_size; i++) {
1760 free(list->unique[i].leafs);
1761 }
1762 free(list->unique);
1763 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1764 d->unique_size = c_uniq;
1765 list->unique_size = 0;
1766 } else if (d->mod == LY_DEVIATE_ADD) {
1767 /* reallocate the unique array of the target */
1768 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1769 list->unique = d->unique;
1770 d->unique = &list->unique[list->unique_size];
1771 d->unique_size = c_uniq;
1772 } else { /* LY_DEVIATE_DEL */
1773 d->unique = calloc(c_uniq, sizeof *d->unique);
1774 }
1775 }
1776
1777 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001778 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001779 if (!strcmp(child->name, "must")) {
1780 if (d->mod == LY_DEVIATE_DEL) {
1781 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1782 goto error;
1783 }
1784
1785 /* find must to delete, we are ok with just matching conditions */
1786 for (i = 0; i < *trg_must_size; i++) {
1787 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1788 /* we have a match, free the must structure ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001789 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001790 /* ... and maintain the array */
1791 (*trg_must_size)--;
1792 if (i != *trg_must_size) {
1793 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1794 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1795 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1796 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1797 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1798 }
1799 if (!(*trg_must_size)) {
1800 free(*trg_must);
1801 *trg_must = NULL;
1802 } else {
1803 (*trg_must)[*trg_must_size].expr = NULL;
1804 (*trg_must)[*trg_must_size].dsc = NULL;
1805 (*trg_must)[*trg_must_size].ref = NULL;
1806 (*trg_must)[*trg_must_size].eapptag = NULL;
1807 (*trg_must)[*trg_must_size].emsg = NULL;
1808 }
1809
1810 i = -1; /* set match flag */
1811 break;
1812 }
1813 }
1814 d->must_size++;
1815 if (i != -1) {
1816 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001817 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1818 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001819 goto error;
1820 }
1821 } else { /* replace or add */
1822 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1823 goto error;
1824 }
1825 (*trg_must_size)++;
1826 }
1827 } else if (!strcmp(child->name, "unique")) {
1828 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001829 GETVAL(value, child, "tag");
1830 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001831 goto error;
1832 }
1833
1834 /* find unique structures to delete */
1835 for (i = 0; i < list->unique_size; i++) {
1836 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1837 continue;
1838 }
1839
1840 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1841 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1842 break;
1843 }
1844 }
1845
1846 if (j == d->unique[d->unique_size].leafs_size) {
1847 /* we have a match, free the unique structure ... */
1848 free(list->unique[i].leafs);
1849 /* ... and maintain the array */
1850 list->unique_size--;
1851 if (i != list->unique_size) {
1852 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1853 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1854 }
1855
1856 if (!list->unique_size) {
1857 free(list->unique);
1858 list->unique = NULL;
1859 } else {
1860 list->unique[list->unique_size].leafs_size = 0;
1861 list->unique[list->unique_size].leafs = NULL;
1862 }
1863
1864 i = -1; /* set match flag */
1865 break;
1866 }
1867 }
1868
1869 d->unique_size++;
1870 if (i != -1) {
1871 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001872 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1873 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001874 goto error;
1875 }
1876 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001877 GETVAL(value, child, "tag");
1878 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001879 goto error;
1880 }
1881 list->unique_size++;
1882 }
1883 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001884 }
Radek Krejci5b917642015-07-02 09:03:13 +02001885
1886 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001887 }
1888
Radek Krejcieb00f512015-07-01 16:44:58 +02001889 return EXIT_SUCCESS;
1890
1891error:
1892
1893 if (dev->deviate) {
1894 for (i = 0; i < dev->deviate_size; i++) {
1895 lydict_remove(module->ctx, dev->deviate[i].dflt);
1896 lydict_remove(module->ctx, dev->deviate[i].units);
1897
1898 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1899 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001900 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001901 }
1902 free(dev->deviate[i].must);
1903
1904 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1905 free(dev->deviate[i].unique[j].leafs);
1906 }
1907 free(dev->deviate[i].unique);
1908 }
1909 }
1910 free(dev->deviate);
1911 }
1912
1913 return EXIT_FAILURE;
1914}
1915
1916static int
Radek Krejcib8048692015-08-05 13:36:34 +02001917fill_yin_augment(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_node_augment *aug,
Michal Vaskof02e3742015-08-05 16:27:02 +02001918 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001919{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001920 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001921 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001922 struct lys_node *node;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001923 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02001924
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001925 GETVAL(value, yin, "target-node");
1926 aug->target_name = lydict_insert(module->ctx, value, 0);
1927 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001928
Radek Krejci76512572015-08-04 09:47:08 +02001929 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001930 goto error;
1931 }
1932
1933 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001934 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1935 /* garbage */
1936 lyxml_free_elem(module->ctx, child);
1937 continue;
1938 }
1939
Radek Krejci3cf9e222015-06-18 11:37:50 +02001940 if (!strcmp(child->name, "if-feature")) {
1941 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001942 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001943 } else if (!strcmp(child->name, "when")) {
1944 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001945 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001946 goto error;
1947 }
1948
1949 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001950 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001951 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001952 goto error;
1953 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001954 unres_add_node(module, unres, aug->when, UNRES_WHEN, (struct lys_node *)aug, LOGLINE(child));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001955 lyxml_free_elem(module->ctx, child);
1956 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001957
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001958 /* check allowed data sub-statements */
1959 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001960 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001961 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001962 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001963 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001964 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001965 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001966 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001967 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001968 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001969 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001970 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001972 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001973 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001974 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001975 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001976 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001977 goto error;
1978 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001979
Radek Krejci1d82ef62015-08-07 14:44:40 +02001980 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001981 goto error;
1982 }
1983
1984 /* check for mandatory nodes - if the target node is in another module
1985 * the added nodes cannot be mandatory
1986 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001987 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001988 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001989 goto error;
1990 }
1991
Radek Krejci1d82ef62015-08-07 14:44:40 +02001992 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001993 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001994 }
1995
1996 if (c) {
1997 aug->features = calloc(c, sizeof *aug->features);
1998 }
1999
2000 LY_TREE_FOR_SAFE(yin->child, next, child) {
2001 if (!strcmp(child->name, "if-feature")) {
2002 GETVAL(value, child, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002003 unres_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child));
Radek Krejci73adb602015-07-02 18:07:40 +02002004 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002005 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002006 }
2007
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002008 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002009 * connected to the tree and adjusted (if possible right now).
2010 * However, if this is augment in a uses, it gets resolved
2011 * when the uses does and cannot be resolved now for sure
2012 * (the grouping was not yet copied into uses).
2013 */
2014 if (!parent || (parent->nodetype != LYS_USES)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002015 unres_add_node(module, unres, aug, UNRES_AUGMENT, NULL, LOGLINE(yin));
Michal Vasko49291b32015-08-06 09:49:41 +02002016 }
Radek Krejci106efc02015-06-10 14:36:27 +02002017
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002018 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002019
2020error:
2021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002022 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002023}
2024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002025static int
Radek Krejcib8048692015-08-05 13:36:34 +02002026fill_yin_refine(struct lys_module *module, struct lyxml_elem *yin, struct lys_refine *rfn, struct lys_node_uses *uses,
Michal Vaskof02e3742015-08-05 16:27:02 +02002027 struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002028{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029 struct lyxml_elem *sub, *next;
2030 const char *value;
2031 char *endptr;
2032 int f_mand = 0, f_min = 0, f_max = 0;
2033 int c_must = 0;
2034 int r;
2035 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002036
Radek Krejci76512572015-08-04 09:47:08 +02002037 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002038 goto error;
2039 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002040
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002041 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002042 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002043
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002044 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002045 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2046 /* garbage */
2047 lyxml_free_elem(module->ctx, sub);
2048 continue;
2049 }
2050
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002051 /* limited applicability */
2052 if (!strcmp(sub->name, "default")) {
2053 /* leaf or choice */
2054 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002055 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 goto error;
2057 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002058
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002059 /* check possibility of statements combination */
2060 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002061 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002062 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002063 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002064 goto error;
2065 }
2066 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002067 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002070 GETVAL(value, sub, "value");
2071 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2072 } else if (!strcmp(sub->name, "mandatory")) {
2073 /* leaf, choice or anyxml */
2074 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002075 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002076 goto error;
2077 }
2078 /* just checking the flags in leaf is not sufficient, we would allow
2079 * multiple mandatory statements with the "false" value
2080 */
2081 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 /* check possibility of statements combination */
2084 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002085 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002087 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002088 goto error;
2089 }
2090 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002091 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002094 GETVAL(value, sub, "value");
2095 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002096 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002098 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002099 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002100 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 goto error;
2102 }
2103 } else if (!strcmp(sub->name, "min-elements")) {
2104 /* list or leaf-list */
2105 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002106 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002107 goto error;
2108 }
2109 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002110
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 /* check possibility of statements combination */
2112 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002113 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002114 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002115 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002116 goto error;
2117 }
2118 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002119 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002122 GETVAL(value, sub, "value");
2123 while (isspace(value[0])) {
2124 value++;
2125 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002127 /* convert it to uint32_t */
2128 errno = 0;
2129 endptr = NULL;
2130 val = strtoul(value, &endptr, 10);
2131 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002132 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002133 goto error;
2134 }
2135 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002136
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 /* magic - bit 3 in flags means min set */
2138 rfn->flags |= 0x04;
2139 } else if (!strcmp(sub->name, "max-elements")) {
2140 /* list or leaf-list */
2141 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002142 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 goto error;
2144 }
2145 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 /* check possibility of statements combination */
2148 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002149 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002150 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002151 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002152 goto error;
2153 }
2154 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002155 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002157
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002158 GETVAL(value, sub, "value");
2159 while (isspace(value[0])) {
2160 value++;
2161 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002163 /* convert it to uint32_t */
2164 errno = 0;
2165 endptr = NULL;
2166 val = strtoul(value, &endptr, 10);
2167 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002168 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002169 goto error;
2170 }
2171 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002172
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 /* magic - bit 4 in flags means min set */
2174 rfn->flags |= 0x08;
2175 } else if (!strcmp(sub->name, "presence")) {
2176 /* container */
2177 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002178 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 goto error;
2180 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002181
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002182 /* check possibility of statements combination */
2183 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002184 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002186 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002187 goto error;
2188 }
2189 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002190 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002192
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002193 GETVAL(value, sub, "value");
2194 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2195 } else if (!strcmp(sub->name, "must")) {
2196 /* leaf-list, list, container or anyxml */
2197 /* check possibility of statements combination */
2198 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002199 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002201 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002202 goto error;
2203 }
2204 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002205 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002207
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002208 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002209 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002210
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002211 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002212 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002213 goto error;
2214 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002215
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002216 lyxml_free_elem(module->ctx, sub);
2217 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002219 /* process nodes with cardinality of 0..n */
2220 if (c_must) {
2221 rfn->must = calloc(c_must, sizeof *rfn->must);
2222 }
Radek Krejci73adb602015-07-02 18:07:40 +02002223 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002224 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002225 if (r) {
2226 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002228 unres_add_node(module, unres, &rfn->must[rfn->must_size-1], UNRES_MUST, (struct lys_node *)uses,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002229 LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002230 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002231
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002232 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002233
2234error:
2235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237}
2238
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002239static int
Radek Krejcib8048692015-08-05 13:36:34 +02002240fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002241{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002242 struct lyxml_elem *child;
2243 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002245 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002246 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2247 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002248 continue;
2249 }
2250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002251 if (!strcmp(child->name, "prefix")) {
2252 GETVAL(value, child, "value");
2253 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2254 goto error;
2255 }
2256 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2257 } else if (!strcmp(child->name, "revision-date")) {
2258 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002259 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002260 goto error;
2261 }
2262 GETVAL(value, child, "date");
2263 if (check_date(value, LOGLINE(child))) {
2264 goto error;
2265 }
2266 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2267 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002268 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002269 goto error;
2270 }
2271 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002272
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 /* check mandatory information */
2274 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002275 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002276 goto error;
2277 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002278
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002279 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002280 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002281 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002282 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2283 if (!imp->module) {
2284 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2285 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002286 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002287 goto error;
2288 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002291 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002292
2293error:
2294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002296}
2297
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298static int
Radek Krejcib8048692015-08-05 13:36:34 +02002299fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002300{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002301 struct lyxml_elem *child;
2302 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002303
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002304 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002305 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2306 /* garbage */
2307 continue;
2308 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002309 if (!strcmp(child->name, "revision-date")) {
2310 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002311 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002312 goto error;
2313 }
2314 GETVAL(value, child, "date");
2315 if (check_date(value, LOGLINE(child))) {
2316 goto error;
2317 }
2318 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2319 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002320 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002321 goto error;
2322 }
2323 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002326 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002328 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 +02002329 if (!inc->submodule) {
2330 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2331 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002332 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002333 goto error;
2334 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002335 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002336
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002337 /* check that belongs-to corresponds */
2338 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002339 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002340 }
2341 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002342 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2343 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 goto error;
2345 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002346
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002347 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002348
2349error:
2350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002352}
2353
Radek Krejcida04f4a2015-05-21 12:54:09 +02002354/*
2355 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002356 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002357 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002358 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002359static int
Radek Krejcib8048692015-08-05 13:36:34 +02002360read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002361 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002362{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363 const char *value;
2364 struct lyxml_elem *sub, *next;
2365 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002366
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002368 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 if (opt & OPT_IDENT) {
2372 GETVAL(value, xmlnode, "name");
2373 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2374 goto error;
2375 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002376 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002377 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002378
Radek Krejci6764bb32015-07-03 15:16:04 +02002379 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002380 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002381 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002382 }
2383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002384 /* process local parameters */
2385 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002386 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002387 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002388 lyxml_free_elem(ctx, sub);
2389 continue;
2390 }
2391 if (strcmp(sub->ns->value, LY_NSYIN)) {
2392 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002393 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002394 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002395 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002396 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002397 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002398 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002399 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002400 goto error;
2401 }
2402 }
2403
2404 /* else garbage */
2405 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002406 continue;
2407 }
2408
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002409 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002410 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002411 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002412 goto error;
2413 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002414 node->dsc = read_yin_subnode(ctx, sub, "text");
2415 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002416 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002417 }
2418 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002419 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002420 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 goto error;
2422 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002423 node->ref = read_yin_subnode(ctx, sub, "text");
2424 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002425 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002426 }
2427 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002428 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002429 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 goto error;
2431 }
2432 GETVAL(value, sub, "value");
2433 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002434 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002435 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002436 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002437 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002438 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002440 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002441 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002442 }
2443 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002444 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002445 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 goto error;
2447 }
2448 GETVAL(value, sub, "value");
2449 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002450 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002451 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002452 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002453 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002454 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002455 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002456 }
2457 } else {
2458 /* skip the lyxml_free_elem */
2459 continue;
2460 }
2461 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002462 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002463
Radek Krejci1d82ef62015-08-07 14:44:40 +02002464 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002465 /* get config flag from parent */
2466 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 } else {
2469 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002470 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 }
2472 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002473
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002474 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002475
2476error:
2477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002479}
2480
Radek Krejci76512572015-08-04 09:47:08 +02002481static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002482read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002483{
Radek Krejci76512572015-08-04 09:47:08 +02002484 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002485 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002486 const char *value;
2487
2488 retval = calloc(1, sizeof *retval);
2489
2490 GETVAL(value, yin, "condition");
2491 retval->cond = lydict_insert(module->ctx, value, 0);
2492
Radek Krejci73adb602015-07-02 18:07:40 +02002493 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002494 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2495 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002496 continue;
2497 }
2498
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002499 if (!strcmp(child->name, "description")) {
2500 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002501 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002502 goto error;
2503 }
2504 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2505 if (!retval->dsc) {
2506 goto error;
2507 }
2508 } else if (!strcmp(child->name, "reference")) {
2509 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002510 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002511 goto error;
2512 }
2513 retval->ref = read_yin_subnode(module->ctx, child, "text");
2514 if (!retval->ref) {
2515 goto error;
2516 }
2517 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002518 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002519 goto error;
2520 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002521 }
2522
2523 return retval;
2524
2525error:
2526
Radek Krejci1d82ef62015-08-07 14:44:40 +02002527 lys_node_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002528 return NULL;
2529}
2530
Radek Krejcib4cf2022015-06-03 14:40:05 +02002531/* additional check in case statement - the child must be unique across
2532 * all other case names and its data children
2533 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002534static int
Radek Krejci76512572015-08-04 09:47:08 +02002535check_branch_id(struct lys_node *parent, struct lys_node *new, struct lys_node *excl, int line)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002536{
Radek Krejci1d82ef62015-08-07 14:44:40 +02002537 struct lys_node *node, *subnode;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002538
Radek Krejci76512572015-08-04 09:47:08 +02002539 if (new->nodetype == LYS_CHOICE) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002540 /* we have nested choice in case, so we need recursion */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002541 LY_TREE_FOR(new->child, node) {
2542 if (node->nodetype == LYS_CASE) {
2543 LY_TREE_FOR(node->child, subnode) {
2544 if (check_branch_id(parent, subnode, new, line)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002545 return EXIT_FAILURE;
2546 }
2547 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002548 } else if (check_branch_id(parent, node, new, line)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002549 return EXIT_FAILURE;
2550 }
2551 }
2552 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002553 LY_TREE_FOR(parent->child, node) {
2554 if (node == excl) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002555 continue;
2556 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002557
Radek Krejci1d82ef62015-08-07 14:44:40 +02002558 if (!strcmp(new->name, node->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002559 LOGVAL(LYE_INID, line, new->name, "duplicated identifier within a choice's cases");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002560 return EXIT_FAILURE;
2561 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002562 if (node->nodetype == LYS_CASE) {
2563 LY_TREE_FOR(node->child, subnode) {
2564 if (!strcmp(new->name, subnode->name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002565 LOGVAL(LYE_INID, line, new->name, "duplicated identifier within a choice's cases");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002566 return EXIT_FAILURE;
2567 }
2568 }
2569 }
2570 }
2571 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 return EXIT_SUCCESS;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002574}
2575
Radek Krejci76512572015-08-04 09:47:08 +02002576static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002577read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2578 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002579{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002580 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002581 struct lys_node_case *cs;
2582 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002583 int c_ftrs = 0;
2584 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002585
Radek Krejci1d82ef62015-08-07 14:44:40 +02002586 cs = calloc(1, sizeof *cs);
2587 cs->nodetype = LYS_CASE;
2588 cs->prev = (struct lys_node *)cs;
2589 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002590
Radek Krejci6a113852015-07-03 16:04:20 +02002591 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002592 goto error;
2593 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002595 /* process choice's specific children */
2596 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002597 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2598 /* garbage */
2599 lyxml_free_elem(module->ctx, sub);
2600 continue;
2601 }
2602
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002603 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002604 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002606 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002607 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002608 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002609 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002610 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002611 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002612 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002613 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002614 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002615 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002616 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002617 } else if (!strcmp(sub->name, "if-feature")) {
2618 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002619 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2620 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002621 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002622 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002623 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002624 goto error;
2625 }
2626
Radek Krejci1d82ef62015-08-07 14:44:40 +02002627 cs->when = read_yin_when(module, sub);
2628 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002629 goto error;
2630 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002631 unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002633 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002634 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002635 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002636
Radek Krejci1d82ef62015-08-07 14:44:40 +02002637 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002639 } else if (check_branch_id(parent, node, node, LOGLINE(sub))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002640 goto error;
2641 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002642
Radek Krejci1d82ef62015-08-07 14:44:40 +02002643 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002644 lyxml_free_elem(module->ctx, sub);
2645 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002646
Radek Krejci3cf9e222015-06-18 11:37:50 +02002647 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002648 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002649 }
Radek Krejci73adb602015-07-02 18:07:40 +02002650 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002651 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002652 unres_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002653 }
Radek Krejcib388c152015-06-04 17:03:03 +02002654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 /* insert the node into the schema tree */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002656 if (lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002657 goto error;
2658 }
Radek Krejcib7155b52015-06-10 17:03:01 +02002659
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002661
2662error:
2663
Radek Krejci1d82ef62015-08-07 14:44:40 +02002664 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002666 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002667}
2668
Radek Krejci76512572015-08-04 09:47:08 +02002669static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002670read_yin_choice(struct lys_module *module,
Michal Vaskof02e3742015-08-05 16:27:02 +02002671 struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002672{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002673 struct lyxml_elem *sub, *next;
2674 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002675 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002676 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002677 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002678 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002680 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002681 choice->nodetype = LYS_CHOICE;
2682 choice->prev = (struct lys_node *)choice;
2683 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002684
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002685 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2686 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002687 goto error;
2688 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002689
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 /* process choice's specific children */
2691 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002692 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2693 /* garbage */
2694 lyxml_free_elem(module->ctx, sub);
2695 continue;
2696 }
2697
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002698 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002699 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002700 goto error;
2701 }
2702 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002703 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002704 goto error;
2705 }
2706 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002707 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002708 goto error;
2709 }
2710 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002711 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002712 goto error;
2713 }
2714 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002715 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002716 goto error;
2717 }
2718 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002719 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002720 goto error;
2721 }
2722 } else if (!strcmp(sub->name, "default")) {
2723 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002724 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 goto error;
2726 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002727 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 } else if (!strcmp(sub->name, "mandatory")) {
2729 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002730 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 goto error;
2732 }
2733 /* just checking the flags in leaf is not sufficient, we would allow
2734 * multiple mandatory statements with the "false" value
2735 */
2736 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002737
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002738 GETVAL(value, sub, "value");
2739 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002740 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002741 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002742 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002743 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002744 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002745 goto error;
2746 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002747 } else if (!strcmp(sub->name, "when")) {
2748 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002749 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002750 goto error;
2751 }
2752
2753 choice->when = read_yin_when(module, sub);
2754 if (!choice->when) {
2755 goto error;
2756 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002757 unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002758 } else if (!strcmp(sub->name, "if-feature")) {
2759 c_ftrs++;
2760
2761 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2762 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002763 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002764 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002766 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002767
Radek Krejci1d82ef62015-08-07 14:44:40 +02002768 if (node && check_branch_id(retval, node, node, LOGLINE(sub))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002769 goto error;
2770 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002771 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002772 lyxml_free_elem(ctx, sub);
2773 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002774
Radek Krejci3cf9e222015-06-18 11:37:50 +02002775 if (c_ftrs) {
2776 choice->features = calloc(c_ftrs, sizeof *choice->features);
2777 }
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");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002781 unres_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002782 }
2783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002784 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002785 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002786 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002787 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2788 goto error;
2789 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002791 /* link default with the case */
2792 if (dflt_str) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002793 unres_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002794 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002795
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002796 /* insert the node into the schema tree */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002797 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002798 goto error;
2799 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002801 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002802
2803error:
2804
Radek Krejci1d82ef62015-08-07 14:44:40 +02002805 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002807 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002808}
2809
Radek Krejci76512572015-08-04 09:47:08 +02002810static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002811read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002812 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002813{
Radek Krejci76512572015-08-04 09:47:08 +02002814 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002815 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002816 struct lyxml_elem *sub, *next;
2817 const char *value;
2818 int r;
2819 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002820 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002821
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002822 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002823 anyxml->nodetype = LYS_ANYXML;
2824 anyxml->prev = (struct lys_node *)anyxml;
2825 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002826
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002827 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2828 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002829 goto error;
2830 }
Radek Krejci863c2852015-06-03 15:47:11 +02002831
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002832 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002833 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2834 /* garbage */
2835 lyxml_free_elem(module->ctx, sub);
2836 continue;
2837 }
2838
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002839 if (!strcmp(sub->name, "mandatory")) {
2840 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002841 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002842 goto error;
2843 }
2844 /* just checking the flags in leaf is not sufficient, we would allow
2845 * multiple mandatory statements with the "false" value
2846 */
2847 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002849 GETVAL(value, sub, "value");
2850 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002851 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002852 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002853 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002854 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002855 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 goto error;
2857 }
2858 /* else false is the default value, so we can ignore it */
2859 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002860 } else if (!strcmp(sub->name, "when")) {
2861 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002862 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002863 goto error;
2864 }
2865
2866 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002867 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002868 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002869 goto error;
2870 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002871 unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002872 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 } else if (!strcmp(sub->name, "must")) {
2874 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002875 } else if (!strcmp(sub->name, "if-feature")) {
2876 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002879 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002880 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 }
2882 }
Radek Krejci863c2852015-06-03 15:47:11 +02002883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 /* middle part - process nodes with cardinality of 0..n */
2885 if (c_must) {
2886 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2887 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002888 if (c_ftrs) {
2889 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2890 }
Radek Krejci863c2852015-06-03 15:47:11 +02002891
Radek Krejci73adb602015-07-02 18:07:40 +02002892 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002894 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 if (r) {
2896 goto error;
2897 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002898 unres_add_node(module, unres, &anyxml->must[anyxml->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci0b24d752015-07-02 15:02:27 +02002899 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002900 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002901 unres_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002902 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002903 }
Radek Krejci863c2852015-06-03 15:47:11 +02002904
Radek Krejci1d82ef62015-08-07 14:44:40 +02002905 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 goto error;
2907 }
Radek Krejci863c2852015-06-03 15:47:11 +02002908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002909 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002910
2911error:
2912
Radek Krejci1d82ef62015-08-07 14:44:40 +02002913 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002916}
2917
Radek Krejci76512572015-08-04 09:47:08 +02002918static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002919read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002920 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002921{
Radek Krejci76512572015-08-04 09:47:08 +02002922 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002923 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 struct lyxml_elem *sub, *next;
2925 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002926 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002927 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002930 leaf->nodetype = LYS_LEAF;
2931 leaf->prev = (struct lys_node *)leaf;
2932 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002933
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002934 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2935 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 goto error;
2937 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002938
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002939 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002940 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2941 /* garbage */
2942 lyxml_free_elem(module->ctx, sub);
2943 continue;
2944 }
2945
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002946 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002947 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002948 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002949 goto error;
2950 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002951 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 goto error;
2953 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002954 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 } else if (!strcmp(sub->name, "default")) {
2956 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002957 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 goto error;
2959 }
2960 GETVAL(value, sub, "value");
2961 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002962 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002963 } else if (!strcmp(sub->name, "units")) {
2964 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002965 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 goto error;
2967 }
2968 GETVAL(value, sub, "name");
2969 leaf->units = lydict_insert(module->ctx, value, strlen(value));
2970 } else if (!strcmp(sub->name, "mandatory")) {
2971 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002972 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 goto error;
2974 }
2975 /* just checking the flags in leaf is not sufficient, we would allow
2976 * multiple mandatory statements with the "false" value
2977 */
2978 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02002979
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002980 GETVAL(value, sub, "value");
2981 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002982 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002983 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002984 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002985 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002986 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002987 goto error;
2988 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002989 } else if (!strcmp(sub->name, "when")) {
2990 if (leaf->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 leaf->when = read_yin_when(module, sub);
2996 if (!leaf->when) {
2997 goto error;
2998 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002999 unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003000
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003002 c_must++;
3003 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003004 } else if (!strcmp(sub->name, "if-feature")) {
3005 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003006 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003007
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003009 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003010 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003012
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003013 lyxml_free_elem(module->ctx, sub);
3014 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003017 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003018 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 goto error;
3020 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003021 if (leaf->dflt) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003022 unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003023 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003024
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003025 /* middle part - process nodes with cardinality of 0..n */
3026 if (c_must) {
3027 leaf->must = calloc(c_must, sizeof *leaf->must);
3028 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003029 if (c_ftrs) {
3030 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3031 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003032
Radek Krejci73adb602015-07-02 18:07:40 +02003033 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003035 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003036 if (r) {
3037 goto error;
3038 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003039 unres_add_node(module, unres, &leaf->must[leaf->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003040 } else if (!strcmp(sub->name, "if-feature")) {
3041 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003042 unres_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003043 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003045
Radek Krejci1d82ef62015-08-07 14:44:40 +02003046 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003047 goto error;
3048 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003051
3052error:
3053
Radek Krejci1d82ef62015-08-07 14:44:40 +02003054 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003055
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003056 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003057}
3058
Radek Krejci76512572015-08-04 09:47:08 +02003059static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003060read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003061 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003062{
Radek Krejci76512572015-08-04 09:47:08 +02003063 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003064 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003065 struct lyxml_elem *sub, *next;
3066 const char *value;
3067 char *endptr;
3068 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003069 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003070 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003071 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003073 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003074 llist->nodetype = LYS_LEAFLIST;
3075 llist->prev = (struct lys_node *)llist;
3076 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003077
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003078 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3079 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003080 goto error;
3081 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003084 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3085 /* garbage */
3086 lyxml_free_elem(module->ctx, sub);
3087 continue;
3088 }
3089
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003091 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003092 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003093 goto error;
3094 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003095 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 goto error;
3097 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003098 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 } else if (!strcmp(sub->name, "units")) {
3100 if (llist->units) {
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 GETVAL(value, sub, "name");
3105 llist->units = lydict_insert(module->ctx, value, strlen(value));
3106 } else if (!strcmp(sub->name, "ordered-by")) {
3107 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003108 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003109 goto error;
3110 }
3111 /* just checking the flags in llist is not sufficient, we would
3112 * allow multiple ordered-by statements with the "system" value
3113 */
3114 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003115
Radek Krejci1574a8d2015-08-03 14:16:52 +02003116 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003117 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3118 * state data
3119 */
3120 lyxml_free_elem(module->ctx, sub);
3121 continue;
3122 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003123
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 GETVAL(value, sub, "value");
3125 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003126 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003127 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003128 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003129 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003130 } /* else system is the default value, so we can ignore it */
3131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003132 } else if (!strcmp(sub->name, "must")) {
3133 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003134 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003135 } else if (!strcmp(sub->name, "if-feature")) {
3136 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003137 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 } else if (!strcmp(sub->name, "min-elements")) {
3140 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003141 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003142 goto error;
3143 }
3144 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003146 GETVAL(value, sub, "value");
3147 while (isspace(value[0])) {
3148 value++;
3149 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003151 /* convert it to uint32_t */
3152 errno = 0;
3153 endptr = NULL;
3154 val = strtoul(value, &endptr, 10);
3155 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003156 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003157 goto error;
3158 }
3159 llist->min = (uint32_t) val;
3160 } else if (!strcmp(sub->name, "max-elements")) {
3161 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003162 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003163 goto error;
3164 }
3165 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 GETVAL(value, sub, "value");
3168 while (isspace(value[0])) {
3169 value++;
3170 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003171
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003172 /* convert it to uint32_t */
3173 errno = 0;
3174 endptr = NULL;
3175 val = strtoul(value, &endptr, 10);
3176 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003177 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003178 goto error;
3179 }
3180 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003181 } else if (!strcmp(sub->name, "when")) {
3182 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003183 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003184 goto error;
3185 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003186
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003187 llist->when = read_yin_when(module, sub);
3188 if (!llist->when) {
3189 goto error;
3190 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003191 unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003192 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003193 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003197 lyxml_free_elem(module->ctx, sub);
3198 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003200 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003201 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003202 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003203 goto error;
3204 }
3205 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003206 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003207 goto error;
3208 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003209
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 /* middle part - process nodes with cardinality of 0..n */
3211 if (c_must) {
3212 llist->must = calloc(c_must, sizeof *llist->must);
3213 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003214 if (c_ftrs) {
3215 llist->features = calloc(c_ftrs, sizeof *llist->features);
3216 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003217
Radek Krejci73adb602015-07-02 18:07:40 +02003218 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003219 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003220 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 if (r) {
3222 goto error;
3223 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003224 unres_add_node(module, unres, &llist->must[llist->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003225 } else if (!strcmp(sub->name, "if-feature")) {
3226 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003227 unres_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003229 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003230
Radek Krejci1d82ef62015-08-07 14:44:40 +02003231 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 goto error;
3233 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003235 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003236
3237error:
3238
Radek Krejci1d82ef62015-08-07 14:44:40 +02003239 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003240
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003241 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003242}
3243
Radek Krejci76512572015-08-04 09:47:08 +02003244static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003245read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3246 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003247{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003248 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003249 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003250 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003251 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003252 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003253 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003254 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003255 char *auxs;
3256 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003257
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003258 /* init */
3259 memset(&root, 0, sizeof root);
3260 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003261
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003263 list->nodetype = LYS_LIST;
3264 list->prev = (struct lys_node *)list;
3265 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003266
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003267 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3268 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 goto error;
3270 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003271
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 /* process list's specific children */
3273 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003274 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3275 /* garbage */
3276 lyxml_free_elem(module->ctx, sub);
3277 continue;
3278 }
3279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003280 /* data statements */
3281 if (!strcmp(sub->name, "container") ||
3282 !strcmp(sub->name, "leaf-list") ||
3283 !strcmp(sub->name, "leaf") ||
3284 !strcmp(sub->name, "list") ||
3285 !strcmp(sub->name, "choice") ||
3286 !strcmp(sub->name, "uses") ||
3287 !strcmp(sub->name, "grouping") ||
3288 !strcmp(sub->name, "anyxml")) {
3289 lyxml_unlink_elem(sub);
3290 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 /* array counters */
3293 } else if (!strcmp(sub->name, "key")) {
3294 /* check cardinality 0..1 */
3295 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003296 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003297 goto error;
3298 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003299
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 /* count the number of keys */
3301 GETVAL(value, sub, "value");
3302 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003303 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003304 while ((value = strpbrk(value, " \t\n"))) {
3305 list->keys_size++;
3306 while (isspace(*value)) {
3307 value++;
3308 }
3309 }
3310 list->keys_size++;
3311 list->keys = calloc(list->keys_size, sizeof *list->keys);
3312 } else if (!strcmp(sub->name, "unique")) {
3313 c_uniq++;
3314 lyxml_unlink_elem(sub);
3315 lyxml_add_child(&uniq, sub);
3316 } else if (!strcmp(sub->name, "typedef")) {
3317 c_tpdf++;
3318 } else if (!strcmp(sub->name, "must")) {
3319 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003320 } else if (!strcmp(sub->name, "if-feature")) {
3321 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 /* optional stetments */
3324 } else if (!strcmp(sub->name, "ordered-by")) {
3325 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003326 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003327 goto error;
3328 }
3329 /* just checking the flags in llist is not sufficient, we would
3330 * allow multiple ordered-by statements with the "system" value
3331 */
3332 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003333
Radek Krejci1574a8d2015-08-03 14:16:52 +02003334 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003335 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3336 * state data
3337 */
3338 lyxml_free_elem(module->ctx, sub);
3339 continue;
3340 }
Radek Krejci345ad742015-06-03 11:04:18 +02003341
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003342 GETVAL(value, sub, "value");
3343 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003344 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003346 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003347 goto error;
3348 }
3349 /* else system is the default value, so we can ignore it */
3350 lyxml_free_elem(module->ctx, sub);
3351 } else if (!strcmp(sub->name, "min-elements")) {
3352 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003353 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003354 goto error;
3355 }
3356 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003357
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003358 GETVAL(value, sub, "value");
3359 while (isspace(value[0])) {
3360 value++;
3361 }
Radek Krejci345ad742015-06-03 11:04:18 +02003362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 /* convert it to uint32_t */
3364 errno = 0;
3365 auxs = NULL;
3366 val = strtoul(value, &auxs, 10);
3367 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003368 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003369 goto error;
3370 }
3371 list->min = (uint32_t) val;
3372 lyxml_free_elem(module->ctx, sub);
3373 } else if (!strcmp(sub->name, "max-elements")) {
3374 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003375 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 goto error;
3377 }
3378 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003380 GETVAL(value, sub, "value");
3381 while (isspace(value[0])) {
3382 value++;
3383 }
Radek Krejci345ad742015-06-03 11:04:18 +02003384
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003385 /* convert it to uint32_t */
3386 errno = 0;
3387 auxs = NULL;
3388 val = strtoul(value, &auxs, 10);
3389 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003390 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003391 goto error;
3392 }
3393 list->max = (uint32_t) val;
3394 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003395 } else if (!strcmp(sub->name, "when")) {
3396 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003397 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003398 goto error;
3399 }
3400
3401 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003402 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003403 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003404 goto error;
3405 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003406 unres_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003407 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003408 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003409 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003410 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003411 }
3412 }
Radek Krejci345ad742015-06-03 11:04:18 +02003413
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003414 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003415 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003416 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003417 goto error;
3418 }
3419 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003420 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003421 goto error;
3422 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003423
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003424 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3425 if (c_tpdf) {
3426 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3427 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003428 if (c_must) {
3429 list->must = calloc(c_must, sizeof *list->must);
3430 }
3431 if (c_ftrs) {
3432 list->features = calloc(c_ftrs, sizeof *list->features);
3433 }
Radek Krejci73adb602015-07-02 18:07:40 +02003434 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003435 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003436 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003438 if (r) {
3439 goto error;
3440 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003441 } else if (!strcmp(sub->name, "if-feature")) {
3442 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003443 unres_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003444 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003445 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003446 if (r) {
3447 goto error;
3448 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003449 unres_add_node(module, unres, &list->must[list->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003450 }
3451 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003452
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003453 /* last part - process data nodes */
3454 LY_TREE_FOR_SAFE(root.child, next, sub) {
3455 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003456 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003458 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003459 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003460 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003462 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003463 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003464 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003465 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003466 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003468 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003469 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003470 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003471 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003472 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003473 goto error;
3474 }
Radek Krejci73adb602015-07-02 18:07:40 +02003475
3476 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003477 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003478
Radek Krejci1d82ef62015-08-07 14:44:40 +02003479 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003480 goto error;
3481 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003482
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003483 if (!key_str) {
3484 /* config false list without a key */
3485 return retval;
3486 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003487 unres_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line);
Radek Krejci812b10a2015-05-28 16:48:25 +02003488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 /* process unique statements */
3490 if (c_uniq) {
3491 list->unique = calloc(c_uniq, sizeof *list->unique);
3492 }
3493 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003494 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003495 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003496 GETVAL(value, sub, "tag");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003497 unres_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value, LOGLINE(sub));
Radek Krejci1e9b9992015-06-04 17:57:04 +02003498
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003499 lyxml_free_elem(module->ctx, sub);
3500 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003501
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003502 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003503
3504error:
3505
Radek Krejci1d82ef62015-08-07 14:44:40 +02003506 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 while (root.child) {
3508 lyxml_free_elem(module->ctx, root.child);
3509 }
3510 while (uniq.child) {
3511 lyxml_free_elem(module->ctx, uniq.child);
3512 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003513
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003514 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003515}
3516
Radek Krejci76512572015-08-04 09:47:08 +02003517static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003518read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3519 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003520{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003522 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003523 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003524 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003525 const char *value;
3526 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003527 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003528
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003529 /* init */
3530 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003531
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003532 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003533 cont->nodetype = LYS_CONTAINER;
3534 cont->prev = (struct lys_node *)cont;
3535 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003536
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003537 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3538 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003539 goto error;
3540 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003541
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 /* process container's specific children */
3543 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003544 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003545 /* garbage */
3546 lyxml_free_elem(module->ctx, sub);
3547 continue;
3548 }
3549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003550 if (!strcmp(sub->name, "presence")) {
3551 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003552 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003553 goto error;
3554 }
3555 GETVAL(value, sub, "value");
3556 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003557
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003558 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003559 } else if (!strcmp(sub->name, "when")) {
3560 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003561 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003562 goto error;
3563 }
3564
3565 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003566 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003567 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003568 goto error;
3569 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003570 unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003571 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003572
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003573 /* data statements */
3574 } else if (!strcmp(sub->name, "container") ||
3575 !strcmp(sub->name, "leaf-list") ||
3576 !strcmp(sub->name, "leaf") ||
3577 !strcmp(sub->name, "list") ||
3578 !strcmp(sub->name, "choice") ||
3579 !strcmp(sub->name, "uses") ||
3580 !strcmp(sub->name, "grouping") ||
3581 !strcmp(sub->name, "anyxml")) {
3582 lyxml_unlink_elem(sub);
3583 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003584
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003585 /* array counters */
3586 } else if (!strcmp(sub->name, "typedef")) {
3587 c_tpdf++;
3588 } else if (!strcmp(sub->name, "must")) {
3589 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003590 } else if (!strcmp(sub->name, "if-feature")) {
3591 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003592 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003593 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003594 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 }
3596 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003597
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003598 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3599 if (c_tpdf) {
3600 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3601 }
3602 if (c_must) {
3603 cont->must = calloc(c_must, sizeof *cont->must);
3604 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003605 if (c_ftrs) {
3606 cont->features = calloc(c_ftrs, sizeof *cont->features);
3607 }
Radek Krejci800af702015-06-02 13:46:01 +02003608
Radek Krejci73adb602015-07-02 18:07:40 +02003609 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003610 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003611 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 if (r) {
3613 goto error;
3614 }
3615 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003616 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003617 if (r) {
3618 goto error;
3619 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003620 unres_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003621 } else if (!strcmp(sub->name, "if-feature")) {
3622 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003623 unres_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 /* last part - process data nodes */
3628 LY_TREE_FOR_SAFE(root.child, next, sub) {
3629 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003630 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003632 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003634 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003635 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003636 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003638 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003639 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003640 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003641 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003642 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003644 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003645 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003646 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 goto error;
3648 }
Radek Krejci73adb602015-07-02 18:07:40 +02003649
3650 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003652
Radek Krejci1d82ef62015-08-07 14:44:40 +02003653 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003654 goto error;
3655 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003657 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003658
3659error:
3660
Radek Krejci1d82ef62015-08-07 14:44:40 +02003661 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003662 while (root.child) {
3663 lyxml_free_elem(module->ctx, root.child);
3664 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003665
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003666 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003667}
3668
Radek Krejci76512572015-08-04 09:47:08 +02003669static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003670read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003671 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003672{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003673 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003674 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003675 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003676 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003677 int r;
3678 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003679
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 /* init */
3681 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003684 grp->nodetype = LYS_GROUPING;
3685 grp->prev = (struct lys_node *)grp;
3686 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003687
Radek Krejci1d82ef62015-08-07 14:44:40 +02003688 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003689 goto error;
3690 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003691
Radek Krejci1d82ef62015-08-07 14:44:40 +02003692 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003693 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3694 /* garbage */
3695 lyxml_free_elem(module->ctx, sub);
3696 continue;
3697 }
3698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003699 /* data statements */
3700 if (!strcmp(sub->name, "container") ||
3701 !strcmp(sub->name, "leaf-list") ||
3702 !strcmp(sub->name, "leaf") ||
3703 !strcmp(sub->name, "list") ||
3704 !strcmp(sub->name, "choice") ||
3705 !strcmp(sub->name, "uses") ||
3706 !strcmp(sub->name, "grouping") ||
3707 !strcmp(sub->name, "anyxml")) {
3708 lyxml_unlink_elem(sub);
3709 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 /* array counters */
3712 } else if (!strcmp(sub->name, "typedef")) {
3713 c_tpdf++;
3714 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003715 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 goto error;
3717 }
3718 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003719
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3721 if (c_tpdf) {
3722 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3723 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003724 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003725 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003726
Radek Krejci73adb602015-07-02 18:07:40 +02003727 if (r) {
3728 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003729 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003730 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 /* last part - process data nodes */
3733 LY_TREE_FOR_SAFE(root.child, next, sub) {
3734 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003735 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003736 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003737 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003738 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003740 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003741 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003742 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003743 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003744 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003745 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003747 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003748 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003749 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003750 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003752 goto error;
3753 }
Radek Krejci73adb602015-07-02 18:07:40 +02003754
3755 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757
Radek Krejci1d82ef62015-08-07 14:44:40 +02003758 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003759 goto error;
3760 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003762 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003763
3764error:
3765
Radek Krejci1d82ef62015-08-07 14:44:40 +02003766 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 while (root.child) {
3768 lyxml_free_elem(module->ctx, root.child);
3769 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003770
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003771 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003772}
3773
Radek Krejci76512572015-08-04 09:47:08 +02003774static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003775read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3776 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003777{
Radek Krejcie0674f82015-06-15 13:58:51 +02003778 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003779 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003780 struct lys_node *retval;
Radek Krejci4608ada2015-08-05 16:04:37 +02003781 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003782 int r;
3783 int c_tpdf = 0;
3784
Radek Krejcie0674f82015-06-15 13:58:51 +02003785 /* init */
3786 memset(&root, 0, sizeof root);
3787
Michal Vasko38d01f72015-06-15 09:41:06 +02003788 inout = calloc(1, sizeof *inout);
3789
3790 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003791 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003792 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003793 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003794 } else {
3795 assert(0);
3796 }
3797
Radek Krejci76512572015-08-04 09:47:08 +02003798 inout->prev = (struct lys_node *)inout;
3799 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003800
Radek Krejci6a113852015-07-03 16:04:20 +02003801 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003802 goto error;
3803 }
3804
Michal Vasko38d01f72015-06-15 09:41:06 +02003805 /* data statements */
3806 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003807 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3808 /* garbage */
3809 lyxml_free_elem(module->ctx, sub);
3810 continue;
3811 }
3812
Michal Vasko38d01f72015-06-15 09:41:06 +02003813 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 !strcmp(sub->name, "leaf-list") ||
3815 !strcmp(sub->name, "leaf") ||
3816 !strcmp(sub->name, "list") ||
3817 !strcmp(sub->name, "choice") ||
3818 !strcmp(sub->name, "uses") ||
3819 !strcmp(sub->name, "grouping") ||
3820 !strcmp(sub->name, "anyxml")) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003821 lyxml_unlink_elem(sub);
3822 lyxml_add_child(&root, sub);
3823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003824 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003825 } else if (!strcmp(sub->name, "typedef")) {
3826 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003827
Michal Vasko38d01f72015-06-15 09:41:06 +02003828 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003829 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003830 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003831 }
3832 }
3833
3834 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3835 if (c_tpdf) {
3836 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3837 }
3838
Radek Krejci73adb602015-07-02 18:07:40 +02003839 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003840 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003841
Radek Krejci73adb602015-07-02 18:07:40 +02003842 if (r) {
3843 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003844 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003845 }
3846
3847 /* last part - process data nodes */
3848 LY_TREE_FOR_SAFE(root.child, next, sub) {
3849 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003850 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003851 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003852 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003853 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003854 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003855 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003856 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003857 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003858 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003859 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003860 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003861 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003862 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003863 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003864 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003865 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003866 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003867 goto error;
3868 }
Radek Krejci73adb602015-07-02 18:07:40 +02003869
3870 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003871 }
3872
Radek Krejci1d82ef62015-08-07 14:44:40 +02003873 if (parent && lys_node_addchild(parent, retval)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003874 goto error;
3875 }
3876
3877 return retval;
3878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003879error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003880
Radek Krejci1d82ef62015-08-07 14:44:40 +02003881 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003882 while (root.child) {
3883 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003884 }
3885
3886 return NULL;
3887}
3888
Radek Krejci76512572015-08-04 09:47:08 +02003889static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003890read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3891 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003892{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003893 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003894 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003895 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003896 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003897 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003898 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003899 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003900
Michal Vaskoc6551b32015-06-16 10:51:43 +02003901 memset(&root, 0, sizeof root);
3902
Michal Vasko0ea41032015-06-16 08:53:55 +02003903 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02003904 notif->nodetype = LYS_NOTIF;
3905 notif->prev = (struct lys_node *)notif;
3906 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02003907
Radek Krejci6a113852015-07-03 16:04:20 +02003908 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003909 goto error;
3910 }
3911
3912 /* process rpc's specific children */
3913 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003914 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3915 /* garbage */
3916 lyxml_free_elem(module->ctx, sub);
3917 continue;
3918 }
3919
Michal Vasko0ea41032015-06-16 08:53:55 +02003920 /* data statements */
3921 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003922 !strcmp(sub->name, "leaf-list") ||
3923 !strcmp(sub->name, "leaf") ||
3924 !strcmp(sub->name, "list") ||
3925 !strcmp(sub->name, "choice") ||
3926 !strcmp(sub->name, "uses") ||
3927 !strcmp(sub->name, "grouping") ||
3928 !strcmp(sub->name, "anyxml")) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003929 lyxml_unlink_elem(sub);
3930 lyxml_add_child(&root, sub);
3931
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003932 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02003933 } else if (!strcmp(sub->name, "typedef")) {
3934 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003935 } else if (!strcmp(sub->name, "if-feature")) {
3936 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02003937 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003938 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02003939 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02003940 }
3941 }
3942
3943 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3944 if (c_tpdf) {
3945 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
3946 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003947 if (c_ftrs) {
3948 notif->features = calloc(c_ftrs, sizeof *notif->features);
3949 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003950
Radek Krejci73adb602015-07-02 18:07:40 +02003951 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003952 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003953 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003954
3955 if (r) {
3956 goto error;
3957 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003958 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003959 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003960 unres_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko0ea41032015-06-16 08:53:55 +02003961 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003962 }
3963
3964 /* last part - process data nodes */
3965 LY_TREE_FOR_SAFE(root.child, next, sub) {
3966 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003967 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003968 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003969 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003970 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003971 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003972 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003973 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003974 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003975 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003976 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003977 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003978 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003979 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003980 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003981 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003982 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003983 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003984 goto error;
3985 }
Radek Krejci73adb602015-07-02 18:07:40 +02003986
3987 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02003988 }
3989
Radek Krejci1d82ef62015-08-07 14:44:40 +02003990 if (parent && lys_node_addchild(parent, retval)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003991 goto error;
3992 }
3993
3994 return retval;
3995
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003996error:
Michal Vasko0ea41032015-06-16 08:53:55 +02003997
Radek Krejci1d82ef62015-08-07 14:44:40 +02003998 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02003999 while (root.child) {
4000 lyxml_free_elem(module->ctx, root.child);
4001 }
4002
4003 return NULL;
4004}
4005
Radek Krejci76512572015-08-04 09:47:08 +02004006static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004007read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4008 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004009{
Radek Krejcie0674f82015-06-15 13:58:51 +02004010 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004011 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004012 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004013 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004014 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004015 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004016 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004017
Radek Krejcie0674f82015-06-15 13:58:51 +02004018 /* init */
4019 memset(&root, 0, sizeof root);
4020
Michal Vasko38d01f72015-06-15 09:41:06 +02004021 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004022 rpc->nodetype = LYS_RPC;
4023 rpc->prev = (struct lys_node *)rpc;
4024 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004025
Radek Krejci6a113852015-07-03 16:04:20 +02004026 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004027 goto error;
4028 }
4029
4030 /* process rpc's specific children */
4031 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004032 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4033 /* garbage */
4034 lyxml_free_elem(module->ctx, sub);
4035 continue;
4036 }
4037
Michal Vasko38d01f72015-06-15 09:41:06 +02004038 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004039 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004040 && (rpc->child->nodetype == LYS_INPUT
4041 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004042 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004043 goto error;
4044 }
4045 lyxml_unlink_elem(sub);
4046 lyxml_add_child(&root, sub);
4047 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004048 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004049 && (rpc->child->nodetype == LYS_INPUT
4050 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004051 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004052 goto error;
4053 }
4054 lyxml_unlink_elem(sub);
4055 lyxml_add_child(&root, sub);
4056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004057 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004058 } else if (!strcmp(sub->name, "grouping")) {
4059 lyxml_unlink_elem(sub);
4060 lyxml_add_child(&root, sub);
4061
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004062 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004063 } else if (!strcmp(sub->name, "typedef")) {
4064 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004065 } else if (!strcmp(sub->name, "if-feature")) {
4066 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004067 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004068 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004069 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004070 }
4071 }
4072
4073 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4074 if (c_tpdf) {
4075 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4076 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004077 if (c_ftrs) {
4078 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4079 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004080
Radek Krejci73adb602015-07-02 18:07:40 +02004081 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004082 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004083 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004084
4085 if (r) {
4086 goto error;
4087 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004088 } else if (!strcmp(sub->name, "if-feature")) {
4089 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02004090 unres_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko38d01f72015-06-15 09:41:06 +02004091 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004092 }
4093
4094 /* last part - process data nodes */
4095 LY_TREE_FOR_SAFE(root.child, next, sub) {
4096 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004097 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004098 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004099 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004100 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004101 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004102 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004103 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004104 goto error;
4105 }
Radek Krejci73adb602015-07-02 18:07:40 +02004106
4107 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004108 }
4109
Radek Krejci1d82ef62015-08-07 14:44:40 +02004110 if (parent && lys_node_addchild(parent, retval)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004111 goto error;
4112 }
4113
4114 return retval;
4115
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004116error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004117
Radek Krejci1d82ef62015-08-07 14:44:40 +02004118 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004119 while (root.child) {
4120 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004121 }
4122
4123 return NULL;
4124}
4125
Radek Krejci74705112015-06-05 10:25:44 +02004126/*
4127 * resolve - referenced grouping should be bounded to the namespace (resolved)
4128 * only when uses does not appear in grouping. In a case of grouping's uses,
4129 * we just get information but we do not apply augment or refine to it.
4130 */
Radek Krejci76512572015-08-04 09:47:08 +02004131static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004132read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *node, int resolve,
4133 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004134{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004135 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004136 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004137 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004138 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004139 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004140 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004141
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004142 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004143 uses->nodetype = LYS_USES;
4144 uses->prev = (struct lys_node *)uses;
4145 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004146
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004147 GETVAL(value, node, "name");
4148 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004149
Radek Krejci6a113852015-07-03 16:04:20 +02004150 if (read_yin_common(module, parent, retval, node, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004151 goto error;
4152 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004154 /* get other properties of uses */
4155 LY_TREE_FOR_SAFE(node->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004156 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4157 /* garbage */
4158 lyxml_free_elem(module->ctx, sub);
4159 continue;
4160 }
4161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004162 if (!strcmp(sub->name, "refine")) {
4163 c_ref++;
4164 } else if (!strcmp(sub->name, "augment")) {
4165 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004166 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004167 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004168 } else if (!strcmp(sub->name, "when")) {
4169 if (uses->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004170 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, node->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004171 goto error;
4172 }
4173
4174 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004175 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004176 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004177 goto error;
4178 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 unres_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004180 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004181 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004182 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004183 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004184 }
4185 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004186
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004187 /* process properties with cardinality 0..n */
4188 if (c_ref) {
4189 uses->refine = calloc(c_ref, sizeof *uses->refine);
4190 }
4191 if (c_aug) {
4192 uses->augment = calloc(c_aug, sizeof *uses->augment);
4193 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004194 if (c_ftrs) {
4195 uses->features = calloc(c_ftrs, sizeof *uses->features);
4196 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004197
Radek Krejci73adb602015-07-02 18:07:40 +02004198 LY_TREE_FOR(node->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004200 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4201 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004202 goto error;
4203 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004204 } else if (!strcmp(sub->name, "augment")) {
4205 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4206 if (r) {
4207 goto error;
4208 }
4209 } else if (!strcmp(sub->name, "if-feature")) {
4210 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02004211 unres_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004212 }
4213 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004214
Radek Krejci1d82ef62015-08-07 14:44:40 +02004215 unres_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(node));
Radek Krejci74705112015-06-05 10:25:44 +02004216
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 if (parent && lys_node_addchild(parent, retval)) {
Radek Krejci368c38f2015-06-15 15:09:55 +02004218 goto error;
4219 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004221 if (resolve) {
4222 /* inherit config flag */
4223 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004224 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225 } else {
4226 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004227 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004228 }
4229 }
Radek Krejcib388c152015-06-04 17:03:03 +02004230
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004231 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004232
4233error:
4234
Radek Krejci1d82ef62015-08-07 14:44:40 +02004235 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004237 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004238}
4239
Radek Krejciefaeba32015-05-27 14:30:57 +02004240/* common code for yin_read_module() and yin_read_submodule() */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004241static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004242read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004243{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004244 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004245 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004246 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4247 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004249 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004250 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004251 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004252 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 +02004253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 /* init */
4255 memset(&root, 0, sizeof root);
4256 memset(&grps, 0, sizeof grps);
4257 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004258 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004260 /*
4261 * in the first run, we process elements with cardinality of 1 or 0..1 and
4262 * count elements with cardinality 0..n. Data elements (choices, containers,
4263 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4264 * need have all top-level and groupings already prepared at that time. In
4265 * the middle loop, we process other elements with carinality of 0..n since
4266 * we need to allocate arrays to store them.
4267 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004268 LY_TREE_FOR_SAFE(yin->child, next, child) {
4269 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004270 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004271 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 continue;
4273 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004274
Radek Krejci1d82ef62015-08-07 14:44:40 +02004275 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004276 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004277 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004278 goto error;
4279 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004280 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004281 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004282 lyxml_free_elem(ctx, child);
4283 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004285 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004286 goto error;
4287 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004288 GETVAL(value, child, "value");
4289 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004290 goto error;
4291 }
4292 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004293 lyxml_free_elem(ctx, child);
4294 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004296 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004297 goto error;
4298 }
4299 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004300 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004301 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004302 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004303 }
4304 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004305 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004306 goto error;
4307 }
Radek Krejcif3886932015-06-04 17:36:06 +02004308
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004309 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004310 if (!child->child) {
4311 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004312 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004313 } else if (strcmp(child->child->name, "prefix")) {
4314 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004315 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004316 } else if (child->child->next) {
4317 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 goto error;
4319 }
4320 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004321 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004322 /* check here differs from a generic prefix check, since this prefix
4323 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004324 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004325 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004326 goto error;
4327 }
4328 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004331 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004332
4333 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004334 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004335 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004336 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004337 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004338 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004339 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004340 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004341 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004342 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004343 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004344 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004345 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004346 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004347 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004348 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004349 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004352 } else if (!strcmp(child->name, "container") ||
4353 !strcmp(child->name, "leaf-list") ||
4354 !strcmp(child->name, "leaf") ||
4355 !strcmp(child->name, "list") ||
4356 !strcmp(child->name, "choice") ||
4357 !strcmp(child->name, "uses") ||
4358 !strcmp(child->name, "anyxml")) {
4359 lyxml_unlink_elem(child);
4360 lyxml_add_child(&root, child);
4361 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 /* keep groupings separated and process them before other data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004363 lyxml_unlink_elem(child);
4364 lyxml_add_child(&grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004367 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004368 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004369 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 goto error;
4371 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004372 module->dsc = read_yin_subnode(ctx, child, "text");
4373 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004374 if (!module->dsc) {
4375 goto error;
4376 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004377 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004378 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004379 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 goto error;
4381 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004382 module->ref = read_yin_subnode(ctx, child, "text");
4383 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004384 if (!module->ref) {
4385 goto error;
4386 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004387 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004389 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 goto error;
4391 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004392 module->org = read_yin_subnode(ctx, child, "text");
4393 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004394 if (!module->org) {
4395 goto error;
4396 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004397 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004398 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004399 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 goto error;
4401 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004402 module->contact = read_yin_subnode(ctx, child, "text");
4403 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004404 if (!module->contact) {
4405 goto error;
4406 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004407 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004408 /* TODO: support YANG 1.1 ? */
4409 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004410 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 goto error;
4412 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004413 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004414 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004415 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004416 goto error;
4417 }
4418 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004419 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004422 } else if (!strcmp(child->name, "rpc")) {
4423 lyxml_unlink_elem(child);
4424 lyxml_add_child(&rpcs, child);
4425 } else if (!strcmp(child->name, "notification")) {
4426 lyxml_unlink_elem(child);
4427 lyxml_add_child(&notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004428
Radek Krejci1d82ef62015-08-07 14:44:40 +02004429 } else if (!strcmp(child->name, "extension")) {
4430 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004431
Radek Krejci6764bb32015-07-03 15:16:04 +02004432 /* we have 2 supported (hardcoded) extensions:
4433 * NACM's default-deny-write and default-deny-all
4434 */
4435 if (strcmp(module->ns, LY_NSNACM) ||
4436 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4437 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004438 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004439 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004441 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004443 }
4444 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004445
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004446 if (!submodule) {
4447 /* check for mandatory statements */
4448 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004449 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004450 goto error;
4451 }
4452 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004453 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 goto error;
4455 }
4456 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004457
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 /* allocate arrays for elements with cardinality of 0..n */
4459 if (c_imp) {
4460 module->imp = calloc(c_imp, sizeof *module->imp);
4461 }
4462 if (c_rev) {
4463 module->rev = calloc(c_rev, sizeof *module->rev);
4464 }
4465 if (c_tpdf) {
4466 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4467 }
4468 if (c_ident) {
4469 module->ident = calloc(c_ident, sizeof *module->ident);
4470 }
4471 if (c_inc) {
4472 module->inc = calloc(c_inc, sizeof *module->inc);
4473 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004474 if (c_aug) {
4475 module->augment = calloc(c_aug, sizeof *module->augment);
4476 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004477 if (c_ftrs) {
4478 module->features = calloc(c_ftrs, sizeof *module->features);
4479 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004480 if (c_dev) {
4481 module->deviation = calloc(c_dev, sizeof *module->deviation);
4482 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004485 LY_TREE_FOR(yin->child, child) {
4486 if (!strcmp(child->name, "import")) {
4487 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004488 module->imp_size++;
4489 if (r) {
4490 goto error;
4491 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004492
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 /* check duplicities in imported modules */
4494 for (i = 0; i < module->imp_size - 1; i++) {
4495 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004496 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004497 goto error;
4498 }
4499 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004500 } else if (!strcmp(child->name, "include")) {
4501 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004502 module->inc_size++;
4503 if (r) {
4504 goto error;
4505 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004507 /* check duplications in include submodules */
4508 for (i = 0; i < module->inc_size - 1; i++) {
4509 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004510 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004511 module->inc[i].submodule->name);
4512 goto error;
4513 }
4514 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004515 } else if (!strcmp(child->name, "revision")) {
4516 GETVAL(value, child, "date");
4517 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 goto error;
4519 }
4520 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4521 /* check uniqueness of the revision date - not required by RFC */
4522 for (i = 0; i < module->rev_size; i++) {
4523 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004524 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004525 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004526 }
4527 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004528
Radek Krejci1d82ef62015-08-07 14:44:40 +02004529 LY_TREE_FOR(child->child, child2) {
4530 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004531 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004532 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004533 goto error;
4534 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004535 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 if (!module->rev[module->rev_size].dsc) {
4537 goto error;
4538 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004539 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004540 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004541 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004542 goto error;
4543 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004544 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004545 if (!module->rev[module->rev_size].ref) {
4546 goto error;
4547 }
4548 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004549 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 goto error;
4551 }
4552 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 /* keep the latest revision at position 0 */
4555 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4556 /* switch their position */
4557 value = strdup(module->rev[0].date);
4558 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4559 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4560 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4563 value = module->rev[0].dsc;
4564 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4565 module->rev[module->rev_size].dsc = value;
4566 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004568 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4569 value = module->rev[0].ref;
4570 module->rev[0].ref = module->rev[module->rev_size].ref;
4571 module->rev[module->rev_size].ref = value;
4572 }
4573 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004574
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004575 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004576 } else if (!strcmp(child->name, "typedef")) {
4577 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004578 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004579
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004580 if (r) {
4581 goto error;
4582 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004583 } else if (!strcmp(child->name, "identity")) {
4584 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004585 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004587 if (r) {
4588 goto error;
4589 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004590 } else if (!strcmp(child->name, "feature")) {
4591 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004592 module->features_size++;
4593
4594 if (r) {
4595 goto error;
4596 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004597 } else if (!strcmp(child->name, "augment")) {
4598 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004599 module->augment_size++;
4600
4601 if (r) {
4602 goto error;
4603 }
4604
4605 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4606 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004607 } else if (!strcmp(child->name, "deviation")) {
4608 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004609 module->deviation_size++;
4610
4611 if (r) {
4612 goto error;
4613 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004614 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004616
Radek Krejcif5be10f2015-06-16 13:29:36 +02004617 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004618 * refer to them
4619 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004620 LY_TREE_FOR_SAFE(grps.child, next, child) {
4621 node = read_yin_grouping(module, NULL, child, 0, unres);
4622 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004623 goto error;
4624 }
Radek Krejci74705112015-06-05 10:25:44 +02004625
Radek Krejci1d82ef62015-08-07 14:44:40 +02004626 lyxml_free_elem(ctx, child);
Radek Krejci73adb602015-07-02 18:07:40 +02004627
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 /* include data element */
4629 if (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004630 module->data->prev->next = node;
4631 node->prev = module->data->prev;
4632 module->data->prev = node;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004633 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004634 module->data = node;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004635 }
4636 }
Radek Krejci74705112015-06-05 10:25:44 +02004637
Radek Krejcif5be10f2015-06-16 13:29:36 +02004638 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004639 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004640
Radek Krejci1d82ef62015-08-07 14:44:40 +02004641 if (!strcmp(child->name, "container")) {
4642 node = read_yin_container(module, NULL, child, 1, unres);
4643 } else if (!strcmp(child->name, "leaf-list")) {
4644 node = read_yin_leaflist(module, NULL, child, 1, unres);
4645 } else if (!strcmp(child->name, "leaf")) {
4646 node = read_yin_leaf(module, NULL, child, 1, unres);
4647 } else if (!strcmp(child->name, "list")) {
4648 node = read_yin_list(module, NULL, child, 1, unres);
4649 } else if (!strcmp(child->name, "choice")) {
4650 node = read_yin_choice(module, NULL, child, 1, unres);
4651 } else if (!strcmp(child->name, "uses")) {
4652 node = read_yin_uses(module, NULL, child, 1, unres);
4653 } else if (!strcmp(child->name, "anyxml")) {
4654 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004656 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 goto error;
4658 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004659
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 lyxml_free_elem(ctx, child);
Radek Krejci73adb602015-07-02 18:07:40 +02004661
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004662 /* include data element */
4663 if (module->data) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004664 module->data->prev->next = node;
4665 node->prev = module->data->prev;
4666 module->data->prev = node;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004667 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004668 module->data = node;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004669 }
4670 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004671
4672 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004673 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4674 node = read_yin_rpc(module, NULL, child, 0, unres);
4675 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004676 goto error;
4677 }
4678
Radek Krejci1d82ef62015-08-07 14:44:40 +02004679 lyxml_free_elem(ctx, child);
Radek Krejci73adb602015-07-02 18:07:40 +02004680
Radek Krejcif5be10f2015-06-16 13:29:36 +02004681 /* include rpc element */
4682 if (module->rpc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004683 module->rpc->prev->next = node;
4684 node->prev = module->rpc->prev;
4685 module->rpc->prev = node;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004686 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004687 module->rpc = node;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004688 }
4689 }
4690
4691 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004692 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4693 node = read_yin_notif(module, NULL, child, 0, unres);
4694 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004695 goto error;
4696 }
4697
Radek Krejci1d82ef62015-08-07 14:44:40 +02004698 lyxml_free_elem(ctx, child);
Radek Krejci73adb602015-07-02 18:07:40 +02004699
Radek Krejcif5be10f2015-06-16 13:29:36 +02004700 /* include notification element */
4701 if (module->notif) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004702 module->notif->prev->next = node;
4703 node->prev = module->notif->prev;
4704 module->notif->prev = node;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004705 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004706 module->notif = node;
Radek Krejcif5be10f2015-06-16 13:29:36 +02004707 }
4708 }
4709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004711
4712error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004713 /* cleanup */
4714 while (root.child) {
4715 lyxml_free_elem(module->ctx, root.child);
4716 }
4717 while (grps.child) {
4718 lyxml_free_elem(module->ctx, grps.child);
4719 }
4720 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004721 lyxml_free_elem(module->ctx, rpcs.child);
4722 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004723
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004724 free(unres->item);
4725 unres->item = NULL;
4726 free(unres->type);
4727 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004728 free(unres->str_snode);
4729 unres->str_snode = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004730 free(unres->line);
4731 unres->line = NULL;
4732 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004734 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004735}
4736
Radek Krejcib8048692015-08-05 13:36:34 +02004737struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004738yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004739{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004740 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004741 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004742 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004746 yin = lyxml_read(module->ctx, data, 0);
4747 if (!yin) {
4748 return NULL;
4749 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004750
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004751 /* check root element */
4752 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004753 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004754 goto error;
4755 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004756
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004757 GETVAL(value, yin, "name");
4758 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4759 goto error;
4760 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004761
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004762 submodule = calloc(1, sizeof *submodule);
4763 if (!submodule) {
4764 LOGMEM;
4765 goto error;
4766 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004767
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004768 submodule->ctx = module->ctx;
4769 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4770 submodule->type = 1;
4771 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004772 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004773
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004774 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004775 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 goto error;
4777 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 /* cleanup */
4780 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004783
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004784 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004785
4786error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 /* cleanup */
4788 lyxml_free_elem(module->ctx, yin);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004789 lys_submodule_free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02004790
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004791 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004792}
4793
Radek Krejcib8048692015-08-05 13:36:34 +02004794struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004795yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004796{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004797 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004798 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004799 const char *value;
4800 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004802 yin = lyxml_read(ctx, data, 0);
4803 if (!yin) {
4804 return NULL;
4805 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004806
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004807 /* check root element */
4808 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004809 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 goto error;
4811 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004812
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 GETVAL(value, yin, "name");
4814 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4815 goto error;
4816 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 module = calloc(1, sizeof *module);
4819 if (!module) {
4820 LOGMEM;
4821 goto error;
4822 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004823
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004824 module->ctx = ctx;
4825 module->name = lydict_insert(ctx, value, strlen(value));
4826 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004827 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004828
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004829 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004830 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 goto error;
4832 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004833
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004834 /* add to the context's list of modules */
4835 if (ctx->models.used == ctx->models.size) {
4836 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4837 if (!newlist) {
4838 LOGMEM;
4839 goto error;
4840 }
4841 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4842 newlist[i] = NULL;
4843 }
4844 ctx->models.size *= 2;
4845 ctx->models.list = newlist;
4846 }
4847 for (i = 0; ctx->models.list[i]; i++) {
4848 /* check name (name/revision) and namespace uniqueness */
4849 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004850 if (ctx->models.list[i]->rev_size == module->rev_size) {
4851 /* both have the same number of revisions */
4852 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4853 /* both have the same revision -> we already have the same module */
4854 /* so free the new one and update the old one's implement flag if needed */
4855 lyxml_free_elem(ctx, yin);
4856 lys_free(module);
4857
4858 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4859
4860 if (implement && !ctx->models.list[i]->implemented) {
4861 lyp_set_implemented(ctx->models.list[i]);
4862 }
4863 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004864 }
4865 }
Radek Krejcif647e612015-07-30 11:36:07 +02004866 /* else (both elses) keep searching, for now the caller is just adding
4867 * another revision of an already present schema
4868 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004869 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4870 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4871 ctx->models.list[i]->name, module->name, module->ns);
4872 goto error;
4873 }
4874 }
4875 ctx->models.list[i] = module;
4876 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004877 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004878
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004879 /* cleanup */
4880 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004881
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004882 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004884 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004885
4886error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004887 /* cleanup */
4888 lyxml_free_elem(ctx, yin);
Radek Krejci912da452015-07-29 14:10:06 +02004889 lys_free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004890
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004891 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004892}