blob: 35ff728684c27d74c74fe9ec3837f6b4909336cb [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 Krejci998a0b82015-08-17 13:14:36 +020033#include "libyang.h"
34#include "common.h"
35#include "context.h"
36#include "dict.h"
37#include "parser.h"
38#include "parse.h"
39#include "resolve.h"
40#include "tree_internal.h"
41#include "xml.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020042
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 Krejcia9544502015-08-14 08:24:29 +020084static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +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
Michal Vasko591e0b22015-08-13 13:53:43 +02001925 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001926 GETVAL(value, yin, "target-node");
1927 aug->target_name = lydict_insert(module->ctx, value, 0);
1928 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001929
Radek Krejci76512572015-08-04 09:47:08 +02001930 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001931 goto error;
1932 }
1933
1934 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001935 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1936 /* garbage */
1937 lyxml_free_elem(module->ctx, child);
1938 continue;
1939 }
1940
Radek Krejci3cf9e222015-06-18 11:37:50 +02001941 if (!strcmp(child->name, "if-feature")) {
1942 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001943 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001944 } else if (!strcmp(child->name, "when")) {
1945 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001946 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001947 goto error;
1948 }
1949
1950 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001951 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001952 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001953 goto error;
1954 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02001955 unres_add_node(module, unres, aug->when, UNRES_WHEN, (struct lys_node *)aug, LOGLINE(child));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001956 lyxml_free_elem(module->ctx, child);
1957 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001958
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001959 /* check allowed data sub-statements */
1960 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001961 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001962 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001963 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001964 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001965 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001966 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001967 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001968 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001969 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001970 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001971 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001972 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001973 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001974 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001975 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001976 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001977 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001978 goto error;
1979 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980
Radek Krejci1d82ef62015-08-07 14:44:40 +02001981 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001982 goto error;
1983 }
1984
1985 /* check for mandatory nodes - if the target node is in another module
1986 * the added nodes cannot be mandatory
1987 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001988 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001989 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001990 goto error;
1991 }
1992
Radek Krejci1d82ef62015-08-07 14:44:40 +02001993 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001994 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001995 }
1996
1997 if (c) {
1998 aug->features = calloc(c, sizeof *aug->features);
1999 }
2000
2001 LY_TREE_FOR_SAFE(yin->child, next, child) {
2002 if (!strcmp(child->name, "if-feature")) {
2003 GETVAL(value, child, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002004 unres_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child));
Radek Krejci73adb602015-07-02 18:07:40 +02002005 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002006 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002007 }
2008
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002009 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002010 * connected to the tree and adjusted (if possible right now).
2011 * However, if this is augment in a uses, it gets resolved
2012 * when the uses does and cannot be resolved now for sure
2013 * (the grouping was not yet copied into uses).
2014 */
2015 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002016 if (resolve_augment(aug, aug->child, module)) {
2017 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2018 goto error;
2019 }
Michal Vasko49291b32015-08-06 09:49:41 +02002020 }
Radek Krejci106efc02015-06-10 14:36:27 +02002021
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002022 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002023
2024error:
2025
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002026 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002027}
2028
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002029static int
Radek Krejcib8048692015-08-05 13:36:34 +02002030fill_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 +02002031 struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002032{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002033 struct lyxml_elem *sub, *next;
2034 const char *value;
2035 char *endptr;
2036 int f_mand = 0, f_min = 0, f_max = 0;
2037 int c_must = 0;
2038 int r;
2039 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002040
Radek Krejci76512572015-08-04 09:47:08 +02002041 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002042 goto error;
2043 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002044
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002045 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002046 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002047
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002048 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002049 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2050 /* garbage */
2051 lyxml_free_elem(module->ctx, sub);
2052 continue;
2053 }
2054
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002055 /* limited applicability */
2056 if (!strcmp(sub->name, "default")) {
2057 /* leaf or choice */
2058 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002059 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002060 goto error;
2061 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002062
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002063 /* check possibility of statements combination */
2064 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002065 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002066 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002067 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002068 goto error;
2069 }
2070 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002071 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002072 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002073
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002074 GETVAL(value, sub, "value");
2075 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2076 } else if (!strcmp(sub->name, "mandatory")) {
2077 /* leaf, choice or anyxml */
2078 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002079 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002080 goto error;
2081 }
2082 /* just checking the flags in leaf is not sufficient, we would allow
2083 * multiple mandatory statements with the "false" value
2084 */
2085 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002086
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002087 /* check possibility of statements combination */
2088 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002089 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002090 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002091 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002092 goto error;
2093 }
2094 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002095 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002096 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002097
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002098 GETVAL(value, sub, "value");
2099 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002100 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002101 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002102 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002104 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002105 goto error;
2106 }
2107 } else if (!strcmp(sub->name, "min-elements")) {
2108 /* list or leaf-list */
2109 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002110 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002111 goto error;
2112 }
2113 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 /* check possibility of statements combination */
2116 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002117 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002118 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002119 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002120 goto error;
2121 }
2122 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002123 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002125
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 GETVAL(value, sub, "value");
2127 while (isspace(value[0])) {
2128 value++;
2129 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002130
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002131 /* convert it to uint32_t */
2132 errno = 0;
2133 endptr = NULL;
2134 val = strtoul(value, &endptr, 10);
2135 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002136 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002137 goto error;
2138 }
2139 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002140
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 /* magic - bit 3 in flags means min set */
2142 rfn->flags |= 0x04;
2143 } else if (!strcmp(sub->name, "max-elements")) {
2144 /* list or leaf-list */
2145 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002146 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 goto error;
2148 }
2149 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002150
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002151 /* check possibility of statements combination */
2152 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002153 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002155 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002156 goto error;
2157 }
2158 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002159 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002162 GETVAL(value, sub, "value");
2163 while (isspace(value[0])) {
2164 value++;
2165 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002167 /* convert it to uint32_t */
2168 errno = 0;
2169 endptr = NULL;
2170 val = strtoul(value, &endptr, 10);
2171 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002172 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002173 goto error;
2174 }
2175 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 /* magic - bit 4 in flags means min set */
2178 rfn->flags |= 0x08;
2179 } else if (!strcmp(sub->name, "presence")) {
2180 /* container */
2181 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002182 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 goto error;
2184 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002185
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002186 /* check possibility of statements combination */
2187 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002188 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002189 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002190 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002191 goto error;
2192 }
2193 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002194 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002195 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002197 GETVAL(value, sub, "value");
2198 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2199 } else if (!strcmp(sub->name, "must")) {
2200 /* leaf-list, list, container or anyxml */
2201 /* check possibility of statements combination */
2202 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002203 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002204 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002205 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 goto error;
2207 }
2208 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002209 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002210 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002211
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002213 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002215 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002216 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002217 goto error;
2218 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 lyxml_free_elem(module->ctx, sub);
2221 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002222
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002223 /* process nodes with cardinality of 0..n */
2224 if (c_must) {
2225 rfn->must = calloc(c_must, sizeof *rfn->must);
2226 }
Radek Krejci73adb602015-07-02 18:07:40 +02002227 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002228 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002229 if (r) {
2230 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002231 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002232 unres_add_node(module, unres, &rfn->must[rfn->must_size-1], UNRES_MUST, (struct lys_node *)uses,
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002233 LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002234 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002236 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237
2238error:
2239
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002241}
2242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243static int
Radek Krejcib8048692015-08-05 13:36:34 +02002244fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002245{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 struct lyxml_elem *child;
2247 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002248
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002249 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002250 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2251 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002252 continue;
2253 }
2254
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002255 if (!strcmp(child->name, "prefix")) {
2256 GETVAL(value, child, "value");
2257 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2258 goto error;
2259 }
2260 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2261 } else if (!strcmp(child->name, "revision-date")) {
2262 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002263 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002264 goto error;
2265 }
2266 GETVAL(value, child, "date");
2267 if (check_date(value, LOGLINE(child))) {
2268 goto error;
2269 }
2270 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2271 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002272 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002273 goto error;
2274 }
2275 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002277 /* check mandatory information */
2278 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002279 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 goto error;
2281 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002282
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002283 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002284 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002285 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002286 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2287 if (!imp->module) {
2288 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2289 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002290 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002291 goto error;
2292 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002293 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002294
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002295 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002296
2297error:
2298
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002299 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002300}
2301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302static int
Radek Krejcib8048692015-08-05 13:36:34 +02002303fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002304{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 struct lyxml_elem *child;
2306 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002309 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2310 /* garbage */
2311 continue;
2312 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002313 if (!strcmp(child->name, "revision-date")) {
2314 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002315 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002316 goto error;
2317 }
2318 GETVAL(value, child, "date");
2319 if (check_date(value, LOGLINE(child))) {
2320 goto error;
2321 }
2322 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2323 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002324 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002325 goto error;
2326 }
2327 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002328
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002329 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002330 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002331 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002332 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 +02002333 if (!inc->submodule) {
2334 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2335 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002336 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002337 goto error;
2338 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002339 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002340
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 /* check that belongs-to corresponds */
2342 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002343 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002344 }
2345 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002346 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2347 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002348 goto error;
2349 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002350
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002351 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002352
2353error:
2354
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002355 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002356}
2357
Radek Krejcida04f4a2015-05-21 12:54:09 +02002358/*
2359 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002360 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002361 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002362 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002363static int
Radek Krejcib8048692015-08-05 13:36:34 +02002364read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002365 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002366{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002367 const char *value;
2368 struct lyxml_elem *sub, *next;
2369 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002370
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002371 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002372 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002374
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002375 if (opt & OPT_IDENT) {
2376 GETVAL(value, xmlnode, "name");
2377 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2378 goto error;
2379 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002380 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002381 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002382
Radek Krejci6764bb32015-07-03 15:16:04 +02002383 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002384 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002385 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002386 }
2387
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388 /* process local parameters */
2389 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002390 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002391 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002392 lyxml_free_elem(ctx, sub);
2393 continue;
2394 }
2395 if (strcmp(sub->ns->value, LY_NSYIN)) {
2396 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002397 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002398 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002399 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002400 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002401 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002402 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002403 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002404 goto error;
2405 }
2406 }
2407
2408 /* else garbage */
2409 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002410 continue;
2411 }
2412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002414 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002415 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002416 goto error;
2417 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002418 node->dsc = read_yin_subnode(ctx, sub, "text");
2419 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002420 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002421 }
2422 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002423 if (node->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002424 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002425 goto error;
2426 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002427 node->ref = read_yin_subnode(ctx, sub, "text");
2428 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002429 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002430 }
2431 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002432 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002433 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002434 goto error;
2435 }
2436 GETVAL(value, sub, "value");
2437 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002438 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002439 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002440 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002442 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002443 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002444 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002445 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 }
2447 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002448 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002449 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002450 goto error;
2451 }
2452 GETVAL(value, sub, "value");
2453 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002454 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002456 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002457 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002458 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002459 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002460 }
2461 } else {
2462 /* skip the lyxml_free_elem */
2463 continue;
2464 }
2465 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002467
Radek Krejci1d82ef62015-08-07 14:44:40 +02002468 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002469 /* get config flag from parent */
2470 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002471 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002472 } else {
2473 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002474 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 }
2476 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002477
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002478 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002479
2480error:
2481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002483}
2484
Radek Krejci76512572015-08-04 09:47:08 +02002485static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002486read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002487{
Radek Krejci76512572015-08-04 09:47:08 +02002488 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002489 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002490 const char *value;
2491
2492 retval = calloc(1, sizeof *retval);
2493
2494 GETVAL(value, yin, "condition");
2495 retval->cond = lydict_insert(module->ctx, value, 0);
2496
Radek Krejci73adb602015-07-02 18:07:40 +02002497 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002498 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2499 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002500 continue;
2501 }
2502
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002503 if (!strcmp(child->name, "description")) {
2504 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002505 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002506 goto error;
2507 }
2508 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2509 if (!retval->dsc) {
2510 goto error;
2511 }
2512 } else if (!strcmp(child->name, "reference")) {
2513 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002514 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002515 goto error;
2516 }
2517 retval->ref = read_yin_subnode(module->ctx, child, "text");
2518 if (!retval->ref) {
2519 goto error;
2520 }
2521 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002522 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002523 goto error;
2524 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002525 }
2526
2527 return retval;
2528
2529error:
2530
Radek Krejci1d82ef62015-08-07 14:44:40 +02002531 lys_node_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002532 return NULL;
2533}
2534
Radek Krejci76512572015-08-04 09:47:08 +02002535static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002536read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2537 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002538{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002539 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002540 struct lys_node_case *cs;
2541 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002542 int c_ftrs = 0;
2543 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002544
Radek Krejci1d82ef62015-08-07 14:44:40 +02002545 cs = calloc(1, sizeof *cs);
2546 cs->nodetype = LYS_CASE;
2547 cs->prev = (struct lys_node *)cs;
2548 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002549
Radek Krejci6a113852015-07-03 16:04:20 +02002550 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002551 goto error;
2552 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002553
Radek Krejcia9544502015-08-14 08:24:29 +02002554 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2555
Michal Vasko3a0043f2015-08-12 12:11:30 +02002556 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002557 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002558 goto error;
2559 }
2560
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002561 /* process choice's specific children */
2562 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002563 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2564 /* garbage */
2565 lyxml_free_elem(module->ctx, sub);
2566 continue;
2567 }
2568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002569 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002570 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002571 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002572 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002573 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002574 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002575 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002576 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002577 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002578 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002579 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002580 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002581 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002582 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002583 } else if (!strcmp(sub->name, "if-feature")) {
2584 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002585 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2586 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002587 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002588 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002589 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002590 goto error;
2591 }
2592
Radek Krejci1d82ef62015-08-07 14:44:40 +02002593 cs->when = read_yin_when(module, sub);
2594 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002595 goto error;
2596 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002597 unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002599 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002601 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002602
Radek Krejci1d82ef62015-08-07 14:44:40 +02002603 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002605 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002606
Radek Krejci1d82ef62015-08-07 14:44:40 +02002607 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002608 lyxml_free_elem(module->ctx, sub);
2609 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002610
Radek Krejci3cf9e222015-06-18 11:37:50 +02002611 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002612 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002613 }
Radek Krejci73adb602015-07-02 18:07:40 +02002614 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002615 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002616 unres_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002617 }
Radek Krejcib388c152015-06-04 17:03:03 +02002618
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002619 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002620
2621error:
2622
Radek Krejci1d82ef62015-08-07 14:44:40 +02002623 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002624
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002626}
2627
Radek Krejci76512572015-08-04 09:47:08 +02002628static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002629read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002630{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 struct lyxml_elem *sub, *next;
2632 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002633 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002634 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002635 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002636 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002638 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002639 choice->nodetype = LYS_CHOICE;
2640 choice->prev = (struct lys_node *)choice;
2641 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002642
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002643 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2644 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002645 goto error;
2646 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002647
Radek Krejcia9544502015-08-14 08:24:29 +02002648 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2649
Michal Vasko3a0043f2015-08-12 12:11:30 +02002650 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002651 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002652 goto error;
2653 }
2654
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002655 /* process choice's specific children */
2656 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002657 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2658 /* garbage */
2659 lyxml_free_elem(module->ctx, sub);
2660 continue;
2661 }
2662
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002663 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002664 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002665 goto error;
2666 }
2667 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002668 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002669 goto error;
2670 }
2671 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002672 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002673 goto error;
2674 }
2675 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002676 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002677 goto error;
2678 }
2679 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002680 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002681 goto error;
2682 }
2683 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002684 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002685 goto error;
2686 }
2687 } else if (!strcmp(sub->name, "default")) {
2688 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002689 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002690 goto error;
2691 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002692 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002693 } else if (!strcmp(sub->name, "mandatory")) {
2694 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002695 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002696 goto error;
2697 }
2698 /* just checking the flags in leaf is not sufficient, we would allow
2699 * multiple mandatory statements with the "false" value
2700 */
2701 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002702
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002703 GETVAL(value, sub, "value");
2704 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002705 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002706 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002707 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002708 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002709 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 goto error;
2711 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002712 } else if (!strcmp(sub->name, "when")) {
2713 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002714 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002715 goto error;
2716 }
2717
2718 choice->when = read_yin_when(module, sub);
2719 if (!choice->when) {
2720 goto error;
2721 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002722 unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002723 } else if (!strcmp(sub->name, "if-feature")) {
2724 c_ftrs++;
2725
2726 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2727 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002728 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002729 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002730 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002731 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002732
Radek Krejci1d82ef62015-08-07 14:44:40 +02002733 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002734 lyxml_free_elem(ctx, sub);
2735 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002736
Radek Krejci3cf9e222015-06-18 11:37:50 +02002737 if (c_ftrs) {
2738 choice->features = calloc(c_ftrs, sizeof *choice->features);
2739 }
2740
Radek Krejci73adb602015-07-02 18:07:40 +02002741 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002742 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002743 unres_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02002744 }
2745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002746 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002747 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002748 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002749 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2750 goto error;
2751 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002752
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002753 /* link default with the case */
2754 if (dflt_str) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002755 unres_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002756 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002758 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002759
2760error:
2761
Radek Krejci1d82ef62015-08-07 14:44:40 +02002762 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002763
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002764 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002765}
2766
Radek Krejci76512572015-08-04 09:47:08 +02002767static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002768read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002769 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002770{
Radek Krejci76512572015-08-04 09:47:08 +02002771 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002772 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002773 struct lyxml_elem *sub, *next;
2774 const char *value;
2775 int r;
2776 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002777 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002780 anyxml->nodetype = LYS_ANYXML;
2781 anyxml->prev = (struct lys_node *)anyxml;
2782 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002783
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002784 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2785 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 goto error;
2787 }
Radek Krejci863c2852015-06-03 15:47:11 +02002788
Radek Krejcia9544502015-08-14 08:24:29 +02002789 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002790
2791 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002792 goto error;
2793 }
2794
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002795 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002796 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2797 /* garbage */
2798 lyxml_free_elem(module->ctx, sub);
2799 continue;
2800 }
2801
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002802 if (!strcmp(sub->name, "mandatory")) {
2803 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002804 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002805 goto error;
2806 }
2807 /* just checking the flags in leaf is not sufficient, we would allow
2808 * multiple mandatory statements with the "false" value
2809 */
2810 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002811
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002812 GETVAL(value, sub, "value");
2813 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002814 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002815 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002816 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002817 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002818 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002819 goto error;
2820 }
2821 /* else false is the default value, so we can ignore it */
2822 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002823 } else if (!strcmp(sub->name, "when")) {
2824 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002825 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002826 goto error;
2827 }
2828
2829 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002830 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002831 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002832 goto error;
2833 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002834 unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002835 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002836 } else if (!strcmp(sub->name, "must")) {
2837 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002838 } else if (!strcmp(sub->name, "if-feature")) {
2839 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002840
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002841 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002842 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002843 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002844 }
2845 }
Radek Krejci863c2852015-06-03 15:47:11 +02002846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 /* middle part - process nodes with cardinality of 0..n */
2848 if (c_must) {
2849 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2850 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002851 if (c_ftrs) {
2852 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2853 }
Radek Krejci863c2852015-06-03 15:47:11 +02002854
Radek Krejci73adb602015-07-02 18:07:40 +02002855 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002856 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002857 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002858 if (r) {
2859 goto error;
2860 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002861 unres_add_node(module, unres, &anyxml->must[anyxml->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci0b24d752015-07-02 15:02:27 +02002862 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002863 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02002864 unres_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002865 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002866 }
Radek Krejci863c2852015-06-03 15:47:11 +02002867
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002868 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002869
2870error:
2871
Radek Krejci1d82ef62015-08-07 14:44:40 +02002872 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002873
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002874 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002875}
2876
Radek Krejci76512572015-08-04 09:47:08 +02002877static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002878read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002879 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002880{
Radek Krejci76512572015-08-04 09:47:08 +02002881 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002882 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002883 struct lyxml_elem *sub, *next;
2884 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002885 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002886 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002887
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002888 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002889 leaf->nodetype = LYS_LEAF;
2890 leaf->prev = (struct lys_node *)leaf;
2891 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002892
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002893 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2894 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 goto error;
2896 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002897
Radek Krejcia9544502015-08-14 08:24:29 +02002898 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002899
2900 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002901 goto error;
2902 }
2903
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002904 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002905 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2906 /* garbage */
2907 lyxml_free_elem(module->ctx, sub);
2908 continue;
2909 }
2910
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002911 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002912 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002913 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002914 goto error;
2915 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002916 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002917 goto error;
2918 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002919 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002920 } else if (!strcmp(sub->name, "default")) {
2921 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002922 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002923 goto error;
2924 }
2925 GETVAL(value, sub, "value");
2926 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002927 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002928 } else if (!strcmp(sub->name, "units")) {
2929 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002930 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002931 goto error;
2932 }
2933 GETVAL(value, sub, "name");
2934 leaf->units = lydict_insert(module->ctx, value, strlen(value));
2935 } else if (!strcmp(sub->name, "mandatory")) {
2936 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002937 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002938 goto error;
2939 }
2940 /* just checking the flags in leaf is not sufficient, we would allow
2941 * multiple mandatory statements with the "false" value
2942 */
2943 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02002944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 GETVAL(value, sub, "value");
2946 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002947 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002948 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002949 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002950 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002951 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 goto error;
2953 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002954 } else if (!strcmp(sub->name, "when")) {
2955 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002956 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002957 goto error;
2958 }
2959
2960 leaf->when = read_yin_when(module, sub);
2961 if (!leaf->when) {
2962 goto error;
2963 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002964 unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002965
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002966 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02002967 c_must++;
2968 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002969 } else if (!strcmp(sub->name, "if-feature")) {
2970 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002971 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02002972
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002973 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002974 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002975 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002976 }
Radek Krejci4c31f122015-06-02 14:51:22 +02002977
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002978 lyxml_free_elem(module->ctx, sub);
2979 }
Radek Krejci4c31f122015-06-02 14:51:22 +02002980
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002981 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002982 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002983 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002984 goto error;
2985 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002986 if (leaf->dflt) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002987 unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002988 }
Radek Krejci4c31f122015-06-02 14:51:22 +02002989
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002990 /* middle part - process nodes with cardinality of 0..n */
2991 if (c_must) {
2992 leaf->must = calloc(c_must, sizeof *leaf->must);
2993 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002994 if (c_ftrs) {
2995 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
2996 }
Radek Krejci4c31f122015-06-02 14:51:22 +02002997
Radek Krejci73adb602015-07-02 18:07:40 +02002998 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002999 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003000 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003001 if (r) {
3002 goto error;
3003 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003004 unres_add_node(module, unres, &leaf->must[leaf->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003005 } else if (!strcmp(sub->name, "if-feature")) {
3006 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003007 unres_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003008 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003010
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003011 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003012
3013error:
3014
Radek Krejci1d82ef62015-08-07 14:44:40 +02003015 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003016
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003017 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003018}
3019
Radek Krejci76512572015-08-04 09:47:08 +02003020static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003021read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003022 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003023{
Radek Krejci76512572015-08-04 09:47:08 +02003024 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003025 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003026 struct lyxml_elem *sub, *next;
3027 const char *value;
3028 char *endptr;
3029 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003030 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003031 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003032 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003033
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003034 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003035 llist->nodetype = LYS_LEAFLIST;
3036 llist->prev = (struct lys_node *)llist;
3037 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003038
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003039 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3040 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003041 goto error;
3042 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003043
Radek Krejcia9544502015-08-14 08:24:29 +02003044 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003045
3046 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003047 goto error;
3048 }
3049
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003050 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003051 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3052 /* garbage */
3053 lyxml_free_elem(module->ctx, sub);
3054 continue;
3055 }
3056
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003058 if (llist->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003059 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 goto error;
3061 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003062 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003063 goto error;
3064 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003065 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 } else if (!strcmp(sub->name, "units")) {
3067 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003068 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003069 goto error;
3070 }
3071 GETVAL(value, sub, "name");
3072 llist->units = lydict_insert(module->ctx, value, strlen(value));
3073 } else if (!strcmp(sub->name, "ordered-by")) {
3074 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003075 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003076 goto error;
3077 }
3078 /* just checking the flags in llist is not sufficient, we would
3079 * allow multiple ordered-by statements with the "system" value
3080 */
3081 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003082
Radek Krejci1574a8d2015-08-03 14:16:52 +02003083 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003084 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3085 * state data
3086 */
3087 lyxml_free_elem(module->ctx, sub);
3088 continue;
3089 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003090
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003091 GETVAL(value, sub, "value");
3092 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003093 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003094 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003095 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003096 goto error;
Radek Krejci41882de2015-07-02 16:34:58 +02003097 } /* else system is the default value, so we can ignore it */
3098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 } else if (!strcmp(sub->name, "must")) {
3100 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003101 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003102 } else if (!strcmp(sub->name, "if-feature")) {
3103 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003104 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 } else if (!strcmp(sub->name, "min-elements")) {
3107 if (f_min) {
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 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003112
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003113 GETVAL(value, sub, "value");
3114 while (isspace(value[0])) {
3115 value++;
3116 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 /* convert it to uint32_t */
3119 errno = 0;
3120 endptr = NULL;
3121 val = strtoul(value, &endptr, 10);
3122 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003123 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003124 goto error;
3125 }
3126 llist->min = (uint32_t) val;
3127 } else if (!strcmp(sub->name, "max-elements")) {
3128 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003129 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003130 goto error;
3131 }
3132 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003133
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003134 GETVAL(value, sub, "value");
3135 while (isspace(value[0])) {
3136 value++;
3137 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003138
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003139 /* convert it to uint32_t */
3140 errno = 0;
3141 endptr = NULL;
3142 val = strtoul(value, &endptr, 10);
3143 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003144 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003145 goto error;
3146 }
3147 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003148 } else if (!strcmp(sub->name, "when")) {
3149 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003150 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003151 goto error;
3152 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003153
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003154 llist->when = read_yin_when(module, sub);
3155 if (!llist->when) {
3156 goto error;
3157 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003158 unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003159 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003160 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003161 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003164 lyxml_free_elem(module->ctx, sub);
3165 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003168 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003169 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003170 goto error;
3171 }
3172 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003173 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003174 goto error;
3175 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003177 /* middle part - process nodes with cardinality of 0..n */
3178 if (c_must) {
3179 llist->must = calloc(c_must, sizeof *llist->must);
3180 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003181 if (c_ftrs) {
3182 llist->features = calloc(c_ftrs, sizeof *llist->features);
3183 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003184
Radek Krejci73adb602015-07-02 18:07:40 +02003185 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003186 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003187 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 if (r) {
3189 goto error;
3190 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003191 unres_add_node(module, unres, &llist->must[llist->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003192 } else if (!strcmp(sub->name, "if-feature")) {
3193 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003194 unres_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003195 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003196 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003197
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003198 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003199
3200error:
3201
Radek Krejci1d82ef62015-08-07 14:44:40 +02003202 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003203
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003204 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003205}
3206
Radek Krejci76512572015-08-04 09:47:08 +02003207static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003208read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3209 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003210{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003211 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003212 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003214 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003215 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003216 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003217 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 char *auxs;
3219 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003220
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 /* init */
3222 memset(&root, 0, sizeof root);
3223 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003226 list->nodetype = LYS_LIST;
3227 list->prev = (struct lys_node *)list;
3228 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003229
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003230 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3231 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003232 goto error;
3233 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003234
Radek Krejcia9544502015-08-14 08:24:29 +02003235 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3236
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 /* process list's specific children */
3238 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003239 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3240 /* garbage */
3241 lyxml_free_elem(module->ctx, sub);
3242 continue;
3243 }
3244
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003245 /* data statements */
3246 if (!strcmp(sub->name, "container") ||
3247 !strcmp(sub->name, "leaf-list") ||
3248 !strcmp(sub->name, "leaf") ||
3249 !strcmp(sub->name, "list") ||
3250 !strcmp(sub->name, "choice") ||
3251 !strcmp(sub->name, "uses") ||
3252 !strcmp(sub->name, "grouping") ||
3253 !strcmp(sub->name, "anyxml")) {
3254 lyxml_unlink_elem(sub);
3255 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003257 /* array counters */
3258 } else if (!strcmp(sub->name, "key")) {
3259 /* check cardinality 0..1 */
3260 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003261 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003262 goto error;
3263 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003265 /* count the number of keys */
3266 GETVAL(value, sub, "value");
3267 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003268 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 while ((value = strpbrk(value, " \t\n"))) {
3270 list->keys_size++;
3271 while (isspace(*value)) {
3272 value++;
3273 }
3274 }
3275 list->keys_size++;
3276 list->keys = calloc(list->keys_size, sizeof *list->keys);
3277 } else if (!strcmp(sub->name, "unique")) {
3278 c_uniq++;
3279 lyxml_unlink_elem(sub);
3280 lyxml_add_child(&uniq, sub);
3281 } else if (!strcmp(sub->name, "typedef")) {
3282 c_tpdf++;
3283 } else if (!strcmp(sub->name, "must")) {
3284 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003285 } else if (!strcmp(sub->name, "if-feature")) {
3286 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003287
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 /* optional stetments */
3289 } else if (!strcmp(sub->name, "ordered-by")) {
3290 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003291 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003292 goto error;
3293 }
3294 /* just checking the flags in llist is not sufficient, we would
3295 * allow multiple ordered-by statements with the "system" value
3296 */
3297 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003298
Radek Krejci1574a8d2015-08-03 14:16:52 +02003299 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003300 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3301 * state data
3302 */
3303 lyxml_free_elem(module->ctx, sub);
3304 continue;
3305 }
Radek Krejci345ad742015-06-03 11:04:18 +02003306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003307 GETVAL(value, sub, "value");
3308 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003309 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003310 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003311 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003312 goto error;
3313 }
3314 /* else system is the default value, so we can ignore it */
3315 lyxml_free_elem(module->ctx, sub);
3316 } else if (!strcmp(sub->name, "min-elements")) {
3317 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003318 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003319 goto error;
3320 }
3321 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003322
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003323 GETVAL(value, sub, "value");
3324 while (isspace(value[0])) {
3325 value++;
3326 }
Radek Krejci345ad742015-06-03 11:04:18 +02003327
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003328 /* convert it to uint32_t */
3329 errno = 0;
3330 auxs = NULL;
3331 val = strtoul(value, &auxs, 10);
3332 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003333 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003334 goto error;
3335 }
3336 list->min = (uint32_t) val;
3337 lyxml_free_elem(module->ctx, sub);
3338 } else if (!strcmp(sub->name, "max-elements")) {
3339 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003340 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003341 goto error;
3342 }
3343 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003344
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003345 GETVAL(value, sub, "value");
3346 while (isspace(value[0])) {
3347 value++;
3348 }
Radek Krejci345ad742015-06-03 11:04:18 +02003349
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003350 /* convert it to uint32_t */
3351 errno = 0;
3352 auxs = NULL;
3353 val = strtoul(value, &auxs, 10);
3354 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003355 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 goto error;
3357 }
3358 list->max = (uint32_t) val;
3359 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003360 } else if (!strcmp(sub->name, "when")) {
3361 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003362 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003363 goto error;
3364 }
3365
3366 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003367 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003368 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003369 goto error;
3370 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003371 unres_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003372 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003373 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003374 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003375 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003376 }
3377 }
Radek Krejci345ad742015-06-03 11:04:18 +02003378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003380 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003381 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003382 goto error;
3383 }
3384 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003385 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003386 goto error;
3387 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003388
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003389 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3390 if (c_tpdf) {
3391 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3392 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003393 if (c_must) {
3394 list->must = calloc(c_must, sizeof *list->must);
3395 }
3396 if (c_ftrs) {
3397 list->features = calloc(c_ftrs, sizeof *list->features);
3398 }
Radek Krejci73adb602015-07-02 18:07:40 +02003399 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003400 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003401 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003403 if (r) {
3404 goto error;
3405 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003406 } else if (!strcmp(sub->name, "if-feature")) {
3407 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003408 unres_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003409 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003410 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003411 if (r) {
3412 goto error;
3413 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003414 unres_add_node(module, unres, &list->must[list->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003415 }
3416 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003417
Radek Krejci10c760e2015-08-14 14:45:43 +02003418 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003419 goto error;
3420 }
3421
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003422 /* last part - process data nodes */
3423 LY_TREE_FOR_SAFE(root.child, next, sub) {
3424 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003425 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003426 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003427 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003428 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003429 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003430 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003431 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003432 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003433 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003435 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003436 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003437 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003438 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003439 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003440 } else {
3441 LOGINT;
3442 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003443 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003444 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003445 goto error;
3446 }
Radek Krejci73adb602015-07-02 18:07:40 +02003447
3448 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003449 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003450
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003451 if (!key_str) {
3452 /* config false list without a key */
3453 return retval;
3454 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003455 unres_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line);
Radek Krejci812b10a2015-05-28 16:48:25 +02003456
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003457 /* process unique statements */
3458 if (c_uniq) {
3459 list->unique = calloc(c_uniq, sizeof *list->unique);
3460 }
3461 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003462 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003463 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003464 GETVAL(value, sub, "tag");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003465 unres_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value, LOGLINE(sub));
Radek Krejci1e9b9992015-06-04 17:57:04 +02003466
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003467 lyxml_free_elem(module->ctx, sub);
3468 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003469
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003470 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003471
3472error:
3473
Radek Krejci1d82ef62015-08-07 14:44:40 +02003474 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003475 while (root.child) {
3476 lyxml_free_elem(module->ctx, root.child);
3477 }
3478 while (uniq.child) {
3479 lyxml_free_elem(module->ctx, uniq.child);
3480 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003481
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003482 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003483}
3484
Radek Krejci76512572015-08-04 09:47:08 +02003485static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003486read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3487 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003488{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003489 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003490 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003491 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003492 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003493 const char *value;
3494 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003495 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003496
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003497 /* init */
3498 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003499
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003501 cont->nodetype = LYS_CONTAINER;
3502 cont->prev = (struct lys_node *)cont;
3503 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003504
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003505 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3506 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 goto error;
3508 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003509
Radek Krejcia9544502015-08-14 08:24:29 +02003510 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3511
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003512 /* process container's specific children */
3513 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003514 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003515 /* garbage */
3516 lyxml_free_elem(module->ctx, sub);
3517 continue;
3518 }
3519
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003520 if (!strcmp(sub->name, "presence")) {
3521 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003522 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003523 goto error;
3524 }
3525 GETVAL(value, sub, "value");
3526 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003528 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003529 } else if (!strcmp(sub->name, "when")) {
3530 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003531 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003532 goto error;
3533 }
3534
3535 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003536 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003537 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003538 goto error;
3539 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003540 unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003541 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003542
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003543 /* data statements */
3544 } else if (!strcmp(sub->name, "container") ||
3545 !strcmp(sub->name, "leaf-list") ||
3546 !strcmp(sub->name, "leaf") ||
3547 !strcmp(sub->name, "list") ||
3548 !strcmp(sub->name, "choice") ||
3549 !strcmp(sub->name, "uses") ||
3550 !strcmp(sub->name, "grouping") ||
3551 !strcmp(sub->name, "anyxml")) {
3552 lyxml_unlink_elem(sub);
3553 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003554
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003555 /* array counters */
3556 } else if (!strcmp(sub->name, "typedef")) {
3557 c_tpdf++;
3558 } else if (!strcmp(sub->name, "must")) {
3559 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003560 } else if (!strcmp(sub->name, "if-feature")) {
3561 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003562 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003563 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003565 }
3566 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003567
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003568 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3569 if (c_tpdf) {
3570 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3571 }
3572 if (c_must) {
3573 cont->must = calloc(c_must, sizeof *cont->must);
3574 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003575 if (c_ftrs) {
3576 cont->features = calloc(c_ftrs, sizeof *cont->features);
3577 }
Radek Krejci800af702015-06-02 13:46:01 +02003578
Radek Krejci73adb602015-07-02 18:07:40 +02003579 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003580 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003581 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003582 if (r) {
3583 goto error;
3584 }
3585 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003586 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 if (r) {
3588 goto error;
3589 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003590 unres_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval, LOGLINE(sub));
Radek Krejci3cf9e222015-06-18 11:37:50 +02003591 } else if (!strcmp(sub->name, "if-feature")) {
3592 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003593 unres_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003594 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003596
Radek Krejci10c760e2015-08-14 14:45:43 +02003597 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003598 goto error;
3599 }
3600
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003601 /* last part - process data nodes */
3602 LY_TREE_FOR_SAFE(root.child, next, sub) {
3603 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003604 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003605 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003606 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003607 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003608 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003609 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003610 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003611 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003612 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003613 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003614 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003615 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003616 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003617 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003618 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003619 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003620 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003621 goto error;
3622 }
Radek Krejci73adb602015-07-02 18:07:40 +02003623
3624 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003625 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003626
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003627 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003628
3629error:
3630
Radek Krejci1d82ef62015-08-07 14:44:40 +02003631 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003632 while (root.child) {
3633 lyxml_free_elem(module->ctx, root.child);
3634 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003635
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003636 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003637}
3638
Radek Krejci76512572015-08-04 09:47:08 +02003639static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003640read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003641 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003642{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003643 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003644 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003645 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003646 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003647 int r;
3648 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003650 /* init */
3651 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003652
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003653 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003654 grp->nodetype = LYS_GROUPING;
3655 grp->prev = (struct lys_node *)grp;
3656 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003657
Michal Vasko71e1aa82015-08-12 12:17:51 +02003658 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003659 goto error;
3660 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003661
Radek Krejcia9544502015-08-14 08:24:29 +02003662 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3663
Radek Krejci1d82ef62015-08-07 14:44:40 +02003664 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003665 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3666 /* garbage */
3667 lyxml_free_elem(module->ctx, sub);
3668 continue;
3669 }
3670
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003671 /* data statements */
3672 if (!strcmp(sub->name, "container") ||
3673 !strcmp(sub->name, "leaf-list") ||
3674 !strcmp(sub->name, "leaf") ||
3675 !strcmp(sub->name, "list") ||
3676 !strcmp(sub->name, "choice") ||
3677 !strcmp(sub->name, "uses") ||
3678 !strcmp(sub->name, "grouping") ||
3679 !strcmp(sub->name, "anyxml")) {
3680 lyxml_unlink_elem(sub);
3681 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003682
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003683 /* array counters */
3684 } else if (!strcmp(sub->name, "typedef")) {
3685 c_tpdf++;
3686 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003687 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 goto error;
3689 }
3690 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003692 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3693 if (c_tpdf) {
3694 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3695 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003696 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003697 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003698
Radek Krejci73adb602015-07-02 18:07:40 +02003699 if (r) {
3700 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003701 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003703
Radek Krejci10c760e2015-08-14 14:45:43 +02003704 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003705 goto error;
3706 }
3707
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003708 /* last part - process data nodes */
3709 LY_TREE_FOR_SAFE(root.child, next, sub) {
3710 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003711 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003712 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003713 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003714 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003715 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003716 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003717 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003720 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003721 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003723 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003724 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003725 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003726 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003727 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 goto error;
3729 }
Radek Krejci73adb602015-07-02 18:07:40 +02003730
3731 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003732 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003733
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003735
3736error:
3737
Radek Krejci1d82ef62015-08-07 14:44:40 +02003738 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003739 while (root.child) {
3740 lyxml_free_elem(module->ctx, root.child);
3741 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003742
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003743 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003744}
3745
Radek Krejci76512572015-08-04 09:47:08 +02003746static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003747read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3748 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003749{
Radek Krejcie0674f82015-06-15 13:58:51 +02003750 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003751 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003752 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003753 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003754 int r;
3755 int c_tpdf = 0;
3756
Radek Krejcie0674f82015-06-15 13:58:51 +02003757 /* init */
3758 memset(&root, 0, sizeof root);
3759
Michal Vasko38d01f72015-06-15 09:41:06 +02003760 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003761 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003762
3763 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003764 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003765 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003766 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003767 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003768 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003769 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003770 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003771 }
3772
Radek Krejci76512572015-08-04 09:47:08 +02003773 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003774
Radek Krejci6a113852015-07-03 16:04:20 +02003775 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003776 goto error;
3777 }
3778
Radek Krejcia9544502015-08-14 08:24:29 +02003779 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3780
Michal Vasko38d01f72015-06-15 09:41:06 +02003781 /* data statements */
3782 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003783 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3784 /* garbage */
3785 lyxml_free_elem(module->ctx, sub);
3786 continue;
3787 }
3788
Michal Vasko38d01f72015-06-15 09:41:06 +02003789 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003790 !strcmp(sub->name, "leaf-list") ||
3791 !strcmp(sub->name, "leaf") ||
3792 !strcmp(sub->name, "list") ||
3793 !strcmp(sub->name, "choice") ||
3794 !strcmp(sub->name, "uses") ||
3795 !strcmp(sub->name, "grouping") ||
3796 !strcmp(sub->name, "anyxml")) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003797 lyxml_unlink_elem(sub);
3798 lyxml_add_child(&root, sub);
3799
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003800 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003801 } else if (!strcmp(sub->name, "typedef")) {
3802 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003803
Michal Vasko38d01f72015-06-15 09:41:06 +02003804 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003805 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003806 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003807 }
3808 }
3809
3810 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3811 if (c_tpdf) {
3812 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3813 }
3814
Radek Krejci73adb602015-07-02 18:07:40 +02003815 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003816 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003817
Radek Krejci73adb602015-07-02 18:07:40 +02003818 if (r) {
3819 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003820 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003821 }
3822
Radek Krejci10c760e2015-08-14 14:45:43 +02003823 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003824 goto error;
3825 }
3826
Michal Vasko38d01f72015-06-15 09:41:06 +02003827 /* last part - process data nodes */
3828 LY_TREE_FOR_SAFE(root.child, next, sub) {
3829 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003830 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003831 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003832 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003833 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003834 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003835 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003836 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003837 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003838 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003839 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003840 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003841 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003842 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003843 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003844 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003845 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003846 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003847 goto error;
3848 }
Radek Krejci73adb602015-07-02 18:07:40 +02003849
3850 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003851 }
3852
Michal Vasko38d01f72015-06-15 09:41:06 +02003853 return retval;
3854
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003855error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003856
Radek Krejci1d82ef62015-08-07 14:44:40 +02003857 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003858 while (root.child) {
3859 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003860 }
3861
3862 return NULL;
3863}
3864
Radek Krejci76512572015-08-04 09:47:08 +02003865static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003866read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3867 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003868{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003869 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003870 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003871 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003872 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003873 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003874 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003875 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003876
Michal Vaskoc6551b32015-06-16 10:51:43 +02003877 memset(&root, 0, sizeof root);
3878
Michal Vasko0ea41032015-06-16 08:53:55 +02003879 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02003880 notif->nodetype = LYS_NOTIF;
3881 notif->prev = (struct lys_node *)notif;
3882 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02003883
Radek Krejci6a113852015-07-03 16:04:20 +02003884 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003885 goto error;
3886 }
3887
Radek Krejcia9544502015-08-14 08:24:29 +02003888 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3889
Michal Vasko0ea41032015-06-16 08:53:55 +02003890 /* process rpc's specific children */
3891 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003892 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3893 /* garbage */
3894 lyxml_free_elem(module->ctx, sub);
3895 continue;
3896 }
3897
Michal Vasko0ea41032015-06-16 08:53:55 +02003898 /* data statements */
3899 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003900 !strcmp(sub->name, "leaf-list") ||
3901 !strcmp(sub->name, "leaf") ||
3902 !strcmp(sub->name, "list") ||
3903 !strcmp(sub->name, "choice") ||
3904 !strcmp(sub->name, "uses") ||
3905 !strcmp(sub->name, "grouping") ||
3906 !strcmp(sub->name, "anyxml")) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003907 lyxml_unlink_elem(sub);
3908 lyxml_add_child(&root, sub);
3909
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003910 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02003911 } else if (!strcmp(sub->name, "typedef")) {
3912 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003913 } else if (!strcmp(sub->name, "if-feature")) {
3914 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02003915 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003916 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02003917 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02003918 }
3919 }
3920
3921 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3922 if (c_tpdf) {
3923 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
3924 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003925 if (c_ftrs) {
3926 notif->features = calloc(c_ftrs, sizeof *notif->features);
3927 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003928
Radek Krejci73adb602015-07-02 18:07:40 +02003929 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003930 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003931 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003932
3933 if (r) {
3934 goto error;
3935 }
Radek Krejci0b24d752015-07-02 15:02:27 +02003936 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02003937 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02003938 unres_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko0ea41032015-06-16 08:53:55 +02003939 }
Michal Vasko0ea41032015-06-16 08:53:55 +02003940 }
3941
Radek Krejci10c760e2015-08-14 14:45:43 +02003942 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003943 goto error;
3944 }
3945
Michal Vasko0ea41032015-06-16 08:53:55 +02003946 /* last part - process data nodes */
3947 LY_TREE_FOR_SAFE(root.child, next, sub) {
3948 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003949 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003950 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003951 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003952 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003953 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003954 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003955 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003956 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003957 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003958 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003959 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003960 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003961 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003962 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003963 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02003964 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003965 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003966 goto error;
3967 }
Radek Krejci73adb602015-07-02 18:07:40 +02003968
3969 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02003970 }
3971
Michal Vasko0ea41032015-06-16 08:53:55 +02003972 return retval;
3973
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003974error:
Michal Vasko0ea41032015-06-16 08:53:55 +02003975
Radek Krejci1d82ef62015-08-07 14:44:40 +02003976 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02003977 while (root.child) {
3978 lyxml_free_elem(module->ctx, root.child);
3979 }
3980
3981 return NULL;
3982}
3983
Radek Krejci76512572015-08-04 09:47:08 +02003984static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003985read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3986 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003987{
Radek Krejcie0674f82015-06-15 13:58:51 +02003988 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003989 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003990 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003991 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003992 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02003993 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003994 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02003995
Radek Krejcie0674f82015-06-15 13:58:51 +02003996 /* init */
3997 memset(&root, 0, sizeof root);
3998
Michal Vasko38d01f72015-06-15 09:41:06 +02003999 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004000 rpc->nodetype = LYS_RPC;
4001 rpc->prev = (struct lys_node *)rpc;
4002 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004003
Radek Krejci6a113852015-07-03 16:04:20 +02004004 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004005 goto error;
4006 }
4007
Radek Krejcia9544502015-08-14 08:24:29 +02004008 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4009
Michal Vasko38d01f72015-06-15 09:41:06 +02004010 /* process rpc's specific children */
4011 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004012 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4013 /* garbage */
4014 lyxml_free_elem(module->ctx, sub);
4015 continue;
4016 }
4017
Michal Vasko38d01f72015-06-15 09:41:06 +02004018 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004019 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004020 && (rpc->child->nodetype == LYS_INPUT
4021 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004022 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004023 goto error;
4024 }
4025 lyxml_unlink_elem(sub);
4026 lyxml_add_child(&root, sub);
4027 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004028 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004029 && (rpc->child->nodetype == LYS_INPUT
4030 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004031 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004032 goto error;
4033 }
4034 lyxml_unlink_elem(sub);
4035 lyxml_add_child(&root, sub);
4036
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004037 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004038 } else if (!strcmp(sub->name, "grouping")) {
4039 lyxml_unlink_elem(sub);
4040 lyxml_add_child(&root, sub);
4041
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004042 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004043 } else if (!strcmp(sub->name, "typedef")) {
4044 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004045 } else if (!strcmp(sub->name, "if-feature")) {
4046 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004047 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004048 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004049 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004050 }
4051 }
4052
4053 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4054 if (c_tpdf) {
4055 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4056 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004057 if (c_ftrs) {
4058 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4059 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004060
Radek Krejci73adb602015-07-02 18:07:40 +02004061 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004062 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004063 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004064
4065 if (r) {
4066 goto error;
4067 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004068 } else if (!strcmp(sub->name, "if-feature")) {
4069 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02004070 unres_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Michal Vasko38d01f72015-06-15 09:41:06 +02004071 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004072 }
4073
Radek Krejci10c760e2015-08-14 14:45:43 +02004074 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004075 goto error;
4076 }
4077
Michal Vasko38d01f72015-06-15 09:41:06 +02004078 /* last part - process data nodes */
4079 LY_TREE_FOR_SAFE(root.child, next, sub) {
4080 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004081 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004082 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004083 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004084 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004085 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004086 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004087 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 goto error;
4089 }
Radek Krejci73adb602015-07-02 18:07:40 +02004090
4091 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004092 }
4093
Michal Vasko38d01f72015-06-15 09:41:06 +02004094 return retval;
4095
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004096error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004097
Radek Krejci1d82ef62015-08-07 14:44:40 +02004098 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004099 while (root.child) {
4100 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 }
4102
4103 return NULL;
4104}
4105
Radek Krejci74705112015-06-05 10:25:44 +02004106/*
4107 * resolve - referenced grouping should be bounded to the namespace (resolved)
4108 * only when uses does not appear in grouping. In a case of grouping's uses,
4109 * we just get information but we do not apply augment or refine to it.
4110 */
Radek Krejci76512572015-08-04 09:47:08 +02004111static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004112read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004113 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004114{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004115 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004116 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004117 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004118 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004119 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004121
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004122 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004123 uses->nodetype = LYS_USES;
4124 uses->prev = (struct lys_node *)uses;
4125 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004126
Radek Krejcia9544502015-08-14 08:24:29 +02004127 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004128 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004129
Radek Krejcia9544502015-08-14 08:24:29 +02004130 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004131 goto error;
4132 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004133
Radek Krejcia9544502015-08-14 08:24:29 +02004134 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4135
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004136 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004137 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004138 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4139 /* garbage */
4140 lyxml_free_elem(module->ctx, sub);
4141 continue;
4142 }
4143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004144 if (!strcmp(sub->name, "refine")) {
4145 c_ref++;
4146 } else if (!strcmp(sub->name, "augment")) {
4147 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004148 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004149 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004150 } else if (!strcmp(sub->name, "when")) {
4151 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004152 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004153 goto error;
4154 }
4155
4156 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004157 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004158 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004159 goto error;
4160 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004161 unres_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004162 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004163 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004164 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004165 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004166 }
4167 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004168
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004169 /* process properties with cardinality 0..n */
4170 if (c_ref) {
4171 uses->refine = calloc(c_ref, sizeof *uses->refine);
4172 }
4173 if (c_aug) {
4174 uses->augment = calloc(c_aug, sizeof *uses->augment);
4175 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004176 if (c_ftrs) {
4177 uses->features = calloc(c_ftrs, sizeof *uses->features);
4178 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004179
Radek Krejci10c760e2015-08-14 14:45:43 +02004180 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004181 goto error;
4182 }
4183
Radek Krejcia9544502015-08-14 08:24:29 +02004184 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004185 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004186 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4187 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004188 goto error;
4189 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004190 } else if (!strcmp(sub->name, "augment")) {
4191 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4192 if (r) {
4193 goto error;
4194 }
4195 } else if (!strcmp(sub->name, "if-feature")) {
4196 GETVAL(value, sub, "name");
Radek Krejci1d82ef62015-08-07 14:44:40 +02004197 unres_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value, LOGLINE(sub));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004198 }
4199 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004200
Radek Krejcia9544502015-08-14 08:24:29 +02004201 unres_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin));
Radek Krejci74705112015-06-05 10:25:44 +02004202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004203 if (resolve) {
4204 /* inherit config flag */
4205 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004206 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004207 } else {
4208 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004209 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004210 }
4211 }
Radek Krejcib388c152015-06-04 17:03:03 +02004212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004213 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004214
4215error:
4216
Radek Krejci1d82ef62015-08-07 14:44:40 +02004217 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004219 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004220}
4221
Radek Krejciefaeba32015-05-27 14:30:57 +02004222/* common code for yin_read_module() and yin_read_submodule() */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004223static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004224read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004225{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004226 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004227 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004228 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4229 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004230 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004231 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004232 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004233 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004234 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 +02004235
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004236 /* init */
4237 memset(&root, 0, sizeof root);
4238 memset(&grps, 0, sizeof grps);
4239 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004240 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004242 /*
4243 * in the first run, we process elements with cardinality of 1 or 0..1 and
4244 * count elements with cardinality 0..n. Data elements (choices, containers,
4245 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4246 * need have all top-level and groupings already prepared at that time. In
4247 * the middle loop, we process other elements with carinality of 0..n since
4248 * we need to allocate arrays to store them.
4249 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004250 LY_TREE_FOR_SAFE(yin->child, next, child) {
4251 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004252 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004253 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004254 continue;
4255 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004256
Radek Krejci1d82ef62015-08-07 14:44:40 +02004257 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004258 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004259 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004260 goto error;
4261 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004262 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004263 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004264 lyxml_free_elem(ctx, child);
4265 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004266 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004267 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004268 goto error;
4269 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004270 GETVAL(value, child, "value");
4271 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004272 goto error;
4273 }
4274 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004275 lyxml_free_elem(ctx, child);
4276 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004277 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004278 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004279 goto error;
4280 }
4281 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004282 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004283 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004284 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004285 }
4286 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004287 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004288 goto error;
4289 }
Radek Krejcif3886932015-06-04 17:36:06 +02004290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004291 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004292 if (!child->child) {
4293 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004294 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004295 } else if (strcmp(child->child->name, "prefix")) {
4296 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004297 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004298 } else if (child->child->next) {
4299 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004300 goto error;
4301 }
4302 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004303 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004304 /* check here differs from a generic prefix check, since this prefix
4305 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004306 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004307 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004308 goto error;
4309 }
4310 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004311
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004312 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004313 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004314
4315 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004316 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004317 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004318 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004319 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004320 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004321 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004322 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004323 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004324 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004325 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004326 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004327 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004328 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004329 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004330 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004331 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004333 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004334 } else if (!strcmp(child->name, "container") ||
4335 !strcmp(child->name, "leaf-list") ||
4336 !strcmp(child->name, "leaf") ||
4337 !strcmp(child->name, "list") ||
4338 !strcmp(child->name, "choice") ||
4339 !strcmp(child->name, "uses") ||
4340 !strcmp(child->name, "anyxml")) {
4341 lyxml_unlink_elem(child);
4342 lyxml_add_child(&root, child);
4343 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004344 /* keep groupings separated and process them before other data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 lyxml_unlink_elem(child);
4346 lyxml_add_child(&grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004349 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004350 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004351 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004352 goto error;
4353 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004354 module->dsc = read_yin_subnode(ctx, child, "text");
4355 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356 if (!module->dsc) {
4357 goto error;
4358 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004359 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004361 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004362 goto error;
4363 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004364 module->ref = read_yin_subnode(ctx, child, "text");
4365 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004366 if (!module->ref) {
4367 goto error;
4368 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004369 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004370 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004371 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004372 goto error;
4373 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004374 module->org = read_yin_subnode(ctx, child, "text");
4375 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 if (!module->org) {
4377 goto error;
4378 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004379 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004380 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004381 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 goto error;
4383 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004384 module->contact = read_yin_subnode(ctx, child, "text");
4385 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004386 if (!module->contact) {
4387 goto error;
4388 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004389 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004390 /* TODO: support YANG 1.1 ? */
4391 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004392 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004393 goto error;
4394 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004395 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004397 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004398 goto error;
4399 }
4400 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004401 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004402
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004403 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004404 } else if (!strcmp(child->name, "rpc")) {
4405 lyxml_unlink_elem(child);
4406 lyxml_add_child(&rpcs, child);
4407 } else if (!strcmp(child->name, "notification")) {
4408 lyxml_unlink_elem(child);
4409 lyxml_add_child(&notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004410
Radek Krejci1d82ef62015-08-07 14:44:40 +02004411 } else if (!strcmp(child->name, "extension")) {
4412 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004413
Radek Krejci6764bb32015-07-03 15:16:04 +02004414 /* we have 2 supported (hardcoded) extensions:
4415 * NACM's default-deny-write and default-deny-all
4416 */
4417 if (strcmp(module->ns, LY_NSNACM) ||
4418 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4419 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004420 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004421 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004422 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004423 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004424 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004425 }
4426 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004427
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004428 if (!submodule) {
4429 /* check for mandatory statements */
4430 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004431 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 goto error;
4433 }
4434 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004435 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 goto error;
4437 }
4438 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004439
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 /* allocate arrays for elements with cardinality of 0..n */
4441 if (c_imp) {
4442 module->imp = calloc(c_imp, sizeof *module->imp);
4443 }
4444 if (c_rev) {
4445 module->rev = calloc(c_rev, sizeof *module->rev);
4446 }
4447 if (c_tpdf) {
4448 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4449 }
4450 if (c_ident) {
4451 module->ident = calloc(c_ident, sizeof *module->ident);
4452 }
4453 if (c_inc) {
4454 module->inc = calloc(c_inc, sizeof *module->inc);
4455 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004456 if (c_aug) {
4457 module->augment = calloc(c_aug, sizeof *module->augment);
4458 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004459 if (c_ftrs) {
4460 module->features = calloc(c_ftrs, sizeof *module->features);
4461 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004462 if (c_dev) {
4463 module->deviation = calloc(c_dev, sizeof *module->deviation);
4464 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004465
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004466 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004467 LY_TREE_FOR(yin->child, child) {
4468 if (!strcmp(child->name, "import")) {
4469 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 module->imp_size++;
4471 if (r) {
4472 goto error;
4473 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004474
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004475 /* check duplicities in imported modules */
4476 for (i = 0; i < module->imp_size - 1; i++) {
4477 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004478 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004479 goto error;
4480 }
4481 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004482 } else if (!strcmp(child->name, "include")) {
4483 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 module->inc_size++;
4485 if (r) {
4486 goto error;
4487 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004488
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004489 /* check duplications in include submodules */
4490 for (i = 0; i < module->inc_size - 1; i++) {
4491 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004492 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004493 module->inc[i].submodule->name);
4494 goto error;
4495 }
4496 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004497 } else if (!strcmp(child->name, "revision")) {
4498 GETVAL(value, child, "date");
4499 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004500 goto error;
4501 }
4502 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4503 /* check uniqueness of the revision date - not required by RFC */
4504 for (i = 0; i < module->rev_size; i++) {
4505 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004506 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004507 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004508 }
4509 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004510
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 LY_TREE_FOR(child->child, child2) {
4512 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004514 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004515 goto error;
4516 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004517 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004518 if (!module->rev[module->rev_size].dsc) {
4519 goto error;
4520 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004521 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004522 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004523 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 goto error;
4525 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004526 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004527 if (!module->rev[module->rev_size].ref) {
4528 goto error;
4529 }
4530 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004531 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004532 goto error;
4533 }
4534 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004535
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004536 /* keep the latest revision at position 0 */
4537 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4538 /* switch their position */
4539 value = strdup(module->rev[0].date);
4540 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4541 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4542 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004543
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004544 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4545 value = module->rev[0].dsc;
4546 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4547 module->rev[module->rev_size].dsc = value;
4548 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004549
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004550 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4551 value = module->rev[0].ref;
4552 module->rev[0].ref = module->rev[module->rev_size].ref;
4553 module->rev[module->rev_size].ref = value;
4554 }
4555 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004556
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004557 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004558 } else if (!strcmp(child->name, "typedef")) {
4559 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004560 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004561
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004562 if (r) {
4563 goto error;
4564 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004565 } else if (!strcmp(child->name, "identity")) {
4566 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004568
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004569 if (r) {
4570 goto error;
4571 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004572 } else if (!strcmp(child->name, "feature")) {
4573 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004574 module->features_size++;
4575
4576 if (r) {
4577 goto error;
4578 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004579 } else if (!strcmp(child->name, "augment")) {
4580 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004581 module->augment_size++;
4582
4583 if (r) {
4584 goto error;
4585 }
4586
4587 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4588 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004589 } else if (!strcmp(child->name, "deviation")) {
4590 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004591 module->deviation_size++;
4592
4593 if (r) {
4594 goto error;
4595 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004597 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004598
Radek Krejcif5be10f2015-06-16 13:29:36 +02004599 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004600 * refer to them
4601 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004602 LY_TREE_FOR_SAFE(grps.child, next, child) {
4603 node = read_yin_grouping(module, NULL, child, 0, unres);
4604 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004605 goto error;
4606 }
Radek Krejci74705112015-06-05 10:25:44 +02004607
Radek Krejci1d82ef62015-08-07 14:44:40 +02004608 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004609 }
Radek Krejci74705112015-06-05 10:25:44 +02004610
Radek Krejcif5be10f2015-06-16 13:29:36 +02004611 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004612 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004613
Radek Krejci1d82ef62015-08-07 14:44:40 +02004614 if (!strcmp(child->name, "container")) {
4615 node = read_yin_container(module, NULL, child, 1, unres);
4616 } else if (!strcmp(child->name, "leaf-list")) {
4617 node = read_yin_leaflist(module, NULL, child, 1, unres);
4618 } else if (!strcmp(child->name, "leaf")) {
4619 node = read_yin_leaf(module, NULL, child, 1, unres);
4620 } else if (!strcmp(child->name, "list")) {
4621 node = read_yin_list(module, NULL, child, 1, unres);
4622 } else if (!strcmp(child->name, "choice")) {
4623 node = read_yin_choice(module, NULL, child, 1, unres);
4624 } else if (!strcmp(child->name, "uses")) {
4625 node = read_yin_uses(module, NULL, child, 1, unres);
4626 } else if (!strcmp(child->name, "anyxml")) {
4627 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004628 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004629 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004630 goto error;
4631 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004632
Radek Krejci1d82ef62015-08-07 14:44:40 +02004633 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004634 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004635
4636 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004637 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4638 node = read_yin_rpc(module, NULL, child, 0, unres);
4639 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004640 goto error;
4641 }
4642
Radek Krejci1d82ef62015-08-07 14:44:40 +02004643 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004644 }
4645
4646 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004647 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4648 node = read_yin_notif(module, NULL, child, 0, unres);
4649 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004650 goto error;
4651 }
4652
Radek Krejci1d82ef62015-08-07 14:44:40 +02004653 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004654 }
4655
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004656 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004657
4658error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004659 /* cleanup */
4660 while (root.child) {
4661 lyxml_free_elem(module->ctx, root.child);
4662 }
4663 while (grps.child) {
4664 lyxml_free_elem(module->ctx, grps.child);
4665 }
4666 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004667 lyxml_free_elem(module->ctx, rpcs.child);
4668 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004669
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004670 free(unres->item);
4671 unres->item = NULL;
4672 free(unres->type);
4673 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004674 free(unres->str_snode);
4675 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004676#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004677 free(unres->line);
4678 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004679#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004680 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004681
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004682 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004683}
4684
Radek Krejcib8048692015-08-05 13:36:34 +02004685struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004686yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004687{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004689 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004690 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004692 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004693
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004694 yin = lyxml_read(module->ctx, data, 0);
4695 if (!yin) {
4696 return NULL;
4697 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004698
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004699 /* check root element */
4700 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004701 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004702 goto error;
4703 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004704
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004705 GETVAL(value, yin, "name");
4706 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4707 goto error;
4708 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004709
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004710 submodule = calloc(1, sizeof *submodule);
4711 if (!submodule) {
4712 LOGMEM;
4713 goto error;
4714 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004715
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 submodule->ctx = module->ctx;
4717 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4718 submodule->type = 1;
4719 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004720 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004721
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004723 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004724 goto error;
4725 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004726
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004727 /* cleanup */
4728 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004729
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004730 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004732 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004733
4734error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004735 /* cleanup */
4736 lyxml_free_elem(module->ctx, yin);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004737 lys_submodule_free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02004738
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004739 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004740}
4741
Radek Krejcib8048692015-08-05 13:36:34 +02004742struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004743yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004744{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004745 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004746 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 const char *value;
4748 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004749
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004750 yin = lyxml_read(ctx, data, 0);
4751 if (!yin) {
4752 return NULL;
4753 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004754
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004755 /* check root element */
4756 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004757 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004758 goto error;
4759 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004760
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004761 GETVAL(value, yin, "name");
4762 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4763 goto error;
4764 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004765
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004766 module = calloc(1, sizeof *module);
4767 if (!module) {
4768 LOGMEM;
4769 goto error;
4770 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004771
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004772 module->ctx = ctx;
4773 module->name = lydict_insert(ctx, value, strlen(value));
4774 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004775 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004776
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004777 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004778 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004779 goto error;
4780 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 /* add to the context's list of modules */
4783 if (ctx->models.used == ctx->models.size) {
4784 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4785 if (!newlist) {
4786 LOGMEM;
4787 goto error;
4788 }
4789 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4790 newlist[i] = NULL;
4791 }
4792 ctx->models.size *= 2;
4793 ctx->models.list = newlist;
4794 }
4795 for (i = 0; ctx->models.list[i]; i++) {
4796 /* check name (name/revision) and namespace uniqueness */
4797 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004798 if (ctx->models.list[i]->rev_size == module->rev_size) {
4799 /* both have the same number of revisions */
4800 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4801 /* both have the same revision -> we already have the same module */
4802 /* so free the new one and update the old one's implement flag if needed */
4803 lyxml_free_elem(ctx, yin);
4804 lys_free(module);
Michal Vaskoaa211572015-08-13 13:55:39 +02004805 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004806
4807 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4808
4809 if (implement && !ctx->models.list[i]->implemented) {
4810 lyp_set_implemented(ctx->models.list[i]);
4811 }
4812 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004813 }
4814 }
Radek Krejcif647e612015-07-30 11:36:07 +02004815 /* else (both elses) keep searching, for now the caller is just adding
4816 * another revision of an already present schema
4817 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4819 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4820 ctx->models.list[i]->name, module->name, module->ns);
4821 goto error;
4822 }
4823 }
4824 ctx->models.list[i] = module;
4825 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004826 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004827
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004828 /* cleanup */
4829 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004830
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004831 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004832
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004834
4835error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004836 /* cleanup */
4837 lyxml_free_elem(ctx, yin);
Radek Krejci912da452015-07-29 14:10:06 +02004838 lys_free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004839
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004840 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004841}