blob: 83400ba508b8809e0932a4f7c2a2e952835fbe14 [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"
Radek Krejci998a0b82015-08-17 13:14:36 +020038#include "resolve.h"
39#include "tree_internal.h"
40#include "xml.h"
Radek Krejciefdd0ce2015-05-26 16:48:29 +020041
Radek Krejcice7fb782015-05-29 16:52:34 +020042enum LY_IDENT {
Radek Krejci994b6f62015-06-18 16:47:27 +020043 LY_IDENT_SIMPLE, /* only syntax rules */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020044 LY_IDENT_FEATURE,
45 LY_IDENT_IDENTITY,
46 LY_IDENT_TYPE,
47 LY_IDENT_NODE,
Radek Krejci994b6f62015-06-18 16:47:27 +020048 LY_IDENT_NAME, /* uniqueness across the siblings */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020049 LY_IDENT_PREFIX
Radek Krejcice7fb782015-05-29 16:52:34 +020050};
51
Radek Krejciefdd0ce2015-05-26 16:48:29 +020052#define LY_NSYIN "urn:ietf:params:xml:ns:yang:yin:1"
Radek Krejci6764bb32015-07-03 15:16:04 +020053#define LY_NSNACM "urn:ietf:params:xml:ns:yang:ietf-netconf-acm"
Radek Krejcida04f4a2015-05-21 12:54:09 +020054
Radek Krejcice7fb782015-05-29 16:52:34 +020055#define GETVAL(value, node, arg) \
56 value = lyxml_get_attr(node, arg, NULL); \
57 if (!value) { \
Michal Vaskoe7fc19c2015-08-05 16:24:39 +020058 LOGVAL(LYE_MISSARG, LOGLINE(node), arg, node->name); \
Radek Krejcice7fb782015-05-29 16:52:34 +020059 goto error; \
60 }
61
Radek Krejcib388c152015-06-04 17:03:03 +020062#define OPT_IDENT 0x01
63#define OPT_CONFIG 0x02
64#define OPT_MODULE 0x04
65#define OPT_INHERIT 0x08
Radek Krejci6764bb32015-07-03 15:16:04 +020066#define OPT_NACMEXT 0x10
Radek Krejcib8048692015-08-05 13:36:34 +020067static int read_yin_common(struct lys_module *, struct lys_node *, struct lys_node *, struct lyxml_elem *, int);
Radek Krejcib388c152015-06-04 17:03:03 +020068
Radek Krejcib8048692015-08-05 13:36:34 +020069static struct lys_node *read_yin_choice(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020070 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020071static struct lys_node *read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020072 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020073static struct lys_node *read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020074 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020075static struct lys_node *read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020076 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020077static struct lys_node *read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020078 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020079static struct lys_node *read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020080 int resolve, struct unres_schema *unres);
Radek Krejcib8048692015-08-05 13:36:34 +020081static struct lys_node *read_yin_list(struct lys_module *module,struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020082 int resolve, struct unres_schema *unres);
Radek Krejcia9544502015-08-14 08:24:29 +020083static struct lys_node *read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020084 int resolve, struct unres_schema *unres);
Radek Krejci1d82ef62015-08-07 14:44:40 +020085static struct lys_node *read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin,
Michal Vaskof02e3742015-08-05 16:27:02 +020086 int resolve, struct unres_schema *unres);
87static struct lys_when *read_yin_when(struct lys_module *module, struct lyxml_elem *yin);
Radek Krejci74705112015-06-05 10:25:44 +020088
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020089static int
Radek Krejci1574a8d2015-08-03 14:16:52 +020090dup_typedef_check(const char *type, struct lys_tpdf *tpdf, int size)
Radek Krejcieac35532015-05-31 19:09:15 +020091{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020092 int i;
Radek Krejcieac35532015-05-31 19:09:15 +020093
Radek Krejci6e4ffbb2015-06-16 10:34:41 +020094 for (i = 0; i < size; i++) {
95 if (!strcmp(type, tpdf[i].name)) {
96 /* name collision */
97 return EXIT_FAILURE;
98 }
99 }
Radek Krejcieac35532015-05-31 19:09:15 +0200100
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200101 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +0200102}
103
Radek Krejcib05774c2015-06-18 13:52:59 +0200104static int
Radek Krejcib8048692015-08-05 13:36:34 +0200105dup_feature_check(const char *id, struct lys_module *module)
Radek Krejcib05774c2015-06-18 13:52:59 +0200106{
107 int i;
108
109 for (i = 0; i < module->features_size; i++) {
110 if (!strcmp(id, module->features[i].name)) {
111 return EXIT_FAILURE;
112 }
113 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +0200114
115 return EXIT_SUCCESS;
Radek Krejcib05774c2015-06-18 13:52:59 +0200116}
117
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200118static int
Radek Krejcib8048692015-08-05 13:36:34 +0200119dup_prefix_check(const char *prefix, struct lys_module *module)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200120{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200121 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200122
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200123 if (!module->type && module->prefix && !strcmp(module->prefix, prefix)) {
124 return EXIT_FAILURE;
125 }
126 for (i = 0; i < module->imp_size; i++) {
127 if (!strcmp(module->imp[i].prefix, prefix)) {
128 return EXIT_FAILURE;
129 }
130 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200131
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200132 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200133}
134
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200135static int
136check_identifier(const char *id, enum LY_IDENT type, unsigned int line,
Radek Krejcib8048692015-08-05 13:36:34 +0200137 struct lys_module *module, struct lys_node *parent)
Radek Krejcice7fb782015-05-29 16:52:34 +0200138{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200139 int i;
140 int size;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200141 struct lys_tpdf *tpdf;
Radek Krejci1d82ef62015-08-07 14:44:40 +0200142 struct lys_node *node;
Radek Krejcice7fb782015-05-29 16:52:34 +0200143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200144 assert(id);
Radek Krejcice7fb782015-05-29 16:52:34 +0200145
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200146 /* check id syntax */
147 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200148 LOGVAL(LYE_INID, line, id, "invalid start character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200149 return EXIT_FAILURE;
150 }
151 for (i = 1; id[i]; i++) {
152 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
153 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200154 LOGVAL(LYE_INID, line, id, "invalid character");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200155 return EXIT_FAILURE;
156 }
157 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200158
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200159 if (i > 64) {
160 LOGWRN("Identifier \"%s\" is long, you should use something shorter.", id);
161 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200162
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200163 switch (type) {
164 case LY_IDENT_NAME:
165 /* check uniqueness of the node within its siblings */
166 if (!parent) {
167 break;
168 }
Radek Krejcib4cf2022015-06-03 14:40:05 +0200169
Radek Krejci1d82ef62015-08-07 14:44:40 +0200170 LY_TREE_FOR(parent->child, node) {
171 if (node->name == id) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200172 LOGVAL(LYE_INID, line, id, "name duplication");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200173 return EXIT_FAILURE;
174 }
175 }
176 break;
177 case LY_IDENT_TYPE:
178 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200179
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200180 /* check collision with the built-in types */
181 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
182 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
183 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
184 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
185 !strcmp(id, "int8") || !strcmp(id, "int16") ||
186 !strcmp(id, "int32") || !strcmp(id, "int64") ||
187 !strcmp(id, "leafref") || !strcmp(id, "string") ||
188 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
189 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200190 LOGVAL(LYE_SPEC, line, "Typedef name duplicates built-in type.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200191 return EXIT_FAILURE;
192 }
Radek Krejcieac35532015-05-31 19:09:15 +0200193
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200194 /* check locally scoped typedefs (avoid name shadowing) */
195 for (; parent; parent = parent->parent) {
196 switch (parent->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +0200197 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +0200198 size = ((struct lys_node_container *)parent)->tpdf_size;
199 tpdf = ((struct lys_node_container *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200200 break;
Radek Krejci76512572015-08-04 09:47:08 +0200201 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +0200202 size = ((struct lys_node_list *)parent)->tpdf_size;
203 tpdf = ((struct lys_node_list *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200204 break;
Radek Krejci76512572015-08-04 09:47:08 +0200205 case LYS_GROUPING:
Radek Krejcib8048692015-08-05 13:36:34 +0200206 size = ((struct lys_node_grp *)parent)->tpdf_size;
207 tpdf = ((struct lys_node_grp *)parent)->tpdf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200208 break;
209 default:
210 continue;
211 }
Radek Krejcieac35532015-05-31 19:09:15 +0200212
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200213 if (dup_typedef_check(id, tpdf, size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200214 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200215 return EXIT_FAILURE;
216 }
217 }
Radek Krejcieac35532015-05-31 19:09:15 +0200218
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200219 /* check top-level names */
220 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200221 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200222 return EXIT_FAILURE;
223 }
Radek Krejcieac35532015-05-31 19:09:15 +0200224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200225 /* check submodule's top-level names */
226 for (i = 0; i < module->inc_size; i++) {
227 if (dup_typedef_check(id, module->inc[i].submodule->tpdf, module->inc[i].submodule->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200228 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200229 return EXIT_FAILURE;
230 }
231 }
Radek Krejcieac35532015-05-31 19:09:15 +0200232
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200233 /* check top-level names in the main module */
234 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +0200235 if (dup_typedef_check(id, ((struct lys_submodule *)module)->belongsto->tpdf,
236 ((struct lys_submodule *)module)->belongsto->tpdf_size)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200237 LOGVAL(LYE_DUPID, line, "typedef", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200238 return EXIT_FAILURE;
239 }
240 }
Radek Krejcieac35532015-05-31 19:09:15 +0200241
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200242 break;
243 case LY_IDENT_PREFIX:
244 assert(module);
Radek Krejcieac35532015-05-31 19:09:15 +0200245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200246 if (module->type) {
247 /* go to the main module */
Radek Krejcib8048692015-08-05 13:36:34 +0200248 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200249 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200250
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200251 /* check the main module itself */
252 if (dup_prefix_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200253 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200254 return EXIT_FAILURE;
255 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200256
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200257 /* and all its submodules */
258 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200259 if (dup_prefix_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200260 LOGVAL(LYE_DUPID, line, "prefix", id);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200261 return EXIT_FAILURE;
262 }
263 }
264 break;
Radek Krejcib05774c2015-06-18 13:52:59 +0200265 case LY_IDENT_FEATURE:
266 assert(module);
267
268 /* check feature name uniqness*/
Radek Krejci49babf32015-06-18 13:56:17 +0200269 /* check features in the current module */
Radek Krejcib05774c2015-06-18 13:52:59 +0200270 if (dup_feature_check(id, module)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200271 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200272 return EXIT_FAILURE;
273 }
274
275 /* and all its submodules */
276 for (i = 0; i < module->inc_size; i++) {
Radek Krejcib8048692015-08-05 13:36:34 +0200277 if (dup_feature_check(id, (struct lys_module *)module->inc[i].submodule)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200278 LOGVAL(LYE_DUPID, line, "feature", id);
Radek Krejcib05774c2015-06-18 13:52:59 +0200279 return EXIT_FAILURE;
280 }
281 }
282 break;
283
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200284 default:
285 /* no check required */
286 break;
287 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200288
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200289 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200290}
291
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200292static int
Radek Krejci1d82ef62015-08-07 14:44:40 +0200293check_mandatory(struct lys_node *node)
Radek Krejci3de29a72015-06-16 15:23:03 +0200294{
Radek Krejci76512572015-08-04 09:47:08 +0200295 struct lys_node *child;
Radek Krejci3de29a72015-06-16 15:23:03 +0200296
Radek Krejci1d82ef62015-08-07 14:44:40 +0200297 assert(node);
Radek Krejci3de29a72015-06-16 15:23:03 +0200298
Radek Krejci1d82ef62015-08-07 14:44:40 +0200299 if (node->flags & LYS_MAND_TRUE) {
Radek Krejci3de29a72015-06-16 15:23:03 +0200300 return EXIT_FAILURE;
301 }
302
Radek Krejci1d82ef62015-08-07 14:44:40 +0200303 if (node->nodetype == LYS_CASE || node->nodetype == LYS_CHOICE) {
304 LY_TREE_FOR(node->child, child) {
Radek Krejcifd0bb0a2015-06-18 13:18:24 +0200305 if (check_mandatory(child)) {
306 return EXIT_FAILURE;
307 }
Radek Krejci3de29a72015-06-16 15:23:03 +0200308 }
309 }
310
311 return EXIT_SUCCESS;
312}
313
314static int
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200315check_date(const char *date, unsigned int line)
Radek Krejcice7fb782015-05-29 16:52:34 +0200316{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200317 int i;
Radek Krejcice7fb782015-05-29 16:52:34 +0200318
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200319 assert(date);
Radek Krejcice7fb782015-05-29 16:52:34 +0200320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200321 if (strlen(date) != LY_REV_SIZE - 1) {
322 goto error;
323 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200324
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200325 for (i = 0; i < LY_REV_SIZE - 1; i++) {
326 if (i == 4 || i == 7) {
327 if (date[i] != '-') {
328 goto error;
329 }
330 } else if (!isdigit(date[i])) {
331 goto error;
332 }
333 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200334
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200335 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +0200336
337error:
338
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200339 LOGVAL(LYE_INDATE, line, date);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200340 return EXIT_FAILURE;
Radek Krejcice7fb782015-05-29 16:52:34 +0200341}
342
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200343static const char *
344read_yin_subnode(struct ly_ctx *ctx, struct lyxml_elem *node, const char *name)
Radek Krejcice7fb782015-05-29 16:52:34 +0200345{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200346 int len;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200347
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200348 /* there should be <text> child */
349 if (!node->child || !node->child->name || strcmp(node->child->name, name)) {
350 LOGWRN("Expected \"%s\" element in \"%s\" element.", name, node->name);
351 } else if (node->child->content) {
352 len = strlen(node->child->content);
353 return lydict_insert(ctx, node->child->content, len);
354 }
Radek Krejcice7fb782015-05-29 16:52:34 +0200355
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200356 LOGVAL(LYE_INARG, LOGLINE(node), name, node->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200357 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200358}
359
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200360static int
Michal Vaskof02e3742015-08-05 16:27:02 +0200361fill_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 +0200362{
Radek Krejci73adb602015-07-02 18:07:40 +0200363 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200364 const char *value;
Radek Krejci04581c62015-05-22 21:24:00 +0200365
Michal Vasko4cfcd252015-08-03 14:31:10 +0200366 GETVAL(value, yin, "name");
367 ident->name = lydict_insert(module->ctx, value, 0);
368
Radek Krejci76512572015-08-04 09:47:08 +0200369 if (read_yin_common(module, NULL, (struct lys_node *)ident, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200370 return EXIT_FAILURE;
371 }
Radek Krejci04581c62015-05-22 21:24:00 +0200372
Radek Krejci73adb602015-07-02 18:07:40 +0200373 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200374 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
375 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200376 continue;
377 }
378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200379 if (!strcmp(node->name, "base")) {
380 if (ident->base) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200381 LOGVAL(LYE_TOOMANY, LOGLINE(node), "base", "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200382 return EXIT_FAILURE;
383 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200384 GETVAL(value, node, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200385 if (unres_add_str(module, unres, ident, UNRES_IDENT, value, LOGLINE(node)) == -1) {
386 return EXIT_FAILURE;
387 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200388 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200389 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name, "identity");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200390 return EXIT_FAILURE;
391 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200392 }
Radek Krejci04581c62015-05-22 21:24:00 +0200393
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200394error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200395 return EXIT_SUCCESS;
Radek Krejci04581c62015-05-22 21:24:00 +0200396}
397
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200398static int
Radek Krejci1574a8d2015-08-03 14:16:52 +0200399read_restr_substmt(struct ly_ctx *ctx, struct lys_restr *restr, struct lyxml_elem *yin)
Radek Krejci41726f92015-06-19 13:11:05 +0200400{
Radek Krejci73adb602015-07-02 18:07:40 +0200401 struct lyxml_elem *child;
Radek Krejci461d1622015-06-30 14:06:28 +0200402 const char *value;
Radek Krejci41726f92015-06-19 13:11:05 +0200403
Radek Krejci73adb602015-07-02 18:07:40 +0200404 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200405 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
406 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200407 continue;
408 }
409
Radek Krejci41726f92015-06-19 13:11:05 +0200410 if (!strcmp(child->name, "description")) {
411 if (restr->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200412 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200413 return EXIT_FAILURE;
414 }
415 restr->dsc = read_yin_subnode(ctx, child, "text");
416 if (!restr->dsc) {
417 return EXIT_FAILURE;
418 }
419 } else if (!strcmp(child->name, "reference")) {
420 if (restr->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200421 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200422 return EXIT_FAILURE;
423 }
424 restr->ref = read_yin_subnode(ctx, child, "text");
425 if (!restr->ref) {
426 return EXIT_FAILURE;
427 }
428 } else if (!strcmp(child->name, "error-app-tag")) {
429 if (restr->eapptag) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200430 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200431 return EXIT_FAILURE;
432 }
Michal Vasko54e426f2015-07-07 15:38:02 +0200433 GETVAL(value, child, "value");
Radek Krejci461d1622015-06-30 14:06:28 +0200434 restr->eapptag = lydict_insert(ctx, value, 0);
Radek Krejci41726f92015-06-19 13:11:05 +0200435 } else if (!strcmp(child->name, "error-message")) {
436 if (restr->emsg) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200437 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200438 return EXIT_FAILURE;
439 }
440 restr->emsg = read_yin_subnode(ctx, child, "value");
441 if (!restr->emsg) {
442 return EXIT_FAILURE;
443 }
444 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200445 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200446 return EXIT_FAILURE;
447 }
Radek Krejci41726f92015-06-19 13:11:05 +0200448 }
449
450 return EXIT_SUCCESS;
Michal Vaskoc8ef47f2015-06-29 14:56:19 +0200451
452error:
453 return EXIT_FAILURE;
Radek Krejci41726f92015-06-19 13:11:05 +0200454}
455
456static int
Radek Krejcib8048692015-08-05 13:36:34 +0200457fill_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 +0200458 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +0200459{
Michal Vasko69068852015-07-13 14:34:31 +0200460#define REGEX_ERR_LEN 128
Radek Krejcif2860132015-06-20 12:37:20 +0200461 const char *value, *delim, *name;
Michal Vasko69068852015-07-13 14:34:31 +0200462 char regex_err[REGEX_ERR_LEN];
Radek Krejci5fbc9162015-06-19 14:11:11 +0200463 struct lyxml_elem *next, *node;
Radek Krejci1574a8d2015-08-03 14:16:52 +0200464 struct lys_restr **restr;
465 struct lys_type_bit bit;
Michal Vasko69068852015-07-13 14:34:31 +0200466 regex_t preq;
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200467 int i, j, rc;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200468 int64_t v, v_;
Radek Krejci994b6f62015-06-18 16:47:27 +0200469 int64_t p, p_;
Radek Krejcida04f4a2015-05-21 12:54:09 +0200470
Radek Krejci8de7b0f2015-07-02 11:43:42 +0200471 GETVAL(value, yin, "name");
472
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200473 delim = strchr(value, ':');
474 if (delim) {
475 type->prefix = lydict_insert(module->ctx, value, delim - value);
476 delim++;
477 value += delim-value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200478 }
Radek Krejci667b97f2015-05-25 15:03:30 +0200479
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200480 rc = resolve_superior_type(value, type->prefix, module, parent, &type->der);
481 if (rc) {
482 if (rc == EXIT_FAILURE) {
483 /* HACK for unres */
484 type->der = (struct lys_tpdf *)parent;
485 rc = unres_add_str(module, unres, type, UNRES_TYPE_DER, value, LOGLINE(yin));
486 }
487 if (rc == -1) {
488 goto error;
489 }
490
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200491 return EXIT_SUCCESS;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200492 }
493 type->base = type->der->type.base;
Radek Krejci25d782a2015-05-22 15:03:23 +0200494
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200495 switch (type->base) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200496 case LY_TYPE_BITS:
Radek Krejci994b6f62015-06-18 16:47:27 +0200497 /* RFC 6020 9.7.4 - bit */
498
499 /* get bit specifications, at least one must be present */
500 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200501 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
502 /* garbage */
503 lyxml_free_elem(module->ctx, node);
504 continue;
505 }
506
Radek Krejci994b6f62015-06-18 16:47:27 +0200507 if (!strcmp(node->name, "bit")) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200508 type->info.bits.count++;
Radek Krejci41726f92015-06-19 13:11:05 +0200509 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200510 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci41726f92015-06-19 13:11:05 +0200511 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200512 }
513 }
Radek Krejciac781922015-07-09 15:35:14 +0200514 if (!type->der->type.der && !type->info.bits.count) {
515 /* type is derived directly from buit-in bits type and bit statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200516 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "bit", "type");
Radek Krejci994b6f62015-06-18 16:47:27 +0200517 goto error;
518 }
Radek Krejciac781922015-07-09 15:35:14 +0200519 if (type->der->type.der && type->info.bits.count) {
520 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200521 LOGVAL(LYE_INSTMT, LOGLINE(yin), "bit");
Radek Krejciac781922015-07-09 15:35:14 +0200522 goto error;
523 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200524
525 type->info.bits.bit = calloc(type->info.bits.count, sizeof *type->info.bits.bit);
Radek Krejci73adb602015-07-02 18:07:40 +0200526 p = 0;
527 i = -1;
528 LY_TREE_FOR(yin->child, next) {
529 i++;
530
531 GETVAL(value, next, "name");
532 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200533 goto error;
534 }
535 type->info.bits.bit[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200536 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.bits.bit[i], next, 0)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200537 type->info.bits.count = i + 1;
538 goto error;
539 }
540
541 /* check the name uniqueness */
542 for (j = 0; j < i; j++) {
543 if (!strcmp(type->info.bits.bit[j].name, type->info.bits.bit[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200544 LOGVAL(LYE_BITS_DUPNAME, LOGLINE(next), type->info.bits.bit[i].name);
Radek Krejci994b6f62015-06-18 16:47:27 +0200545 type->info.bits.count = i + 1;
546 goto error;
547 }
548 }
549
Radek Krejci0d70c372015-07-02 16:23:10 +0200550 p_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200551 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200552 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
553 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200554 continue;
Radek Krejci994b6f62015-06-18 16:47:27 +0200555 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200556
Radek Krejci0d70c372015-07-02 16:23:10 +0200557 if (!strcmp(node->name, "position")) {
558 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200559 p_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200560
561 /* range check */
Radek Krejcib8ca1082015-07-10 11:24:11 +0200562 if (p_ < 0 || p_ > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200563 LOGVAL(LYE_INARG, LOGLINE(node), value, "bit/position");
Radek Krejci0d70c372015-07-02 16:23:10 +0200564 type->info.bits.count = i + 1;
565 goto error;
566 }
567 type->info.bits.bit[i].pos = (uint32_t)p_;
568
569 /* keep the highest enum value for automatic increment */
Michal Vasko9ab05942015-07-07 15:38:26 +0200570 if (type->info.bits.bit[i].pos >= p) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200571 p = type->info.bits.bit[i].pos;
572 p++;
573 } else {
574 /* check that the value is unique */
575 for (j = 0; j < i; j++) {
576 if (type->info.bits.bit[j].pos == type->info.bits.bit[i].pos) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200577 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 +0200578 type->info.bits.count = i + 1;
579 goto error;
580 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200581 }
582 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200583 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200584 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200585 goto error;
Radek Krejci994b6f62015-06-18 16:47:27 +0200586 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200587 }
588 if (p_ == -1) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200589 /* assign value automatically */
590 if (p > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200591 LOGVAL(LYE_INARG, LOGLINE(next), "4294967295", "bit/position");
Radek Krejci994b6f62015-06-18 16:47:27 +0200592 type->info.bits.count = i + 1;
593 goto error;
594 }
595 type->info.bits.bit[i].pos = (uint32_t)p;
596 p++;
597 }
Radek Krejci9a1b95a2015-07-09 15:32:21 +0200598
599 /* keep them ordered by position */
600 j = i;
601 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
602 /* switch them */
603 memcpy(&bit, &type->info.bits.bit[j], sizeof bit);
604 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit);
605 memcpy(&type->info.bits.bit[j - 1], &bit, sizeof bit);
606 j--;
607 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200608 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200609 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200610
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200611 case LY_TYPE_DEC64:
Radek Krejcif9401c32015-06-26 16:47:36 +0200612 /* RFC 6020 9.2.4 - range and 9.3.4 - fraction-digits */
Radek Krejci73adb602015-07-02 18:07:40 +0200613 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200614 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
615 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200616 continue;
617 }
618
Radek Krejcif9401c32015-06-26 16:47:36 +0200619 if (!strcmp(node->name, "range")) {
620 if (type->info.dec64.range) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200621 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200622 goto error;
623 }
624
625 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200626 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200627 LOGVAL(LYE_INARG, LOGLINE(node), value, "range");
Radek Krejcif9401c32015-06-26 16:47:36 +0200628 goto error;
629 }
630 type->info.dec64.range = calloc(1, sizeof *type->info.dec64.range);
631 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
632
633 /* get possible substatements */
634 if (read_restr_substmt(module->ctx, type->info.dec64.range, node)) {
635 goto error;
636 }
637 } else if (!strcmp(node->name, "fraction-digits")) {
638 if (type->info.dec64.dig) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200639 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200640 goto error;
641 }
642 GETVAL(value, node, "value");
643 v = strtol(value, NULL, 10);
644
645 /* range check */
646 if (v < 1 || v > 18) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200647 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200648 goto error;
649 }
650 type->info.dec64.dig = (uint8_t)v;
651 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200652 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif9401c32015-06-26 16:47:36 +0200653 goto error;
654 }
Radek Krejcif9401c32015-06-26 16:47:36 +0200655 }
656
657 /* mandatory sub-statement(s) check */
658 if (!type->info.dec64.dig && !type->der->type.der) {
659 /* decimal64 type directly derived from built-in type requires fraction-digits */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200660 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "fraction-digits", "type");
Radek Krejcif9401c32015-06-26 16:47:36 +0200661 goto error;
662 }
Radek Krejci7511f402015-07-10 09:56:30 +0200663 if (type->info.dec64.dig && type->der->type.der) {
664 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200665 LOGVAL(LYE_INSTMT, LOGLINE(yin), "fraction-digits");
Radek Krejci7511f402015-07-10 09:56:30 +0200666 goto error;
667 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200668 break;
Radek Krejci25d782a2015-05-22 15:03:23 +0200669
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200670 case LY_TYPE_ENUM:
Radek Krejci994b6f62015-06-18 16:47:27 +0200671 /* RFC 6020 9.6 - enum */
Radek Krejci25d782a2015-05-22 15:03:23 +0200672
Radek Krejci994b6f62015-06-18 16:47:27 +0200673 /* get enum specifications, at least one must be present */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200674 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200675 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
676 /* garbage */
677 lyxml_free_elem(module->ctx, node);
678 continue;
679 }
680
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200681 if (!strcmp(node->name, "enum")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200682 type->info.enums.count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +0200683 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200684 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200685 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200686 }
687 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200688 if (!type->der->type.der && !type->info.enums.count) {
689 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200690 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "enum", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200691 goto error;
692 }
Radek Krejcib54bcb12015-07-10 13:16:40 +0200693 if (type->der->type.der && type->info.enums.count) {
694 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200695 LOGVAL(LYE_INSTMT, LOGLINE(yin), "enum");
Radek Krejcib54bcb12015-07-10 13:16:40 +0200696 goto error;
697 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200698
Radek Krejci1574a8d2015-08-03 14:16:52 +0200699 type->info.enums.enm = calloc(type->info.enums.count, sizeof *type->info.enums.enm);
Radek Krejci73adb602015-07-02 18:07:40 +0200700 v = 0;
701 i = -1;
702 LY_TREE_FOR(yin->child, next) {
703 i++;
704
705 GETVAL(value, next, "name");
706 if (check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
Radek Krejci994b6f62015-06-18 16:47:27 +0200707 goto error;
708 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200709 type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci76512572015-08-04 09:47:08 +0200710 if (read_yin_common(module, NULL, (struct lys_node *)&type->info.enums.enm[i], next, 0)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200711 type->info.enums.count = i + 1;
712 goto error;
713 }
Radek Krejci994b6f62015-06-18 16:47:27 +0200714
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200715 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200716 value = type->info.enums.enm[i].name;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200717 if (isspace(value[0]) || isspace(value[strlen(value) - 1])) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200718 LOGVAL(LYE_ENUM_WS, LOGLINE(next), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200719 type->info.enums.count = i + 1;
720 goto error;
721 }
Radek Krejci25d782a2015-05-22 15:03:23 +0200722
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200723 /* check the name uniqueness */
724 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200725 if (!strcmp(type->info.enums.enm[j].name, type->info.enums.enm[i].name)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200726 LOGVAL(LYE_ENUM_DUPNAME, LOGLINE(next), type->info.enums.enm[i].name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200727 type->info.enums.count = i + 1;
728 goto error;
729 }
730 }
Radek Krejci04581c62015-05-22 21:24:00 +0200731
Radek Krejci0d70c372015-07-02 16:23:10 +0200732 v_ = -1;
Radek Krejci73adb602015-07-02 18:07:40 +0200733 LY_TREE_FOR(next->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200734 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
735 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200736 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200737 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200738
Radek Krejci0d70c372015-07-02 16:23:10 +0200739 if (!strcmp(node->name, "value")) {
740 GETVAL(value, node, "value");
Radek Krejci7511f402015-07-10 09:56:30 +0200741 v_ = strtoll(value, NULL, 10);
Radek Krejci0d70c372015-07-02 16:23:10 +0200742
743 /* range check */
744 if (v_ < INT32_MIN || v_ > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200745 LOGVAL(LYE_INARG, LOGLINE(node), value, "enum/value");
Radek Krejci0d70c372015-07-02 16:23:10 +0200746 type->info.enums.count = i + 1;
747 goto error;
748 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200749 type->info.enums.enm[i].value = v_;
Radek Krejci0d70c372015-07-02 16:23:10 +0200750
751 /* keep the highest enum value for automatic increment */
Radek Krejci1574a8d2015-08-03 14:16:52 +0200752 if (type->info.enums.enm[i].value > v) {
753 v = type->info.enums.enm[i].value;
Radek Krejci0d70c372015-07-02 16:23:10 +0200754 v++;
755 } else {
756 /* check that the value is unique */
757 for (j = 0; j < i; j++) {
Radek Krejci1574a8d2015-08-03 14:16:52 +0200758 if (type->info.enums.enm[j].value == type->info.enums.enm[i].value) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200759 LOGVAL(LYE_ENUM_DUPVAL, LOGLINE(node), type->info.enums.enm[i].value,
Radek Krejci1574a8d2015-08-03 14:16:52 +0200760 type->info.enums.enm[i].name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200761 type->info.enums.count = i + 1;
762 goto error;
763 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200764 }
765 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200766 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200767 LOGVAL(LYE_INSTMT, LOGLINE(next), next->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200768 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200769 }
Radek Krejci0d70c372015-07-02 16:23:10 +0200770 }
771 if (v_ == -1) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200772 /* assign value automatically */
773 if (v > INT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200774 LOGVAL(LYE_INARG, LOGLINE(next), "2147483648", "enum/value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200775 type->info.enums.count = i + 1;
776 goto error;
777 }
Radek Krejci1574a8d2015-08-03 14:16:52 +0200778 type->info.enums.enm[i].value = v;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200779 v++;
780 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200781 }
782 break;
783
784 case LY_TYPE_IDENT:
Radek Krejci994b6f62015-06-18 16:47:27 +0200785 /* RFC 6020 9.10 - base */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200786
787 /* get base specification, exactly one must be present */
Radek Krejci0d70c372015-07-02 16:23:10 +0200788 LY_TREE_FOR_SAFE(yin->child, next, node) {
789 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
790 /* garbage */
791 lyxml_free_elem(module->ctx, node);
792 continue;
793 }
794
795 if (strcmp(yin->child->name, "base")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200796 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +0200797 goto error;
798 }
799 }
800
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200801 if (!yin->child) {
Radek Krejci65c889c2015-06-22 10:17:22 +0200802 if (type->der->type.der) {
803 /* this is just a derived type with no base specified/required */
804 break;
805 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200806 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "base", "type");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200807 goto error;
808 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200809 if (yin->child->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200810 LOGVAL(LYE_TOOMANY, LOGLINE(yin->child->next), yin->child->next->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200811 goto error;
812 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200813 GETVAL(value, yin->child, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200814 if (unres_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, LOGLINE(yin->child)) == -1) {
815 goto error;
816 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200817 break;
818
819 case LY_TYPE_INST:
Radek Krejciaf351422015-06-19 14:49:38 +0200820 /* RFC 6020 9.13.2 - require-instance */
Radek Krejci73adb602015-07-02 18:07:40 +0200821 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200822 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
823 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200824 continue;
825 }
826
Radek Krejciaf351422015-06-19 14:49:38 +0200827 if (!strcmp(node->name, "require-instance")) {
828 if (type->info.inst.req) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200829 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200830 goto error;
831 }
832 GETVAL(value, node, "value");
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200833 if (!strcmp(value, "true")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200834 type->info.inst.req = 1;
Michal Vasko25fa5ac2015-07-17 10:53:38 +0200835 } else if (!strcmp(value, "false")) {
Radek Krejciaf351422015-06-19 14:49:38 +0200836 type->info.inst.req = -1;
837 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200838 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200839 goto error;
840 }
841 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200842 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejciaf351422015-06-19 14:49:38 +0200843 goto error;
844 }
Radek Krejciaf351422015-06-19 14:49:38 +0200845 }
Michal Vasko8548cf92015-07-20 15:17:53 +0200846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200847 break;
848
Radek Krejcif2860132015-06-20 12:37:20 +0200849 case LY_TYPE_BINARY:
850 /* RFC 6020 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200851 case LY_TYPE_INT8:
852 case LY_TYPE_INT16:
853 case LY_TYPE_INT32:
854 case LY_TYPE_INT64:
855 case LY_TYPE_UINT8:
856 case LY_TYPE_UINT16:
857 case LY_TYPE_UINT32:
858 case LY_TYPE_UINT64:
Radek Krejcif2860132015-06-20 12:37:20 +0200859 /* RFC 6020 9.2.4 - range */
860
861 /* length and range are actually the same restriction, so process
862 * them by this common code, we just need to differ the name and
863 * structure where the information will be stored
864 */
865 if (type->base == LY_TYPE_BINARY) {
866 restr = &type->info.binary.length;
867 name = "length";
868 } else {
869 restr = &type->info.num.range;
870 name = "range";
871 }
872
Radek Krejci73adb602015-07-02 18:07:40 +0200873 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200874 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
875 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200876 continue;
877 }
878
Radek Krejcif2860132015-06-20 12:37:20 +0200879 if (!strcmp(node->name, name)) {
880 if (*restr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200881 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200882 goto error;
883 }
884
885 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200886 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200887 LOGVAL(LYE_INARG, LOGLINE(node), value, name);
Radek Krejcif2860132015-06-20 12:37:20 +0200888 goto error;
889 }
890 *restr = calloc(1, sizeof **restr);
891 (*restr)->expr = lydict_insert(module->ctx, value, 0);
892
893 /* get possible substatements */
894 if (read_restr_substmt(module->ctx, *restr, node)) {
895 goto error;
896 }
897 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200898 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcif2860132015-06-20 12:37:20 +0200899 goto error;
900 }
Radek Krejcif2860132015-06-20 12:37:20 +0200901 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200902 break;
903
904 case LY_TYPE_LEAFREF:
Radek Krejcidc4c1412015-06-19 15:39:54 +0200905 /* RFC 6020 9.9.2 - path */
Radek Krejci73adb602015-07-02 18:07:40 +0200906 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200907 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
908 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +0200909 continue;
910 }
911
Radek Krejcidc4c1412015-06-19 15:39:54 +0200912 if (!strcmp(node->name, "path")) {
913 if (type->info.lref.path) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200914 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200915 goto error;
916 }
917
918 GETVAL(value, node, "value");
Radek Krejcidc4c1412015-06-19 15:39:54 +0200919 type->info.lref.path = lydict_insert(module->ctx, value, 0);
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200920 if (unres_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent, LOGLINE(yin)) == -1) {
921 goto error;
922 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +0200923
Radek Krejcidc4c1412015-06-19 15:39:54 +0200924 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200925 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcidc4c1412015-06-19 15:39:54 +0200926 goto error;
927 }
Radek Krejci73adb602015-07-02 18:07:40 +0200928 }
929
930 if (!type->info.lref.path) {
931 if (type->der->type.der) {
932 /* this is just a derived type with no path specified/required */
933 break;
934 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200935 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "path", "type");
Radek Krejci73adb602015-07-02 18:07:40 +0200936 goto error;
Radek Krejcidc4c1412015-06-19 15:39:54 +0200937 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +0200938 break;
939
940 case LY_TYPE_STRING:
Radek Krejci3733a802015-06-19 13:43:21 +0200941 /* RFC 6020 9.4.4 - length */
942 /* RFC 6020 9.4.6 - pattern */
Radek Krejci73adb602015-07-02 18:07:40 +0200943 i = 0;
Radek Krejci3733a802015-06-19 13:43:21 +0200944 LY_TREE_FOR_SAFE(yin->child, next, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +0200945 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
946 /* garbage */
947 lyxml_free_elem(module->ctx, node);
948 continue;
949 }
950
Radek Krejci3733a802015-06-19 13:43:21 +0200951 if (!strcmp(node->name, "length")) {
952 if (type->info.str.length) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200953 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200954 goto error;
955 }
956
957 GETVAL(value, node, "value");
Radek Krejci6dc53a22015-08-17 13:27:59 +0200958 if (lyp_check_length_range(value, type)) {
Michal Vasko9c1bc642015-08-05 16:25:53 +0200959 LOGVAL(LYE_INARG, LOGLINE(node), value, "length");
Radek Krejci3733a802015-06-19 13:43:21 +0200960 goto error;
961 }
962 type->info.str.length = calloc(1, sizeof *type->info.str.length);
963 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
964
Radek Krejci5fbc9162015-06-19 14:11:11 +0200965 /* get possible sub-statements */
966 if (read_restr_substmt(module->ctx, type->info.str.length, node)) {
Radek Krejci3733a802015-06-19 13:43:21 +0200967 goto error;
968 }
Radek Krejci82d971d2015-06-19 14:20:50 +0200969 lyxml_free_elem(module->ctx, node);
Radek Krejci3733a802015-06-19 13:43:21 +0200970 } else if (!strcmp(node->name, "pattern")) {
Radek Krejci73adb602015-07-02 18:07:40 +0200971 i++;
Radek Krejci3733a802015-06-19 13:43:21 +0200972 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200973 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejci3733a802015-06-19 13:43:21 +0200974 goto error;
975 }
976 }
Radek Krejci5fbc9162015-06-19 14:11:11 +0200977 /* store patterns in array */
Radek Krejci73adb602015-07-02 18:07:40 +0200978 if (i) {
979 type->info.str.patterns = calloc(i, sizeof *type->info.str.patterns);
980 LY_TREE_FOR(yin->child, node) {
Radek Krejci5fbc9162015-06-19 14:11:11 +0200981 GETVAL(value, yin->child, "value");
Michal Vasko69068852015-07-13 14:34:31 +0200982
983 /* check that the regex is valid */
Michal Vasko3ab70fc2015-08-17 14:06:23 +0200984 if ((rc = regcomp(&preq, value, REG_EXTENDED | REG_NOSUB)) != 0) {
985 regerror(rc, &preq, regex_err, REGEX_ERR_LEN);
Michal Vasko69068852015-07-13 14:34:31 +0200986 regfree(&preq);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +0200987 LOGVAL(LYE_INREGEX, LOGLINE(node), value, regex_err);
Michal Vasko69068852015-07-13 14:34:31 +0200988 free(type->info.str.patterns);
989 goto error;
990 }
991 regfree(&preq);
992
Radek Krejci73adb602015-07-02 18:07:40 +0200993 type->info.str.patterns[type->info.str.pat_count].expr = lydict_insert(module->ctx, value, 0);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200994
995 /* get possible sub-statements */
Radek Krejci73adb602015-07-02 18:07:40 +0200996 if (read_restr_substmt(module->ctx, &type->info.str.patterns[type->info.str.pat_count], yin->child)) {
Michal Vasko69068852015-07-13 14:34:31 +0200997 free(type->info.str.patterns);
Radek Krejci5fbc9162015-06-19 14:11:11 +0200998 goto error;
999 }
Radek Krejci73adb602015-07-02 18:07:40 +02001000 type->info.str.pat_count++;
Radek Krejci5fbc9162015-06-19 14:11:11 +02001001 }
1002 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001003 break;
1004
1005 case LY_TYPE_UNION:
Radek Krejcie4c366b2015-07-02 10:11:31 +02001006 /* RFC 6020 7.4 - type */
1007 /* count number of types in union */
1008 i = 0;
Radek Krejci0d70c372015-07-02 16:23:10 +02001009 LY_TREE_FOR_SAFE(yin->child, next, node) {
1010 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1011 /* garbage */
1012 lyxml_free_elem(module->ctx, node);
1013 continue;
1014 }
1015
Radek Krejcie4c366b2015-07-02 10:11:31 +02001016 if (!strcmp(node->name, "type")) {
1017 i++;
1018 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001019 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001020 goto error;
1021 }
1022 }
1023
1024 if (!i) {
1025 if (type->der->type.der) {
1026 /* this is just a derived type with no base specified/required */
1027 break;
1028 }
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001029 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", "(union) type");
Radek Krejcie4c366b2015-07-02 10:11:31 +02001030 goto error;
1031 }
1032
1033 /* allocate array for union's types ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001034 type->info.uni.types = calloc(i, sizeof *type->info.uni.types);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001035 /* ... and fill the structures */
Radek Krejci73adb602015-07-02 18:07:40 +02001036 LY_TREE_FOR(yin->child, node) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001037 if (fill_yin_type(module, parent, node, &type->info.uni.types[type->info.uni.count], unres)) {
Radek Krejcie4c366b2015-07-02 10:11:31 +02001038 goto error;
1039 }
1040 type->info.uni.count++;
1041
1042 /* union's type cannot be empty or leafref */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001043 if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_EMPTY) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001044 LOGVAL(LYE_INARG, LOGLINE(node), "empty", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001045 goto error;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001046 } else if (type->info.uni.types[type->info.uni.count - 1].base == LY_TYPE_LEAFREF) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001047 LOGVAL(LYE_INARG, LOGLINE(node), "leafref", node->name);
Radek Krejcie4c366b2015-07-02 10:11:31 +02001048 goto error;
1049 }
Radek Krejcie4c366b2015-07-02 10:11:31 +02001050 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001051 break;
1052
1053 default:
Radek Krejci6e328cd2015-06-26 16:24:11 +02001054 /* no sub-statement allowed in:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001055 * LY_TYPE_BOOL, LY_TYPE_EMPTY
1056 */
Radek Krejci0d70c372015-07-02 16:23:10 +02001057 LY_TREE_FOR(yin->child, node) {
1058 if (node->ns && !strcmp(node->ns->value, LY_NSYIN)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001059 LOGVAL(LYE_INSTMT, LOGLINE(yin->child), yin->child->name);
Radek Krejci0d70c372015-07-02 16:23:10 +02001060 goto error;
1061 }
Radek Krejci6e328cd2015-06-26 16:24:11 +02001062 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001063 break;
1064 }
1065
1066 return EXIT_SUCCESS;
Radek Krejci25d782a2015-05-22 15:03:23 +02001067
1068error:
1069
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001070 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001071}
1072
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001073static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001074fill_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 +02001075{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001076 const char *value;
Radek Krejci73adb602015-07-02 18:07:40 +02001077 struct lyxml_elem *node;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001078 int has_type = 0, dflt_line;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001079
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001080 GETVAL(value, yin, "name");
1081 if (check_identifier(value, LY_IDENT_TYPE, LOGLINE(yin), module, parent)) {
1082 goto error;
1083 }
1084 tpdf->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejcida04f4a2015-05-21 12:54:09 +02001085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001086 /* generic part - status, description, reference */
Radek Krejci76512572015-08-04 09:47:08 +02001087 if (read_yin_common(module, NULL, (struct lys_node *)tpdf, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001088 goto error;
1089 }
Radek Krejcieac35532015-05-31 19:09:15 +02001090
Radek Krejci73adb602015-07-02 18:07:40 +02001091 LY_TREE_FOR(yin->child, node) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001092 if (!node->ns || strcmp(node->ns->value, LY_NSYIN)) {
1093 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02001094 continue;
1095 }
1096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001097 if (!strcmp(node->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001098 if (tpdf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001099 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001100 goto error;
1101 }
Radek Krejci73adb602015-07-02 18:07:40 +02001102 if (fill_yin_type(module, parent, node, &tpdf->type, unres)) {
1103 goto error;
1104 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001105 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001106 } else if (!strcmp(node->name, "default")) {
1107 if (tpdf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001108 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001109 goto error;
1110 }
1111 GETVAL(value, node, "value");
1112 tpdf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001113 dflt_line = LOGLINE(node);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001114 } else if (!strcmp(node->name, "units")) {
1115 if (tpdf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001116 LOGVAL(LYE_TOOMANY, LOGLINE(node), node->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001117 goto error;
1118 }
1119 GETVAL(value, node, "name");
1120 tpdf->units = lydict_insert(module->ctx, value, strlen(value));
1121 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001122 LOGVAL(LYE_INSTMT, LOGLINE(node), value);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001123 goto error;
1124 }
1125 }
Radek Krejci25d782a2015-05-22 15:03:23 +02001126
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001127 /* check mandatory value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001128 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001129 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001130 goto error;
1131 }
Radek Krejcieac35532015-05-31 19:09:15 +02001132
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001133 /* check default value */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001134 if (tpdf->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001135 if (unres_add_str(module, unres, &tpdf->type, UNRES_TYPE_DFLT, tpdf->dflt, dflt_line) == -1) {
1136 goto error;
1137 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001138 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02001139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001140 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02001141
1142error:
1143
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001144 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02001145}
1146
Radek Krejci3cf9e222015-06-18 11:37:50 +02001147static int
Michal Vaskof02e3742015-08-05 16:27:02 +02001148fill_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 +02001149{
1150 const char *value;
1151 struct lyxml_elem *child, *next;
1152 int c = 0;
1153
Radek Krejcib05774c2015-06-18 13:52:59 +02001154 GETVAL(value, yin, "name");
1155 if (check_identifier(value, LY_IDENT_FEATURE, LOGLINE(yin), module, NULL)) {
1156 goto error;
1157 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001158 f->name = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci6a113852015-07-03 16:04:20 +02001159 f->module = module;
Radek Krejcib05774c2015-06-18 13:52:59 +02001160
Radek Krejci76512572015-08-04 09:47:08 +02001161 if (read_yin_common(module, NULL, (struct lys_node *)f, yin, 0)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001162 goto error;
1163 }
1164
1165 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001166 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1167 /* garbage */
1168 lyxml_free_elem(module->ctx, child);
1169 continue;
1170 }
1171
Radek Krejci3cf9e222015-06-18 11:37:50 +02001172 if (!strcmp(child->name, "if-feature")) {
1173 c++;
1174 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001175 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001176 goto error;
1177 }
1178 }
1179
1180 if (c) {
1181 f->features = calloc(c, sizeof *f->features);
1182 }
Radek Krejci73adb602015-07-02 18:07:40 +02001183 LY_TREE_FOR(yin->child, child) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001184 GETVAL(value, child, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001185 if (unres_add_str(module, unres, &f->features[f->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
1186 goto error;
1187 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02001188 }
1189
Radek Krejci3cf9e222015-06-18 11:37:50 +02001190 return EXIT_SUCCESS;
1191
1192error:
1193
1194 return EXIT_FAILURE;
1195}
1196
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001197static int
Radek Krejcib8048692015-08-05 13:36:34 +02001198fill_yin_must(struct lys_module *module, struct lyxml_elem *yin, struct lys_restr *must)
Radek Krejci800af702015-06-02 13:46:01 +02001199{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001200 const char *value;
Radek Krejci800af702015-06-02 13:46:01 +02001201
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001202 GETVAL(value, yin, "condition");
Radek Krejci0bd5db42015-06-19 13:30:07 +02001203 must->expr = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02001204
Radek Krejci41726f92015-06-19 13:11:05 +02001205 return read_restr_substmt(module->ctx, must, yin);
Radek Krejci800af702015-06-02 13:46:01 +02001206
Radek Krejci41726f92015-06-19 13:11:05 +02001207error: /* GETVAL requires this label */
Radek Krejci800af702015-06-02 13:46:01 +02001208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001209 return EXIT_FAILURE;
Radek Krejci800af702015-06-02 13:46:01 +02001210}
1211
Radek Krejcieb00f512015-07-01 16:44:58 +02001212/*
1213 * type: 0 - min, 1 - max
1214 */
1215static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001216deviate_minmax(struct lys_node *target, struct lyxml_elem *node, struct lys_deviate *d, int type)
Radek Krejcieb00f512015-07-01 16:44:58 +02001217{
1218 const char *value;
1219 char *endptr;
1220 unsigned long val;
1221 uint32_t *ui32val;
1222
1223 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001224 if (target->nodetype == LYS_LEAFLIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001225 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001226 ui32val = &((struct lys_node_leaflist *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001227 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001228 ui32val = &((struct lys_node_leaflist *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001229 }
Radek Krejci76512572015-08-04 09:47:08 +02001230 } else if (target->nodetype == LYS_LIST) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001231 if (type) {
Radek Krejcib8048692015-08-05 13:36:34 +02001232 ui32val = &((struct lys_node_list *)target)->max;
Radek Krejcieb00f512015-07-01 16:44:58 +02001233 } else {
Radek Krejcib8048692015-08-05 13:36:34 +02001234 ui32val = &((struct lys_node_list *)target)->min;
Radek Krejcieb00f512015-07-01 16:44:58 +02001235 }
1236 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001237 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1238 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001239 goto error;
1240 }
1241
1242 GETVAL(value, node, "value");
1243 while (isspace(value[0])) {
1244 value++;
1245 }
1246
1247 /* convert it to uint32_t */
1248 errno = 0;
1249 endptr = NULL;
1250 val = strtoul(value, &endptr, 10);
1251 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001252 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001253 goto error;
1254 }
1255 if (type) {
1256 d->max = (uint32_t)val;
1257 } else {
1258 d->min = (uint32_t)val;
1259 }
1260
1261 if (d->mod == LY_DEVIATE_ADD) {
1262 /* check that there is no current value */
1263 if (*ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001264 LOGVAL(LYE_INSTMT, LOGLINE(node), node->name);
1265 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001266 goto error;
1267 }
1268 }
1269
1270 if (d->mod == LY_DEVIATE_DEL) {
1271 /* check values */
1272 if ((uint32_t)val != *ui32val) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001273 LOGVAL(LYE_INARG, LOGLINE(node), value, node->name);
1274 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001275 goto error;
1276 }
1277 /* remove current min-elements value of the target */
1278 *ui32val = 0;
1279 } else { /* add (already checked) and replace */
1280 /* set new value specified in deviation */
1281 *ui32val = (uint32_t)val;
1282 }
1283
1284 return EXIT_SUCCESS;
1285
1286error:
1287
1288 return EXIT_FAILURE;
1289}
1290
1291static int
Radek Krejcia52656e2015-08-05 13:41:50 +02001292fill_yin_deviation(struct lys_module *module, struct lyxml_elem *yin, struct lys_deviation *dev)
Radek Krejcieb00f512015-07-01 16:44:58 +02001293{
1294 const char *value, **stritem;
1295 struct lyxml_elem *next, *child, *develem;
1296 int c_dev = 0, c_must, c_uniq;
1297 int f_min = 0; /* flags */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001298 int i, j, rc;
Radek Krejcia52656e2015-08-05 13:41:50 +02001299 struct lys_deviate *d = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001300 struct lys_node *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02001301 struct lys_node_choice *choice = NULL;
1302 struct lys_node_leaf *leaf = NULL;
1303 struct lys_node_list *list = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001304 struct lys_type *t = NULL;
Radek Krejcie4c366b2015-07-02 10:11:31 +02001305 uint8_t *trg_must_size = NULL;
Radek Krejci1574a8d2015-08-03 14:16:52 +02001306 struct lys_restr **trg_must = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001307
1308 GETVAL(value, yin, "target-node");
1309 dev->target_name = lydict_insert(module->ctx, value, 0);
1310
1311 /* resolve target node */
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001312 rc = resolve_schema_nodeid(dev->target_name, NULL, module, LYS_AUGMENT, &dev->target);
1313 if (rc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001314 LOGVAL(LYE_INARG, LOGLINE(yin), dev->target_name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001315 goto error;
1316 }
1317 if (dev->target->module == module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001318 LOGVAL(LYE_SPEC, LOGLINE(yin), "Deviating own module is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001319 goto error;
1320 }
1321 /* mark the target module as deviated */
1322 dev->target->module->deviated = 1;
1323
1324 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001325 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1326 /* garbage */
1327 lyxml_free_elem(module->ctx, child);
1328 continue;
1329 }
1330
Radek Krejcieb00f512015-07-01 16:44:58 +02001331 if (!strcmp(child->name, "description")) {
1332 if (dev->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001333 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001334 goto error;
1335 }
1336 dev->dsc = read_yin_subnode(module->ctx, child, "text");
1337 if (!dev->dsc) {
1338 goto error;
1339 }
1340 } else if (!strcmp(child->name, "reference")) {
1341 if (dev->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001342 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001343 goto error;
1344 }
1345 dev->ref = read_yin_subnode(module->ctx, child, "text");
1346 if (!dev->ref) {
1347 goto error;
1348 }
1349 } else if (!strcmp(child->name, "deviate")) {
1350 c_dev++;
1351
1352 /* skip lyxml_free_elem() at the end of the loop, node will be
1353 * further processed later
1354 */
1355 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02001356
Radek Krejcieb00f512015-07-01 16:44:58 +02001357 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001358 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001359 goto error;
1360 }
1361
1362 lyxml_free_elem(module->ctx, child);
1363 }
1364
1365 if (c_dev) {
1366 dev->deviate = calloc(c_dev, sizeof *dev->deviate);
1367 }
1368
1369 LY_TREE_FOR(yin->child, develem) {
1370 /* init */
1371 f_min = 0;
1372 c_must = 0;
1373 c_uniq = 0;
1374
1375 /* get deviation type */
1376 GETVAL(value, develem, "value");
1377 if (!strcmp(value, "not-supported")) {
1378 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1379 /* no property expected in this case */
1380 if (develem->child) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001381 LOGVAL(LYE_INSTMT, LOGLINE(develem->child), develem->child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001382 goto error;
1383 }
1384
Radek Krejci5b917642015-07-02 09:03:13 +02001385 /* and neither any other deviate statement is expected,
1386 * not-supported deviation must be the only deviation of the target
1387 */
1388 if (dev->deviate_size || develem->next) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001389 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
1390 LOGVAL(LYE_SPEC, 0, "\"not-supported\" deviation cannot be combined with any other deviation.");
Radek Krejci5b917642015-07-02 09:03:13 +02001391 goto error;
1392 }
1393
1394
Radek Krejcieb00f512015-07-01 16:44:58 +02001395 /* remove target node */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001396 lys_node_free(dev->target);
Radek Krejci5b917642015-07-02 09:03:13 +02001397 dev->target = NULL;
Radek Krejcieb00f512015-07-01 16:44:58 +02001398
Radek Krejci5b917642015-07-02 09:03:13 +02001399 dev->deviate_size = 1;
1400 return EXIT_SUCCESS;
Radek Krejcieb00f512015-07-01 16:44:58 +02001401 } else if (!strcmp(value, "add")) {
1402 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_ADD;
1403 } else if (!strcmp(value, "replace")) {
1404 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_RPL;
1405 } else if (!strcmp(value, "delete")) {
1406 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_DEL;
1407 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001408 LOGVAL(LYE_INARG, LOGLINE(develem), value, develem->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001409 goto error;
1410 }
1411 d = &dev->deviate[dev->deviate_size];
1412
1413 /* process deviation properties */
1414 LY_TREE_FOR_SAFE(develem->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001415 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1416 /* garbage */
1417 lyxml_free_elem(module->ctx, child);
1418 continue;
1419 }
1420
Radek Krejcieb00f512015-07-01 16:44:58 +02001421 if (!strcmp(child->name, "config")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001422 if (d->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001423 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001424 goto error;
1425 }
1426
1427 /* for we deviate from RFC 6020 and allow config property even it is/is not
1428 * specified in the target explicitly since config property inherits. So we expect
1429 * that config is specified in every node. But for delete, we check that the value
1430 * is the same as here in deviation
1431 */
1432 GETVAL(value, child, "value");
1433 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001434 d->flags |= LYS_CONFIG_R;
Radek Krejcieb00f512015-07-01 16:44:58 +02001435 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001436 d->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001437 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001438 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001439 goto error;
1440 }
1441
1442 if (d->mod == LY_DEVIATE_DEL) {
1443 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001444 if ((d->flags & LYS_CONFIG_MASK) != (dev->target->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001445 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1446 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001447 goto error;
1448 }
1449 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001450 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001451
1452 /* ... and inherit config value from the target's parent */
1453 if (dev->target->parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001454 dev->target->flags |= dev->target->parent->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001455 } else {
1456 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001457 dev->target->flags |= LYS_CONFIG_W;
Radek Krejcieb00f512015-07-01 16:44:58 +02001458 }
1459 } else { /* add and replace are the same in this case */
1460 /* remove current config value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001461 dev->target->flags &= ~LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001462
1463 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001464 dev->target->flags |= d->flags & LYS_CONFIG_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001465 }
1466 } else if (!strcmp(child->name, "default")) {
1467 if (d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001468 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001469 goto error;
1470 }
1471 GETVAL(value, child, "value");
1472 d->dflt = lydict_insert(module->ctx, value, 0);
1473
Radek Krejci76512572015-08-04 09:47:08 +02001474 if (dev->target->nodetype == LYS_CHOICE) {
Radek Krejcib8048692015-08-05 13:36:34 +02001475 choice = (struct lys_node_choice *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001476
1477 if (d->mod == LY_DEVIATE_ADD) {
1478 /* check that there is no current value */
1479 if (choice->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001480 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1481 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001482 goto error;
1483 }
1484 }
1485
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001486 rc = resolve_schema_nodeid(d->dflt, choice->child, choice->module, LYS_CHOICE, &node);
1487 if (rc) {
1488 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1489 goto error;
1490 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001491 if (d->mod == LY_DEVIATE_DEL) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001492 if (!choice->dflt || choice->dflt != node) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001493 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1494 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001495 goto error;
1496 }
1497 } else { /* add (already checked) and replace */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001498 choice->dflt = node;
Radek Krejcieb00f512015-07-01 16:44:58 +02001499 if (!choice->dflt) {
1500 /* default branch not found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001501 LOGVAL(LYE_INARG, LOGLINE(yin), value, "default");
Radek Krejcieb00f512015-07-01 16:44:58 +02001502 goto error;
1503 }
1504 }
Radek Krejci76512572015-08-04 09:47:08 +02001505 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001506 leaf = (struct lys_node_leaf *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001507
1508 if (d->mod == LY_DEVIATE_ADD) {
1509 /* check that there is no current value */
1510 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001511 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1512 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001513 goto error;
1514 }
1515 }
1516
1517 if (d->mod == LY_DEVIATE_DEL) {
1518 if (!leaf->dflt || leaf->dflt != d->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001519 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1520 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001521 goto error;
1522 }
1523 /* remove value */
1524 lydict_remove(leaf->module->ctx, leaf->dflt);
1525 leaf->dflt = NULL;
1526 } else { /* add (already checked) and replace */
1527 /* remove value */
1528 lydict_remove(leaf->module->ctx, leaf->dflt);
1529
1530 /* set new value */
1531 leaf->dflt = lydict_insert(leaf->module->ctx, d->dflt, 0);
1532 }
1533 } else {
1534 /* invalid target for default value */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001535 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1536 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001537 goto error;
1538 }
1539 } else if (!strcmp(child->name, "mandatory")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001540 if (d->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001541 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001542 goto error;
1543 }
1544
1545 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001546 if (!(dev->target->nodetype &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001547 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1548 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001549 goto error;
1550 }
1551
1552 GETVAL(value, child, "value");
1553 if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001554 d->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001555 } else if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02001556 d->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02001557 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001558 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001559 goto error;
1560 }
1561
1562 if (d->mod == LY_DEVIATE_ADD) {
1563 /* check that there is no current value */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001564 if (dev->target->flags & LYS_MAND_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001565 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1566 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001567 goto error;
1568 }
1569 }
1570
1571 if (d->mod == LY_DEVIATE_DEL) {
1572 /* check values */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001573 if ((d->flags & LYS_MAND_MASK) != (dev->target->flags & LYS_MAND_MASK)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001574 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1575 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001576 goto error;
1577 }
1578 /* remove current mandatory value of the target */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001579 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001580 } else { /* add (already checked) and replace */
1581 /* remove current mandatory value of the target ... */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001582 dev->target->flags &= ~LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001583
1584 /* ... and replace it with the value specified in deviation */
Radek Krejci1574a8d2015-08-03 14:16:52 +02001585 dev->target->flags |= d->flags & LYS_MAND_MASK;
Radek Krejcieb00f512015-07-01 16:44:58 +02001586 }
1587 } else if (!strcmp(child->name, "min-elements")) {
1588 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001589 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001590 goto error;
1591 }
1592 f_min = 1;
1593
1594 if (deviate_minmax(dev->target, child, d, 0)) {
1595 goto error;
1596 }
1597 } else if (!strcmp(child->name, "max-elements")) {
1598 if (d->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001599 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001600 goto error;
1601 }
1602
1603 if (deviate_minmax(dev->target, child, d, 1)) {
1604 goto error;
1605 }
1606 } else if (!strcmp(child->name, "must")) {
1607 c_must++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001608 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1609 continue;
1610 } else if (!strcmp(child->name, "type")) {
1611 if (d->type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001612 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001613 goto error;
1614 }
1615
1616 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001617 if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001618 t = &((struct lys_node_leaf *)dev->target)->type;
Radek Krejci76512572015-08-04 09:47:08 +02001619 } else if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001620 t = &((struct lys_node_leaflist *)dev->target)->type;
Radek Krejcieb00f512015-07-01 16:44:58 +02001621 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001622 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1623 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001624 goto error;
1625 }
1626
1627 if (d->mod == LY_DEVIATE_ADD) {
1628 /* not allowed, type is always present at the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001629 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1630 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001631 goto error;
1632 } else if (d->mod == LY_DEVIATE_DEL) {
1633 /* not allowed, type cannot be deleted from the target */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001634 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1635 LOGVAL(LYE_SPEC, 0, "Deleteing type from the target is not allowed.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001636 goto error;
1637 }
1638
1639 /* replace */
1640 /* remove current units value of the target ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001641 lys_type_free(dev->target->module->ctx, t);
Radek Krejcieb00f512015-07-01 16:44:58 +02001642
1643 /* ... and replace it with the value specified in deviation */
Radek Krejci8de7b0f2015-07-02 11:43:42 +02001644 if (fill_yin_type(module, dev->target, child, t, NULL)) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001645 goto error;
1646 }
1647 d->type = t;
1648 } else if (!strcmp(child->name, "unique")) {
1649 c_uniq++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001650 /* skip lyxml_free_elem() at the end of the loop, this node will be processed later */
1651 continue;
1652 } else if (!strcmp(child->name, "units")) {
1653 if (d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001654 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001655 goto error;
1656 }
1657
1658 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001659 if (dev->target->nodetype == LYS_LEAFLIST) {
Radek Krejcib8048692015-08-05 13:36:34 +02001660 stritem = &((struct lys_node_leaflist *)dev->target)->units;
Radek Krejci76512572015-08-04 09:47:08 +02001661 } else if (dev->target->nodetype == LYS_LEAF) {
Radek Krejcib8048692015-08-05 13:36:34 +02001662 stritem = &((struct lys_node_leaf *)dev->target)->units;
Radek Krejcieb00f512015-07-01 16:44:58 +02001663 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001664 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1665 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001666 goto error;
1667 }
1668
1669 /* get units value */
1670 GETVAL(value, child, "name");
1671 d->units = lydict_insert(module->ctx, value, 0);
1672
1673 /* apply to target */
1674 if (d->mod == LY_DEVIATE_ADD) {
1675 /* check that there is no current value */
1676 if (*stritem) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001677 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1678 LOGVAL(LYE_SPEC, 0, "Adding property that already exists.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001679 goto error;
1680 }
1681 }
1682
1683 if (d->mod == LY_DEVIATE_DEL) {
1684 /* check values */
1685 if (*stritem != d->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001686 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
1687 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001688 goto error;
1689 }
1690 /* remove current units value of the target */
1691 lydict_remove(dev->target->module->ctx, *stritem);
1692 } else { /* add (already checked) and replace */
1693 /* remove current units value of the target ... */
1694 lydict_remove(dev->target->module->ctx, *stritem);
1695
1696 /* ... and replace it with the value specified in deviation */
1697 *stritem = lydict_insert(module->ctx, value, 0);
1698 }
1699 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001700 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001701 goto error;
1702 }
1703
1704 lyxml_free_elem(module->ctx, child);
1705 }
1706
1707 if (c_must) {
1708 /* check target node type */
1709 switch (dev->target->nodetype) {
Radek Krejci76512572015-08-04 09:47:08 +02001710 case LYS_LEAF:
Radek Krejcib8048692015-08-05 13:36:34 +02001711 trg_must = &((struct lys_node_leaf *)dev->target)->must;
1712 trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001713 break;
Radek Krejci76512572015-08-04 09:47:08 +02001714 case LYS_CONTAINER:
Radek Krejcib8048692015-08-05 13:36:34 +02001715 trg_must = &((struct lys_node_container *)dev->target)->must;
1716 trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001717 break;
Radek Krejci76512572015-08-04 09:47:08 +02001718 case LYS_LEAFLIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001719 trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1720 trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001721 break;
Radek Krejci76512572015-08-04 09:47:08 +02001722 case LYS_LIST:
Radek Krejcib8048692015-08-05 13:36:34 +02001723 trg_must = &((struct lys_node_list *)dev->target)->must;
1724 trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001725 break;
Radek Krejci76512572015-08-04 09:47:08 +02001726 case LYS_ANYXML:
Radek Krejcib8048692015-08-05 13:36:34 +02001727 trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1728 trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
Radek Krejcieb00f512015-07-01 16:44:58 +02001729 break;
1730 default:
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001731 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1732 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001733 goto error;
1734 }
1735
1736 if (d->mod == LY_DEVIATE_RPL) {
1737 /* remove target's musts and allocate new array for it */
1738 if (!*trg_must) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001739 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1740 LOGVAL(LYE_SPEC, 0, "Property \"must\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001741 goto error;
1742 }
1743
1744 for (i = 0; i < list->must_size; i++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001745 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001746 }
1747 free(*trg_must);
1748 *trg_must = d->must = calloc(c_must, sizeof *d->must);
1749 d->must_size = c_must;
1750 *trg_must_size = 0;
1751 } else if (d->mod == LY_DEVIATE_ADD) {
1752 /* reallocate the must array of the target */
1753 d->must = realloc(*trg_must, (c_must + *trg_must_size) * sizeof *d->must);
1754 *trg_must = d->must;
1755 d->must = &(*trg_must[*trg_must_size]);
1756 d->must_size = c_must;
1757 } else { /* LY_DEVIATE_DEL */
1758 d->must = calloc(c_must, sizeof *d->must);
1759 }
1760 }
1761 if (c_uniq) {
1762 /* check target node type */
Radek Krejci76512572015-08-04 09:47:08 +02001763 if (dev->target->nodetype != LYS_LIST) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001764 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
1765 LOGVAL(LYE_SPEC, 0, "Target node does not allow \"%s\" property.", child->name);
Radek Krejcieb00f512015-07-01 16:44:58 +02001766 goto error;
1767 }
1768
Radek Krejcib8048692015-08-05 13:36:34 +02001769 list = (struct lys_node_list *)dev->target;
Radek Krejcieb00f512015-07-01 16:44:58 +02001770 if (d->mod == LY_DEVIATE_RPL) {
1771 /* remove target's unique and allocate new array for it */
1772 if (!list->unique) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001773 LOGVAL(LYE_INARG, LOGLINE(develem), "replace", "deviate");
1774 LOGVAL(LYE_SPEC, 0, "Property \"unique\" to replace does not exists in target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001775 goto error;
1776 }
1777
1778 for (i = 0; i < list->unique_size; i++) {
1779 free(list->unique[i].leafs);
1780 }
1781 free(list->unique);
1782 list->unique = d->unique = calloc(c_uniq, sizeof *d->unique);
1783 d->unique_size = c_uniq;
1784 list->unique_size = 0;
1785 } else if (d->mod == LY_DEVIATE_ADD) {
1786 /* reallocate the unique array of the target */
1787 d->unique = realloc(list->unique, (c_uniq + list->unique_size) * sizeof *d->unique);
1788 list->unique = d->unique;
1789 d->unique = &list->unique[list->unique_size];
1790 d->unique_size = c_uniq;
1791 } else { /* LY_DEVIATE_DEL */
1792 d->unique = calloc(c_uniq, sizeof *d->unique);
1793 }
1794 }
1795
1796 /* process deviation properties with 0..n cardinality */
Radek Krejci73adb602015-07-02 18:07:40 +02001797 LY_TREE_FOR(develem->child, child) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001798 if (!strcmp(child->name, "must")) {
1799 if (d->mod == LY_DEVIATE_DEL) {
1800 if (fill_yin_must(module, child, &d->must[d->must_size])) {
1801 goto error;
1802 }
1803
1804 /* find must to delete, we are ok with just matching conditions */
1805 for (i = 0; i < *trg_must_size; i++) {
1806 if (d->must[d->must_size].expr == (*trg_must)[i].expr) {
1807 /* we have a match, free the must structure ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02001808 lys_restr_free(dev->target->module->ctx, &(*trg_must[i]));
Radek Krejcieb00f512015-07-01 16:44:58 +02001809 /* ... and maintain the array */
1810 (*trg_must_size)--;
1811 if (i != *trg_must_size) {
1812 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1813 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1814 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1815 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1816 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1817 }
1818 if (!(*trg_must_size)) {
1819 free(*trg_must);
1820 *trg_must = NULL;
1821 } else {
1822 (*trg_must)[*trg_must_size].expr = NULL;
1823 (*trg_must)[*trg_must_size].dsc = NULL;
1824 (*trg_must)[*trg_must_size].ref = NULL;
1825 (*trg_must)[*trg_must_size].eapptag = NULL;
1826 (*trg_must)[*trg_must_size].emsg = NULL;
1827 }
1828
1829 i = -1; /* set match flag */
1830 break;
1831 }
1832 }
1833 d->must_size++;
1834 if (i != -1) {
1835 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001836 LOGVAL(LYE_INARG, LOGLINE(child), d->must[d->must_size - 1].expr, child->name);
1837 LOGVAL(LYE_SPEC, 0, "Value does not match any must from the target.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001838 goto error;
1839 }
1840 } else { /* replace or add */
1841 if (fill_yin_must(dev->target->module, child, &((*trg_must)[*trg_must_size]))) {
1842 goto error;
1843 }
1844 (*trg_must_size)++;
1845 }
1846 } else if (!strcmp(child->name, "unique")) {
1847 if (d->mod == LY_DEVIATE_DEL) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001848 GETVAL(value, child, "tag");
1849 if (resolve_unique(dev->target, value, &d->unique[d->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001850 goto error;
1851 }
1852
1853 /* find unique structures to delete */
1854 for (i = 0; i < list->unique_size; i++) {
1855 if (list->unique[i].leafs_size != d->unique[d->unique_size].leafs_size) {
1856 continue;
1857 }
1858
1859 for (j = 0; j < d->unique[d->unique_size].leafs_size; j++) {
1860 if (list->unique[i].leafs[j] != d->unique[d->unique_size].leafs[j]) {
1861 break;
1862 }
1863 }
1864
1865 if (j == d->unique[d->unique_size].leafs_size) {
1866 /* we have a match, free the unique structure ... */
1867 free(list->unique[i].leafs);
1868 /* ... and maintain the array */
1869 list->unique_size--;
1870 if (i != list->unique_size) {
1871 list->unique[i].leafs_size = list->unique[list->unique_size].leafs_size;
1872 list->unique[i].leafs = list->unique[list->unique_size].leafs;
1873 }
1874
1875 if (!list->unique_size) {
1876 free(list->unique);
1877 list->unique = NULL;
1878 } else {
1879 list->unique[list->unique_size].leafs_size = 0;
1880 list->unique[list->unique_size].leafs = NULL;
1881 }
1882
1883 i = -1; /* set match flag */
1884 break;
1885 }
1886 }
1887
1888 d->unique_size++;
1889 if (i != -1) {
1890 /* no match found */
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001891 LOGVAL(LYE_INARG, LOGLINE(child), lyxml_get_attr(child, "tag", NULL), child->name);
1892 LOGVAL(LYE_SPEC, 0, "Value differs from the target being deleted.");
Radek Krejcieb00f512015-07-01 16:44:58 +02001893 goto error;
1894 }
1895 } else { /* replace or add */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001896 GETVAL(value, child, "tag");
1897 if (resolve_unique(dev->target, value, &list->unique[list->unique_size], LOGLINE(child))) {
Radek Krejcieb00f512015-07-01 16:44:58 +02001898 goto error;
1899 }
1900 list->unique_size++;
1901 }
1902 }
Radek Krejcieb00f512015-07-01 16:44:58 +02001903 }
Radek Krejci5b917642015-07-02 09:03:13 +02001904
1905 dev->deviate_size++;
Radek Krejcieb00f512015-07-01 16:44:58 +02001906 }
1907
Radek Krejcieb00f512015-07-01 16:44:58 +02001908 return EXIT_SUCCESS;
1909
1910error:
1911
1912 if (dev->deviate) {
1913 for (i = 0; i < dev->deviate_size; i++) {
1914 lydict_remove(module->ctx, dev->deviate[i].dflt);
1915 lydict_remove(module->ctx, dev->deviate[i].units);
1916
1917 if (dev->deviate[i].mod == LY_DEVIATE_DEL) {
1918 for (j = 0; j < dev->deviate[i].must_size; j++) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001919 lys_restr_free(module->ctx, &dev->deviate[i].must[j]);
Radek Krejcieb00f512015-07-01 16:44:58 +02001920 }
1921 free(dev->deviate[i].must);
1922
1923 for (j = 0; j < dev->deviate[i].unique_size; j++) {
1924 free(dev->deviate[i].unique[j].leafs);
1925 }
1926 free(dev->deviate[i].unique);
1927 }
1928 }
1929 free(dev->deviate);
1930 }
1931
1932 return EXIT_FAILURE;
1933}
1934
1935static int
Radek Krejcib8048692015-08-05 13:36:34 +02001936fill_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 +02001937 struct unres_schema *unres)
Radek Krejci106efc02015-06-10 14:36:27 +02001938{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001939 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001940 struct lyxml_elem *child, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02001941 struct lys_node *node;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001942 int c = 0;
Radek Krejci106efc02015-06-10 14:36:27 +02001943
Michal Vasko591e0b22015-08-13 13:53:43 +02001944 aug->nodetype = LYS_AUGMENT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02001945 GETVAL(value, yin, "target-node");
1946 aug->target_name = lydict_insert(module->ctx, value, 0);
1947 aug->parent = parent;
Radek Krejci106efc02015-06-10 14:36:27 +02001948
Radek Krejci76512572015-08-04 09:47:08 +02001949 if (read_yin_common(module, NULL, (struct lys_node *)aug, yin, OPT_NACMEXT)) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02001950 goto error;
1951 }
1952
1953 LY_TREE_FOR_SAFE(yin->child, next, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02001954 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
1955 /* garbage */
1956 lyxml_free_elem(module->ctx, child);
1957 continue;
1958 }
1959
Radek Krejci3cf9e222015-06-18 11:37:50 +02001960 if (!strcmp(child->name, "if-feature")) {
1961 c++;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001962 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001963 } else if (!strcmp(child->name, "when")) {
1964 if (aug->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001965 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001966 goto error;
1967 }
1968
1969 aug->when = read_yin_when(module, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001970 if (!aug->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001971 lyxml_free_elem(module->ctx, child);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02001972 goto error;
1973 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02001974 if (unres_add_node(module, unres, aug->when, UNRES_WHEN, (struct lys_node *)aug, LOGLINE(child)) == -1) {
1975 goto error;
1976 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001977 lyxml_free_elem(module->ctx, child);
1978 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02001979
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001980 /* check allowed data sub-statements */
1981 } else if (!strcmp(child->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001982 node = read_yin_container(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001983 } else if (!strcmp(child->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001984 node = read_yin_leaflist(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001985 } else if (!strcmp(child->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001986 node = read_yin_leaf(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001987 } else if (!strcmp(child->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001988 node = read_yin_list(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001989 } else if (!strcmp(child->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001990 node = read_yin_uses(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001991 } else if (!strcmp(child->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001992 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001993 } else if (!strcmp(child->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001994 node = read_yin_case(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001995 } else if (!strcmp(child->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02001996 node = read_yin_anyxml(module, (struct lys_node *)aug, child, 0, unres);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02001997 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02001998 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02001999 goto error;
2000 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002001
Radek Krejci1d82ef62015-08-07 14:44:40 +02002002 if (!node) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002003 goto error;
2004 }
2005
2006 /* check for mandatory nodes - if the target node is in another module
2007 * the added nodes cannot be mandatory
2008 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002009 if ((!parent || (parent->nodetype != LYS_USES)) && check_mandatory(node)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002010 LOGVAL(LYE_SPEC, LOGLINE(child), "When augmenting data in another module, mandatory statement is not allowed.");
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002011 goto error;
2012 }
2013
Radek Krejci1d82ef62015-08-07 14:44:40 +02002014 node = NULL;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002015 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002016 }
2017
2018 if (c) {
2019 aug->features = calloc(c, sizeof *aug->features);
2020 }
2021
2022 LY_TREE_FOR_SAFE(yin->child, next, child) {
2023 if (!strcmp(child->name, "if-feature")) {
2024 GETVAL(value, child, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002025 if (unres_add_str(module, unres, &aug->features[aug->features_size++], UNRES_IFFEAT, value, LOGLINE(child)) == -1) {
2026 goto error;
2027 }
Radek Krejci73adb602015-07-02 18:07:40 +02002028 lyxml_free_elem(module->ctx, child);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002029 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002030 }
2031
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002032 /* aug->child points to the parsed nodes, they must now be
Michal Vasko49291b32015-08-06 09:49:41 +02002033 * connected to the tree and adjusted (if possible right now).
2034 * However, if this is augment in a uses, it gets resolved
2035 * when the uses does and cannot be resolved now for sure
2036 * (the grouping was not yet copied into uses).
2037 */
2038 if (!parent || (parent->nodetype != LYS_USES)) {
Michal Vasko4adc10f2015-08-11 15:26:17 +02002039 if (resolve_augment(aug, aug->child, module)) {
2040 LOGVAL(LYE_INRESOLV, LOGLINE(yin), "augment", aug->target_name);
2041 goto error;
2042 }
Michal Vasko49291b32015-08-06 09:49:41 +02002043 }
Radek Krejci106efc02015-06-10 14:36:27 +02002044
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002045 return EXIT_SUCCESS;
Radek Krejci106efc02015-06-10 14:36:27 +02002046
2047error:
2048
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002049 return EXIT_FAILURE;
Radek Krejci106efc02015-06-10 14:36:27 +02002050}
2051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002052static int
Radek Krejcib8048692015-08-05 13:36:34 +02002053fill_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 +02002054 struct unres_schema *unres)
Radek Krejci3bde87f2015-06-05 16:51:58 +02002055{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002056 struct lyxml_elem *sub, *next;
2057 const char *value;
2058 char *endptr;
2059 int f_mand = 0, f_min = 0, f_max = 0;
2060 int c_must = 0;
2061 int r;
2062 unsigned long int val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002063
Radek Krejci76512572015-08-04 09:47:08 +02002064 if (read_yin_common(module, NULL, (struct lys_node *)rfn, yin, OPT_CONFIG)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002065 goto error;
2066 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002067
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002068 GETVAL(value, yin, "target-node");
Radek Krejci76512572015-08-04 09:47:08 +02002069 rfn->target_name = lydict_insert(module->ctx, value, 0);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002070
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002071 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002072 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2073 /* garbage */
2074 lyxml_free_elem(module->ctx, sub);
2075 continue;
2076 }
2077
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002078 /* limited applicability */
2079 if (!strcmp(sub->name, "default")) {
2080 /* leaf or choice */
2081 if (rfn->mod.dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002082 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002083 goto error;
2084 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002085
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002086 /* check possibility of statements combination */
2087 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002088 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002089 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002090 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002091 goto error;
2092 }
2093 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002094 rfn->target_type = LYS_LEAF | LYS_CHOICE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002095 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002096
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002097 GETVAL(value, sub, "value");
2098 rfn->mod.dflt = lydict_insert(module->ctx, value, strlen(value));
2099 } else if (!strcmp(sub->name, "mandatory")) {
2100 /* leaf, choice or anyxml */
2101 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002102 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002103 goto error;
2104 }
2105 /* just checking the flags in leaf is not sufficient, we would allow
2106 * multiple mandatory statements with the "false" value
2107 */
2108 f_mand = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002109
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002110 /* check possibility of statements combination */
2111 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002112 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002113 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002114 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002115 goto error;
2116 }
2117 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002118 rfn->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002119 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002120
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002121 GETVAL(value, sub, "value");
2122 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002123 rfn->flags |= LYS_MAND_TRUE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002124 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002125 rfn->flags |= LYS_MAND_FALSE;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002126 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002127 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002128 goto error;
2129 }
2130 } else if (!strcmp(sub->name, "min-elements")) {
2131 /* list or leaf-list */
2132 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002133 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002134 goto error;
2135 }
2136 f_min = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002137
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002138 /* check possibility of statements combination */
2139 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002140 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002141 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002142 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002143 goto error;
2144 }
2145 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002146 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002147 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002148
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002149 GETVAL(value, sub, "value");
2150 while (isspace(value[0])) {
2151 value++;
2152 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002153
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002154 /* convert it to uint32_t */
2155 errno = 0;
2156 endptr = NULL;
2157 val = strtoul(value, &endptr, 10);
2158 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002159 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002160 goto error;
2161 }
2162 rfn->mod.list.min = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002163
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002164 /* magic - bit 3 in flags means min set */
2165 rfn->flags |= 0x04;
2166 } else if (!strcmp(sub->name, "max-elements")) {
2167 /* list or leaf-list */
2168 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002169 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002170 goto error;
2171 }
2172 f_max = 1;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002173
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002174 /* check possibility of statements combination */
2175 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002176 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002177 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002178 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002179 goto error;
2180 }
2181 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002182 rfn->target_type = LYS_LIST | LYS_LEAFLIST;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002183 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002184
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002185 GETVAL(value, sub, "value");
2186 while (isspace(value[0])) {
2187 value++;
2188 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002189
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002190 /* convert it to uint32_t */
2191 errno = 0;
2192 endptr = NULL;
2193 val = strtoul(value, &endptr, 10);
2194 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002195 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002196 goto error;
2197 }
2198 rfn->mod.list.max = (uint32_t) val;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002199
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002200 /* magic - bit 4 in flags means min set */
2201 rfn->flags |= 0x08;
2202 } else if (!strcmp(sub->name, "presence")) {
2203 /* container */
2204 if (rfn->mod.presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002205 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002206 goto error;
2207 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002208
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002209 /* check possibility of statements combination */
2210 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002211 rfn->target_type &= LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002212 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002213 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002214 goto error;
2215 }
2216 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002217 rfn->target_type = LYS_CONTAINER;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002218 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002219
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002220 GETVAL(value, sub, "value");
2221 rfn->mod.presence = lydict_insert(module->ctx, value, strlen(value));
2222 } else if (!strcmp(sub->name, "must")) {
2223 /* leaf-list, list, container or anyxml */
2224 /* check possibility of statements combination */
2225 if (rfn->target_type) {
Radek Krejci76512572015-08-04 09:47:08 +02002226 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002227 if (!rfn->target_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002228 LOGVAL(LYE_SPEC, LOGLINE(sub), "invalid combination of refine substatements");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002229 goto error;
2230 }
2231 } else {
Radek Krejci76512572015-08-04 09:47:08 +02002232 rfn->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002233 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002234
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002235 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02002236 continue;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002237
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002238 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002239 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002240 goto error;
2241 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002242
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002243 lyxml_free_elem(module->ctx, sub);
2244 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002245
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002246 /* process nodes with cardinality of 0..n */
2247 if (c_must) {
2248 rfn->must = calloc(c_must, sizeof *rfn->must);
2249 }
Radek Krejci73adb602015-07-02 18:07:40 +02002250 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002251 r = fill_yin_must(module, sub, &rfn->must[rfn->must_size++]);
Radek Krejci73adb602015-07-02 18:07:40 +02002252 if (r) {
2253 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002254 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002255 if (unres_add_node(module, unres, &rfn->must[rfn->must_size-1], UNRES_MUST, (struct lys_node *)uses,
2256 LOGLINE(sub)) == -1) {
2257 goto error;
2258 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002259 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02002260
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002261 return EXIT_SUCCESS;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002262
2263error:
2264
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002265 return EXIT_FAILURE;
Radek Krejci3bde87f2015-06-05 16:51:58 +02002266}
2267
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002268static int
Radek Krejcib8048692015-08-05 13:36:34 +02002269fill_yin_import(struct lys_module *module, struct lyxml_elem *yin, struct lys_import *imp)
Radek Krejciefaeba32015-05-27 14:30:57 +02002270{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002271 struct lyxml_elem *child;
2272 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002273
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002274 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002275 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2276 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002277 continue;
2278 }
2279
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002280 if (!strcmp(child->name, "prefix")) {
2281 GETVAL(value, child, "value");
2282 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
2283 goto error;
2284 }
2285 imp->prefix = lydict_insert(module->ctx, value, strlen(value));
2286 } else if (!strcmp(child->name, "revision-date")) {
2287 if (imp->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002288 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002289 goto error;
2290 }
2291 GETVAL(value, child, "date");
2292 if (check_date(value, LOGLINE(child))) {
2293 goto error;
2294 }
2295 memcpy(imp->rev, value, LY_REV_SIZE - 1);
2296 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002297 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002298 goto error;
2299 }
2300 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002301
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002302 /* check mandatory information */
2303 if (!imp->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002304 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002305 goto error;
2306 }
Radek Krejcice7fb782015-05-29 16:52:34 +02002307
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002308 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002309 imp->module = ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002310 if (!imp->module) {
Radek Krejci63a91a92015-07-29 13:31:04 +02002311 imp->module = lyp_search_file(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL);
2312 if (!imp->module) {
2313 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2314 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002315 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002316 goto error;
2317 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002318 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002319
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002320 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002321
2322error:
2323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002324 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002325}
2326
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002327static int
Radek Krejcib8048692015-08-05 13:36:34 +02002328fill_yin_include(struct lys_module *module, struct lyxml_elem *yin, struct lys_include *inc)
Radek Krejciefaeba32015-05-27 14:30:57 +02002329{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002330 struct lyxml_elem *child;
2331 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02002332
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002333 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002334 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2335 /* garbage */
2336 continue;
2337 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002338 if (!strcmp(child->name, "revision-date")) {
2339 if (inc->rev[0]) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002340 LOGVAL(LYE_TOOMANY, LOGLINE(child), "revision-date", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002341 goto error;
2342 }
2343 GETVAL(value, child, "date");
2344 if (check_date(value, LOGLINE(child))) {
2345 goto error;
2346 }
2347 memcpy(inc->rev, value, LY_REV_SIZE - 1);
2348 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002349 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002350 goto error;
2351 }
2352 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002353
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002354 GETVAL(value, yin, "module");
Radek Krejci63a91a92015-07-29 13:31:04 +02002355 inc->submodule = ly_ctx_get_submodule(module, value, inc->rev[0] ? inc->rev : NULL);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002356 if (!inc->submodule) {
Radek Krejcib8048692015-08-05 13:36:34 +02002357 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 +02002358 if (!inc->submodule) {
2359 LOGERR(LY_EVALID, "Data model \"%s\" not found (search path is \"%s\")", value, module->ctx->models.search_path);
2360 LOGERR(LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002361 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
Radek Krejci63a91a92015-07-29 13:31:04 +02002362 goto error;
2363 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002364 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002365
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002366 /* check that belongs-to corresponds */
2367 if (module->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02002368 module = ((struct lys_submodule *)module)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002369 }
2370 if (inc->submodule->belongsto != module) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002371 LOGVAL(LYE_INARG, LOGLINE(yin), value, yin->name);
2372 LOGVAL(LYE_SPEC, 0, "The included module does not belongs-to the \"%s\" module", module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002373 goto error;
2374 }
Radek Krejciefaeba32015-05-27 14:30:57 +02002375
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002376 return EXIT_SUCCESS;
Radek Krejcice7fb782015-05-29 16:52:34 +02002377
2378error:
2379
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002380 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02002381}
2382
Radek Krejcida04f4a2015-05-21 12:54:09 +02002383/*
2384 * Covers:
Radek Krejci25d782a2015-05-22 15:03:23 +02002385 * description, reference, status, optionaly config
Radek Krejcib388c152015-06-04 17:03:03 +02002386 *
Radek Krejcida04f4a2015-05-21 12:54:09 +02002387 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002388static int
Radek Krejcib8048692015-08-05 13:36:34 +02002389read_yin_common(struct lys_module *module, struct lys_node *parent,
Radek Krejci1d82ef62015-08-07 14:44:40 +02002390 struct lys_node *node, struct lyxml_elem *xmlnode, int opt)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002391{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002392 const char *value;
2393 struct lyxml_elem *sub, *next;
2394 struct ly_ctx *const ctx = module->ctx;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002395
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002396 if (opt & OPT_MODULE) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002397 node->module = module;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002398 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002400 if (opt & OPT_IDENT) {
2401 GETVAL(value, xmlnode, "name");
2402 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(xmlnode), NULL, NULL)) {
2403 goto error;
2404 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002405 node->name = lydict_insert(ctx, value, strlen(value));
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002406 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002407
Radek Krejci6764bb32015-07-03 15:16:04 +02002408 /* inherit NACM flags */
Radek Krejci6a113852015-07-03 16:04:20 +02002409 if ((opt & OPT_NACMEXT) && parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002410 node->nacm = parent->nacm;
Radek Krejci6764bb32015-07-03 15:16:04 +02002411 }
2412
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002413 /* process local parameters */
2414 LY_TREE_FOR_SAFE(xmlnode->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002415 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002416 /* garbage */
Radek Krejci6764bb32015-07-03 15:16:04 +02002417 lyxml_free_elem(ctx, sub);
2418 continue;
2419 }
2420 if (strcmp(sub->ns->value, LY_NSYIN)) {
2421 /* NACM extensions */
Radek Krejci6a113852015-07-03 16:04:20 +02002422 if ((opt & OPT_NACMEXT) && !strcmp(sub->ns->value, LY_NSNACM)) {
Radek Krejci6764bb32015-07-03 15:16:04 +02002423 if (!strcmp(sub->name, "default-deny-write")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002424 node->nacm |= LYS_NACM_DENYW;
Radek Krejci6764bb32015-07-03 15:16:04 +02002425 } else if (!strcmp(sub->name, "default-deny-all")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002426 node->nacm |= LYS_NACM_DENYA;
Radek Krejci6764bb32015-07-03 15:16:04 +02002427 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002428 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6764bb32015-07-03 15:16:04 +02002429 goto error;
2430 }
2431 }
2432
2433 /* else garbage */
2434 lyxml_free_elem(ctx, sub);
Radek Krejci0d70c372015-07-02 16:23:10 +02002435 continue;
2436 }
2437
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002438 if (!strcmp(sub->name, "description")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002439 if (node->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002440 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002441 goto error;
2442 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002443 node->dsc = read_yin_subnode(ctx, sub, "text");
2444 if (!node->dsc) {
Radek Krejci73adb602015-07-02 18:07:40 +02002445 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002446 }
2447 } else if (!strcmp(sub->name, "reference")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002448 if (node->ref) {
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 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02002452 node->ref = read_yin_subnode(ctx, sub, "text");
2453 if (!node->ref) {
Radek Krejci73adb602015-07-02 18:07:40 +02002454 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002455 }
2456 } else if (!strcmp(sub->name, "status")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002457 if (node->flags & LYS_STATUS_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002458 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002459 goto error;
2460 }
2461 GETVAL(value, sub, "value");
2462 if (!strcmp(value, "current")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002463 node->flags |= LYS_STATUS_CURR;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002464 } else if (!strcmp(value, "deprecated")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002465 node->flags |= LYS_STATUS_DEPRC;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002466 } else if (!strcmp(value, "obsolete")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002467 node->flags |= LYS_STATUS_OBSLT;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002468 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002469 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002470 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002471 }
2472 } else if ((opt & OPT_CONFIG) && !strcmp(sub->name, "config")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002473 if (node->flags & LYS_CONFIG_MASK) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002474 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, xmlnode->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002475 goto error;
2476 }
2477 GETVAL(value, sub, "value");
2478 if (!strcmp(value, "false")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002479 node->flags |= LYS_CONFIG_R;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002480 } else if (!strcmp(value, "true")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002481 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002482 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002483 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci73adb602015-07-02 18:07:40 +02002484 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002485 }
2486 } else {
2487 /* skip the lyxml_free_elem */
2488 continue;
2489 }
2490 lyxml_free_elem(ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002491 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002492
Radek Krejci1d82ef62015-08-07 14:44:40 +02002493 if ((opt & OPT_INHERIT) && !(node->flags & LYS_CONFIG_MASK)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002494 /* get config flag from parent */
2495 if (parent) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002496 node->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002497 } else {
2498 /* default config is true */
Radek Krejci1d82ef62015-08-07 14:44:40 +02002499 node->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002500 }
2501 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002502
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002503 return EXIT_SUCCESS;
Radek Krejcieac35532015-05-31 19:09:15 +02002504
2505error:
2506
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002507 return EXIT_FAILURE;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002508}
2509
Radek Krejci76512572015-08-04 09:47:08 +02002510static struct lys_when *
Radek Krejcib8048692015-08-05 13:36:34 +02002511read_yin_when(struct lys_module *module, struct lyxml_elem *yin)
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002512{
Radek Krejci76512572015-08-04 09:47:08 +02002513 struct lys_when *retval = NULL;
Radek Krejci73adb602015-07-02 18:07:40 +02002514 struct lyxml_elem *child;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002515 const char *value;
2516
2517 retval = calloc(1, sizeof *retval);
2518
2519 GETVAL(value, yin, "condition");
2520 retval->cond = lydict_insert(module->ctx, value, 0);
2521
Radek Krejci73adb602015-07-02 18:07:40 +02002522 LY_TREE_FOR(yin->child, child) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002523 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
2524 /* garbage */
Radek Krejci0d70c372015-07-02 16:23:10 +02002525 continue;
2526 }
2527
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002528 if (!strcmp(child->name, "description")) {
2529 if (retval->dsc) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002530 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002531 goto error;
2532 }
2533 retval->dsc = read_yin_subnode(module->ctx, child, "text");
2534 if (!retval->dsc) {
2535 goto error;
2536 }
2537 } else if (!strcmp(child->name, "reference")) {
2538 if (retval->ref) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002539 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002540 goto error;
2541 }
2542 retval->ref = read_yin_subnode(module->ctx, child, "text");
2543 if (!retval->ref) {
2544 goto error;
2545 }
2546 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002547 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002548 goto error;
2549 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002550 }
2551
2552 return retval;
2553
2554error:
2555
Radek Krejci1d82ef62015-08-07 14:44:40 +02002556 lys_node_free((struct lys_node *)retval);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002557 return NULL;
2558}
2559
Radek Krejci76512572015-08-04 09:47:08 +02002560static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02002561read_yin_case(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
2562 struct unres_schema *unres)
Radek Krejcib4cf2022015-06-03 14:40:05 +02002563{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002564 struct lyxml_elem *sub, *next;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002565 struct lys_node_case *cs;
2566 struct lys_node *retval, *node = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002567 int c_ftrs = 0;
2568 const char *value;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002569
Radek Krejci1d82ef62015-08-07 14:44:40 +02002570 cs = calloc(1, sizeof *cs);
2571 cs->nodetype = LYS_CASE;
2572 cs->prev = (struct lys_node *)cs;
2573 retval = (struct lys_node *)cs;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002574
Radek Krejci6a113852015-07-03 16:04:20 +02002575 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_INHERIT | OPT_NACMEXT)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002576 goto error;
2577 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002578
Radek Krejcia9544502015-08-14 08:24:29 +02002579 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2580
Michal Vasko3a0043f2015-08-12 12:11:30 +02002581 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002582 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002583 goto error;
2584 }
2585
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002586 /* process choice's specific children */
2587 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002588 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2589 /* garbage */
2590 lyxml_free_elem(module->ctx, sub);
2591 continue;
2592 }
2593
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002594 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002595 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002596 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002597 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002598 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002599 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002600 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002601 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002602 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002603 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002604 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002605 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002606 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002607 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002608 } else if (!strcmp(sub->name, "if-feature")) {
2609 c_ftrs++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002610 /* skip lyxml_free_elem() at the end of the loop, sub is processed later */
2611 continue;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002612 } else if (!strcmp(sub->name, "when")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002613 if (cs->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002614 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002615 goto error;
2616 }
2617
Radek Krejci1d82ef62015-08-07 14:44:40 +02002618 cs->when = read_yin_when(module, sub);
2619 if (!cs->when) {
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002620 goto error;
2621 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002622 if (unres_add_node(module, unres, cs->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
2623 goto error;
2624 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002625 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002626 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002627 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002628 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002629
Radek Krejci1d82ef62015-08-07 14:44:40 +02002630 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002631 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002632 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002633
Radek Krejci1d82ef62015-08-07 14:44:40 +02002634 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002635 lyxml_free_elem(module->ctx, sub);
2636 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002637
Radek Krejci3cf9e222015-06-18 11:37:50 +02002638 if (c_ftrs) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002639 cs->features = calloc(c_ftrs, sizeof *cs->features);
Radek Krejci3cf9e222015-06-18 11:37:50 +02002640 }
Radek Krejci73adb602015-07-02 18:07:40 +02002641 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002642 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002643 if (unres_add_str(module, unres, &cs->features[cs->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
2644 goto error;
2645 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002646 }
Radek Krejcib388c152015-06-04 17:03:03 +02002647
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002648 return retval;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002649
2650error:
2651
Radek Krejci1d82ef62015-08-07 14:44:40 +02002652 lys_node_free(retval);
Radek Krejcib4cf2022015-06-03 14:40:05 +02002653
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002654 return NULL;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002655}
2656
Radek Krejci76512572015-08-04 09:47:08 +02002657static struct lys_node *
Radek Krejci10c760e2015-08-14 14:45:43 +02002658read_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 +02002659{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002660 struct lyxml_elem *sub, *next;
2661 struct ly_ctx *const ctx = module->ctx;
Radek Krejci1d82ef62015-08-07 14:44:40 +02002662 struct lys_node *retval, *node = NULL;
Radek Krejcib8048692015-08-05 13:36:34 +02002663 struct lys_node_choice *choice;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002664 const char *value, *dflt_str = NULL;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002665 int f_mand = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002666
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002667 choice = calloc(1, sizeof *choice);
Radek Krejci76512572015-08-04 09:47:08 +02002668 choice->nodetype = LYS_CHOICE;
2669 choice->prev = (struct lys_node *)choice;
2670 retval = (struct lys_node *)choice;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002671
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002672 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2673 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002674 goto error;
2675 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002676
Radek Krejcia9544502015-08-14 08:24:29 +02002677 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
2678
Michal Vasko3a0043f2015-08-12 12:11:30 +02002679 /* insert the node into the schema tree */
Radek Krejci10c760e2015-08-14 14:45:43 +02002680 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002681 goto error;
2682 }
2683
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002684 /* process choice's specific children */
2685 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002686 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2687 /* garbage */
2688 lyxml_free_elem(module->ctx, sub);
2689 continue;
2690 }
2691
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002692 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002693 if (!(node = read_yin_container(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002694 goto error;
2695 }
2696 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002697 if (!(node = read_yin_leaflist(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002698 goto error;
2699 }
2700 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002701 if (!(node = read_yin_leaf(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002702 goto error;
2703 }
2704 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002705 if (!(node = read_yin_list(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002706 goto error;
2707 }
2708 } else if (!strcmp(sub->name, "case")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002709 if (!(node = read_yin_case(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002710 goto error;
2711 }
2712 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02002713 if (!(node = read_yin_anyxml(module, retval, sub, resolve, unres))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002714 goto error;
2715 }
2716 } else if (!strcmp(sub->name, "default")) {
2717 if (dflt_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002718 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002719 goto error;
2720 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002721 GETVAL(dflt_str, sub, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002722 } else if (!strcmp(sub->name, "mandatory")) {
2723 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002724 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002725 goto error;
2726 }
2727 /* just checking the flags in leaf is not sufficient, we would allow
2728 * multiple mandatory statements with the "false" value
2729 */
2730 f_mand = 1;
Radek Krejcib4cf2022015-06-03 14:40:05 +02002731
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002732 GETVAL(value, sub, "value");
2733 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002734 choice->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002735 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002736 choice->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002737 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002738 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002739 goto error;
2740 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002741 } else if (!strcmp(sub->name, "when")) {
2742 if (choice->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002743 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002744 goto error;
2745 }
2746
2747 choice->when = read_yin_when(module, sub);
2748 if (!choice->when) {
2749 goto error;
2750 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002751 if (unres_add_node(module, unres, choice->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
2752 goto error;
2753 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002754 } else if (!strcmp(sub->name, "if-feature")) {
2755 c_ftrs++;
2756
2757 /* skip lyxml_free_elem() at the end of the loop, the sub node is processed later */
2758 continue;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002759 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002760 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002761 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002762 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002763
Radek Krejci1d82ef62015-08-07 14:44:40 +02002764 node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002765 lyxml_free_elem(ctx, sub);
2766 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002767
Radek Krejci3cf9e222015-06-18 11:37:50 +02002768 if (c_ftrs) {
2769 choice->features = calloc(c_ftrs, sizeof *choice->features);
2770 }
2771
Radek Krejci73adb602015-07-02 18:07:40 +02002772 LY_TREE_FOR(yin->child, sub) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002773 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002774 if (unres_add_str(module, unres, &choice->features[choice->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
2775 goto error;
2776 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002777 }
2778
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002779 /* check - default is prohibited in combination with mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02002780 if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002781 LOGVAL(LYE_SPEC, LOGLINE(yin),
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002782 "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
2783 goto error;
2784 }
Radek Krejcib4cf2022015-06-03 14:40:05 +02002785
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002786 /* link default with the case */
2787 if (dflt_str) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002788 if (unres_add_str(module, unres, choice, UNRES_CHOICE_DFLT, dflt_str, LOGLINE(yin)) == -1) {
2789 goto error;
2790 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002791 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002793 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002794
2795error:
2796
Radek Krejci1d82ef62015-08-07 14:44:40 +02002797 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02002798
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002799 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002800}
2801
Radek Krejci76512572015-08-04 09:47:08 +02002802static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002803read_yin_anyxml(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002804 struct unres_schema *unres)
Radek Krejci863c2852015-06-03 15:47:11 +02002805{
Radek Krejci76512572015-08-04 09:47:08 +02002806 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002807 struct lys_node_leaf *anyxml;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002808 struct lyxml_elem *sub, *next;
2809 const char *value;
2810 int r;
2811 int f_mand = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002812 int c_must = 0, c_ftrs = 0;
Radek Krejci863c2852015-06-03 15:47:11 +02002813
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002814 anyxml = calloc(1, sizeof *anyxml);
Radek Krejci76512572015-08-04 09:47:08 +02002815 anyxml->nodetype = LYS_ANYXML;
2816 anyxml->prev = (struct lys_node *)anyxml;
2817 retval = (struct lys_node *)anyxml;
Radek Krejci863c2852015-06-03 15:47:11 +02002818
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002819 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2820 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002821 goto error;
2822 }
Radek Krejci863c2852015-06-03 15:47:11 +02002823
Radek Krejcia9544502015-08-14 08:24:29 +02002824 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002825
2826 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002827 goto error;
2828 }
2829
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002830 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002831 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2832 /* garbage */
2833 lyxml_free_elem(module->ctx, sub);
2834 continue;
2835 }
2836
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002837 if (!strcmp(sub->name, "mandatory")) {
2838 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002839 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002840 goto error;
2841 }
2842 /* just checking the flags in leaf is not sufficient, we would allow
2843 * multiple mandatory statements with the "false" value
2844 */
2845 f_mand = 1;
Radek Krejci863c2852015-06-03 15:47:11 +02002846
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002847 GETVAL(value, sub, "value");
2848 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002849 anyxml->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002850 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002851 anyxml->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002852 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002853 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002854 goto error;
2855 }
2856 /* else false is the default value, so we can ignore it */
2857 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002858 } else if (!strcmp(sub->name, "when")) {
2859 if (anyxml->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002860 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002861 goto error;
2862 }
2863
2864 anyxml->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002865 if (!anyxml->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002866 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002867 goto error;
2868 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002869 if (unres_add_node(module, unres, anyxml->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
2870 goto error;
2871 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002872 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002873 } else if (!strcmp(sub->name, "must")) {
2874 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002875 } else if (!strcmp(sub->name, "if-feature")) {
2876 c_ftrs++;
Radek Krejci863c2852015-06-03 15:47:11 +02002877
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002878 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002879 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002880 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002881 }
2882 }
Radek Krejci863c2852015-06-03 15:47:11 +02002883
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002884 /* middle part - process nodes with cardinality of 0..n */
2885 if (c_must) {
2886 anyxml->must = calloc(c_must, sizeof *anyxml->must);
2887 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02002888 if (c_ftrs) {
2889 anyxml->features = calloc(c_ftrs, sizeof *anyxml->features);
2890 }
Radek Krejci863c2852015-06-03 15:47:11 +02002891
Radek Krejci73adb602015-07-02 18:07:40 +02002892 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002893 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002894 r = fill_yin_must(module, sub, &anyxml->must[anyxml->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002895 if (r) {
2896 goto error;
2897 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002898 if (unres_add_node(module, unres, &anyxml->must[anyxml->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
2899 goto error;
2900 }
Radek Krejci0b24d752015-07-02 15:02:27 +02002901 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02002902 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02002903 if (unres_add_str(module, unres, &anyxml->features[anyxml->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
2904 goto error;
2905 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002906 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002907 }
Radek Krejci863c2852015-06-03 15:47:11 +02002908
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002909 return retval;
Radek Krejci863c2852015-06-03 15:47:11 +02002910
2911error:
2912
Radek Krejci1d82ef62015-08-07 14:44:40 +02002913 lys_node_free(retval);
Radek Krejci863c2852015-06-03 15:47:11 +02002914
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002915 return NULL;
Radek Krejci863c2852015-06-03 15:47:11 +02002916}
2917
Radek Krejci76512572015-08-04 09:47:08 +02002918static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02002919read_yin_leaf(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02002920 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02002921{
Radek Krejci76512572015-08-04 09:47:08 +02002922 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02002923 struct lys_node_leaf *leaf;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002924 struct lyxml_elem *sub, *next;
2925 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002926 int r, has_type = 0, dflt_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02002927 int c_must = 0, c_ftrs = 0, f_mand = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002928
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002929 leaf = calloc(1, sizeof *leaf);
Radek Krejci76512572015-08-04 09:47:08 +02002930 leaf->nodetype = LYS_LEAF;
2931 leaf->prev = (struct lys_node *)leaf;
2932 retval = (struct lys_node *)leaf;
Radek Krejcida04f4a2015-05-21 12:54:09 +02002933
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002934 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
2935 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002936 goto error;
2937 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02002938
Radek Krejcia9544502015-08-14 08:24:29 +02002939 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02002940
2941 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02002942 goto error;
2943 }
2944
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002945 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02002946 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
2947 /* garbage */
2948 lyxml_free_elem(module->ctx, sub);
2949 continue;
2950 }
2951
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002952 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002953 if (leaf->type.der || has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002954 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002955 goto error;
2956 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002957 if (fill_yin_type(module, parent, sub, &leaf->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002958 goto error;
2959 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002960 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002961 } else if (!strcmp(sub->name, "default")) {
2962 if (leaf->dflt) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002963 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002964 goto error;
2965 }
2966 GETVAL(value, sub, "value");
2967 leaf->dflt = lydict_insert(module->ctx, value, strlen(value));
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02002968 dflt_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002969 } else if (!strcmp(sub->name, "units")) {
2970 if (leaf->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002971 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002972 goto error;
2973 }
2974 GETVAL(value, sub, "name");
2975 leaf->units = lydict_insert(module->ctx, value, strlen(value));
2976 } else if (!strcmp(sub->name, "mandatory")) {
2977 if (f_mand) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002978 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002979 goto error;
2980 }
2981 /* just checking the flags in leaf is not sufficient, we would allow
2982 * multiple mandatory statements with the "false" value
2983 */
2984 f_mand = 1;
Radek Krejci4c31f122015-06-02 14:51:22 +02002985
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002986 GETVAL(value, sub, "value");
2987 if (!strcmp(value, "true")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002988 leaf->flags |= LYS_MAND_TRUE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002989 } else if (!strcmp(value, "false")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02002990 leaf->flags |= LYS_MAND_FALSE;
Radek Krejcieb00f512015-07-01 16:44:58 +02002991 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002992 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02002993 goto error;
2994 } /* else false is the default value, so we can ignore it */
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002995 } else if (!strcmp(sub->name, "when")) {
2996 if (leaf->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02002997 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02002998 goto error;
2999 }
3000
3001 leaf->when = read_yin_when(module, sub);
3002 if (!leaf->when) {
3003 goto error;
3004 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003005 if (unres_add_node(module, unres, leaf->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
3006 goto error;
3007 }
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003008
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003009 } else if (!strcmp(sub->name, "must")) {
Radek Krejci41882de2015-07-02 16:34:58 +02003010 c_must++;
3011 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003012 } else if (!strcmp(sub->name, "if-feature")) {
3013 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003014 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003015
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003016 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003017 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003018 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003019 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003020
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003021 lyxml_free_elem(module->ctx, sub);
3022 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003023
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003024 /* check mandatory parameters */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003025 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003026 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003027 goto error;
3028 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003029 if (leaf->dflt) {
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003030 if (unres_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, leaf->dflt, dflt_line) == -1) {
3031 goto error;
3032 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003033 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003034
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003035 /* middle part - process nodes with cardinality of 0..n */
3036 if (c_must) {
3037 leaf->must = calloc(c_must, sizeof *leaf->must);
3038 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003039 if (c_ftrs) {
3040 leaf->features = calloc(c_ftrs, sizeof *leaf->features);
3041 }
Radek Krejci4c31f122015-06-02 14:51:22 +02003042
Radek Krejci73adb602015-07-02 18:07:40 +02003043 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003044 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003045 r = fill_yin_must(module, sub, &leaf->must[leaf->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003046 if (r) {
3047 goto error;
3048 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003049 if (unres_add_node(module, unres, &leaf->must[leaf->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
3050 goto error;
3051 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003052 } else if (!strcmp(sub->name, "if-feature")) {
3053 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003054 if (unres_add_str(module, unres, &leaf->features[leaf->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
3055 goto error;
3056 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003057 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003058 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003059
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003060 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003061
3062error:
3063
Radek Krejci1d82ef62015-08-07 14:44:40 +02003064 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003065
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003066 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003067}
3068
Radek Krejci76512572015-08-04 09:47:08 +02003069static struct lys_node *
Radek Krejcib8048692015-08-05 13:36:34 +02003070read_yin_leaflist(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003071 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003072{
Radek Krejci76512572015-08-04 09:47:08 +02003073 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003074 struct lys_node_leaflist *llist;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003075 struct lyxml_elem *sub, *next;
3076 const char *value;
3077 char *endptr;
3078 unsigned long val;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003079 int r, has_type = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003080 int c_must = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003081 int f_ordr = 0, f_min = 0, f_max = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003082
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003083 llist = calloc(1, sizeof *llist);
Radek Krejci76512572015-08-04 09:47:08 +02003084 llist->nodetype = LYS_LEAFLIST;
3085 llist->prev = (struct lys_node *)llist;
3086 retval = (struct lys_node *)llist;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003087
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003088 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3089 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003090 goto error;
3091 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003092
Radek Krejcia9544502015-08-14 08:24:29 +02003093 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
Radek Krejci10c760e2015-08-14 14:45:43 +02003094
3095 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003096 goto error;
3097 }
3098
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003099 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003100 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3101 /* garbage */
3102 lyxml_free_elem(module->ctx, sub);
3103 continue;
3104 }
3105
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003106 if (!strcmp(sub->name, "type")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003107 if (llist->type.der || has_type) {
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 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003111 if (fill_yin_type(module, parent, sub, &llist->type, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003112 goto error;
3113 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003114 has_type = 1;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003115 } else if (!strcmp(sub->name, "units")) {
3116 if (llist->units) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003117 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003118 goto error;
3119 }
3120 GETVAL(value, sub, "name");
3121 llist->units = lydict_insert(module->ctx, value, strlen(value));
3122 } else if (!strcmp(sub->name, "ordered-by")) {
3123 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003124 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003125 goto error;
3126 }
3127 /* just checking the flags in llist is not sufficient, we would
3128 * allow multiple ordered-by statements with the "system" value
3129 */
3130 f_ordr = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003131
Radek Krejci1574a8d2015-08-03 14:16:52 +02003132 if (llist->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003133 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3134 * state data
3135 */
3136 lyxml_free_elem(module->ctx, sub);
3137 continue;
3138 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003139
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003140 GETVAL(value, sub, "value");
3141 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003142 llist->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003143 } else if (strcmp(value, "system")) {
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;
Radek Krejci41882de2015-07-02 16:34:58 +02003146 } /* else system is the default value, so we can ignore it */
3147
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003148 } else if (!strcmp(sub->name, "must")) {
3149 c_must++;
Radek Krejci41882de2015-07-02 16:34:58 +02003150 continue;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003151 } else if (!strcmp(sub->name, "if-feature")) {
3152 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003153 continue;
Radek Krejci41882de2015-07-02 16:34:58 +02003154
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003155 } else if (!strcmp(sub->name, "min-elements")) {
3156 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003157 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003158 goto error;
3159 }
3160 f_min = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003161
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003162 GETVAL(value, sub, "value");
3163 while (isspace(value[0])) {
3164 value++;
3165 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003166
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003167 /* convert it to uint32_t */
3168 errno = 0;
3169 endptr = NULL;
3170 val = strtoul(value, &endptr, 10);
3171 if (*endptr || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003172 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003173 goto error;
3174 }
3175 llist->min = (uint32_t) val;
3176 } else if (!strcmp(sub->name, "max-elements")) {
3177 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003178 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003179 goto error;
3180 }
3181 f_max = 1;
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003182
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003183 GETVAL(value, sub, "value");
3184 while (isspace(value[0])) {
3185 value++;
3186 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003187
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003188 /* convert it to uint32_t */
3189 errno = 0;
3190 endptr = NULL;
3191 val = strtoul(value, &endptr, 10);
3192 if (*endptr || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003193 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003194 goto error;
3195 }
3196 llist->max = (uint32_t) val;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003197 } else if (!strcmp(sub->name, "when")) {
3198 if (llist->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003199 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003200 goto error;
3201 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003202
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003203 llist->when = read_yin_when(module, sub);
3204 if (!llist->when) {
3205 goto error;
3206 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003207 if (unres_add_node(module, unres, llist->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
3208 goto error;
3209 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003210 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003211 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003212 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003213 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003214
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003215 lyxml_free_elem(module->ctx, sub);
3216 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003217
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003218 /* check constraints */
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003219 if (!has_type) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003220 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "type", yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003221 goto error;
3222 }
3223 if (llist->max && llist->min > llist->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003224 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003225 goto error;
3226 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003227
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003228 /* middle part - process nodes with cardinality of 0..n */
3229 if (c_must) {
3230 llist->must = calloc(c_must, sizeof *llist->must);
3231 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003232 if (c_ftrs) {
3233 llist->features = calloc(c_ftrs, sizeof *llist->features);
3234 }
Radek Krejci8b4f23c2015-06-02 16:09:25 +02003235
Radek Krejci73adb602015-07-02 18:07:40 +02003236 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003237 if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003238 r = fill_yin_must(module, sub, &llist->must[llist->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003239 if (r) {
3240 goto error;
3241 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003242 if (unres_add_node(module, unres, &llist->must[llist->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
3243 goto error;
3244 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003245 } else if (!strcmp(sub->name, "if-feature")) {
3246 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003247 if (unres_add_str(module, unres, &llist->features[llist->features_size++], UNRES_IFFEAT, value,
3248 LOGLINE(sub)) == -1) {
3249 goto error;
3250 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003251 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003252 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003253
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003254 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003255
3256error:
3257
Radek Krejci1d82ef62015-08-07 14:44:40 +02003258 lys_node_free(retval);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003259
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003260 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003261}
3262
Radek Krejci76512572015-08-04 09:47:08 +02003263static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003264read_yin_list(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3265 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003266{
Radek Krejci1d82ef62015-08-07 14:44:40 +02003267 struct lys_node *retval, *node;
Radek Krejcib8048692015-08-05 13:36:34 +02003268 struct lys_node_list *list;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003269 struct lyxml_elem *sub, *next, root, uniq;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003270 int r, key_line;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003271 int c_tpdf = 0, c_must = 0, c_uniq = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003272 int f_ordr = 0, f_max = 0, f_min = 0;
Radek Krejcieb00f512015-07-01 16:44:58 +02003273 const char *key_str = NULL, *value;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003274 char *auxs;
3275 unsigned long val;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003276
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003277 /* init */
3278 memset(&root, 0, sizeof root);
3279 memset(&uniq, 0, sizeof uniq);
Radek Krejcie0674f82015-06-15 13:58:51 +02003280
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003281 list = calloc(1, sizeof *list);
Radek Krejci76512572015-08-04 09:47:08 +02003282 list->nodetype = LYS_LIST;
3283 list->prev = (struct lys_node *)list;
3284 retval = (struct lys_node *)list;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003285
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003286 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3287 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003288 goto error;
3289 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003290
Radek Krejcia9544502015-08-14 08:24:29 +02003291 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3292
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003293 /* process list's specific children */
3294 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003295 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3296 /* garbage */
3297 lyxml_free_elem(module->ctx, sub);
3298 continue;
3299 }
3300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003301 /* data statements */
3302 if (!strcmp(sub->name, "container") ||
3303 !strcmp(sub->name, "leaf-list") ||
3304 !strcmp(sub->name, "leaf") ||
3305 !strcmp(sub->name, "list") ||
3306 !strcmp(sub->name, "choice") ||
3307 !strcmp(sub->name, "uses") ||
3308 !strcmp(sub->name, "grouping") ||
3309 !strcmp(sub->name, "anyxml")) {
3310 lyxml_unlink_elem(sub);
3311 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003312
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003313 /* array counters */
3314 } else if (!strcmp(sub->name, "key")) {
3315 /* check cardinality 0..1 */
3316 if (list->keys_size) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003317 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, list->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003318 goto error;
3319 }
Radek Krejcid7f0d012015-05-25 15:04:52 +02003320
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003321 /* count the number of keys */
3322 GETVAL(value, sub, "value");
3323 key_str = value;
Michal Vaskoe38af6e2015-08-03 14:39:27 +02003324 key_line = LOGLINE(sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003325 while ((value = strpbrk(value, " \t\n"))) {
3326 list->keys_size++;
3327 while (isspace(*value)) {
3328 value++;
3329 }
3330 }
3331 list->keys_size++;
3332 list->keys = calloc(list->keys_size, sizeof *list->keys);
3333 } else if (!strcmp(sub->name, "unique")) {
3334 c_uniq++;
3335 lyxml_unlink_elem(sub);
3336 lyxml_add_child(&uniq, sub);
3337 } else if (!strcmp(sub->name, "typedef")) {
3338 c_tpdf++;
3339 } else if (!strcmp(sub->name, "must")) {
3340 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003341 } else if (!strcmp(sub->name, "if-feature")) {
3342 c_ftrs++;
Radek Krejci345ad742015-06-03 11:04:18 +02003343
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003344 /* optional stetments */
3345 } else if (!strcmp(sub->name, "ordered-by")) {
3346 if (f_ordr) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003347 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003348 goto error;
3349 }
3350 /* just checking the flags in llist is not sufficient, we would
3351 * allow multiple ordered-by statements with the "system" value
3352 */
3353 f_ordr = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003354
Radek Krejci1574a8d2015-08-03 14:16:52 +02003355 if (list->flags & LYS_CONFIG_R) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003356 /* RFC 6020, 7.7.5 - ignore ordering when the list represents
3357 * state data
3358 */
3359 lyxml_free_elem(module->ctx, sub);
3360 continue;
3361 }
Radek Krejci345ad742015-06-03 11:04:18 +02003362
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003363 GETVAL(value, sub, "value");
3364 if (!strcmp(value, "user")) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02003365 list->flags |= LYS_USERORDERED;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003366 } else if (strcmp(value, "system")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003367 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003368 goto error;
3369 }
3370 /* else system is the default value, so we can ignore it */
3371 lyxml_free_elem(module->ctx, sub);
3372 } else if (!strcmp(sub->name, "min-elements")) {
3373 if (f_min) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003374 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003375 goto error;
3376 }
3377 f_min = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003379 GETVAL(value, sub, "value");
3380 while (isspace(value[0])) {
3381 value++;
3382 }
Radek Krejci345ad742015-06-03 11:04:18 +02003383
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003384 /* convert it to uint32_t */
3385 errno = 0;
3386 auxs = NULL;
3387 val = strtoul(value, &auxs, 10);
3388 if (*auxs || value[0] == '-' || errno || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003389 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003390 goto error;
3391 }
3392 list->min = (uint32_t) val;
3393 lyxml_free_elem(module->ctx, sub);
3394 } else if (!strcmp(sub->name, "max-elements")) {
3395 if (f_max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003396 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003397 goto error;
3398 }
3399 f_max = 1;
Radek Krejci345ad742015-06-03 11:04:18 +02003400
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003401 GETVAL(value, sub, "value");
3402 while (isspace(value[0])) {
3403 value++;
3404 }
Radek Krejci345ad742015-06-03 11:04:18 +02003405
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003406 /* convert it to uint32_t */
3407 errno = 0;
3408 auxs = NULL;
3409 val = strtoul(value, &auxs, 10);
3410 if (*auxs || value[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003411 LOGVAL(LYE_INARG, LOGLINE(sub), value, sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003412 goto error;
3413 }
3414 list->max = (uint32_t) val;
3415 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003416 } else if (!strcmp(sub->name, "when")) {
3417 if (list->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003418 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003419 goto error;
3420 }
3421
3422 list->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003423 if (!list->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003424 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003425 goto error;
3426 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003427 if (unres_add_node(module, unres, list->when, UNRES_WHEN, NULL, LOGLINE(sub)) == -1) {
3428 goto error;
3429 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003430 lyxml_free_elem(module->ctx, sub);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003431 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003432 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003433 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003434 }
3435 }
Radek Krejci345ad742015-06-03 11:04:18 +02003436
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003437 /* check - if list is configuration, key statement is mandatory */
Radek Krejci1574a8d2015-08-03 14:16:52 +02003438 if ((list->flags & LYS_CONFIG_W) && !key_str) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003439 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "key", "list");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003440 goto error;
3441 }
3442 if (list->max && list->min > list->max) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003443 LOGVAL(LYE_SPEC, LOGLINE(yin), "\"min-elements\" is bigger than \"max-elements\".");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003444 goto error;
3445 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003446
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003447 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3448 if (c_tpdf) {
3449 list->tpdf = calloc(c_tpdf, sizeof *list->tpdf);
3450 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003451 if (c_must) {
3452 list->must = calloc(c_must, sizeof *list->must);
3453 }
3454 if (c_ftrs) {
3455 list->features = calloc(c_ftrs, sizeof *list->features);
3456 }
Radek Krejci73adb602015-07-02 18:07:40 +02003457 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003458 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003459 r = fill_yin_typedef(module, retval, sub, &list->tpdf[list->tpdf_size++], unres);
Radek Krejcid7f0d012015-05-25 15:04:52 +02003460
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003461 if (r) {
3462 goto error;
3463 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003464 } else if (!strcmp(sub->name, "if-feature")) {
3465 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003466 if (unres_add_str(module, unres, &list->features[list->features_size++], UNRES_IFFEAT, value, LOGLINE(sub)) == -1) {
3467 goto error;
3468 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003469 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003470 r = fill_yin_must(module, sub, &list->must[list->must_size++]);
Radek Krejci3cf9e222015-06-18 11:37:50 +02003471 if (r) {
3472 goto error;
3473 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003474 if (unres_add_node(module, unres, &list->must[list->must_size-1], UNRES_MUST, retval, LOGLINE(sub)) == -1) {
3475 goto error;
3476 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003477 }
3478 }
Radek Krejci25d782a2015-05-22 15:03:23 +02003479
Radek Krejci10c760e2015-08-14 14:45:43 +02003480 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003481 goto error;
3482 }
3483
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003484 /* last part - process data nodes */
3485 LY_TREE_FOR_SAFE(root.child, next, sub) {
3486 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003487 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003488 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003489 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003490 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003491 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003492 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003493 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003494 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003495 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003496 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003497 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003498 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003499 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003500 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003501 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vaskoc07187d2015-08-13 15:20:57 +02003502 } else {
3503 LOGINT;
3504 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003505 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003506 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003507 goto error;
3508 }
Radek Krejci73adb602015-07-02 18:07:40 +02003509
3510 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003511 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003512
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003513 if (!key_str) {
3514 /* config false list without a key */
3515 return retval;
3516 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003517 if (unres_add_str(module, unres, list, UNRES_LIST_KEYS, key_str, key_line) == -1) {
3518 goto error;
3519 }
Radek Krejci812b10a2015-05-28 16:48:25 +02003520
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003521 /* process unique statements */
3522 if (c_uniq) {
3523 list->unique = calloc(c_uniq, sizeof *list->unique);
3524 }
3525 LY_TREE_FOR_SAFE(uniq.child, next, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003526 /* HACK for unres */
Radek Krejcib8048692015-08-05 13:36:34 +02003527 list->unique[list->unique_size++].leafs = (struct lys_node_leaf **)list;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003528 GETVAL(value, sub, "tag");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003529 if (unres_add_str(module, unres, &list->unique[list->unique_size-1], UNRES_LIST_UNIQ, value,
3530 LOGLINE(sub)) == -1) {
3531 goto error;
3532 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003533
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003534 lyxml_free_elem(module->ctx, sub);
3535 }
Radek Krejci1e9b9992015-06-04 17:57:04 +02003536
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003537 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003538
3539error:
3540
Radek Krejci1d82ef62015-08-07 14:44:40 +02003541 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003542 while (root.child) {
3543 lyxml_free_elem(module->ctx, root.child);
3544 }
3545 while (uniq.child) {
3546 lyxml_free_elem(module->ctx, uniq.child);
3547 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003548
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003549 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003550}
3551
Radek Krejci76512572015-08-04 09:47:08 +02003552static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003553read_yin_container(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3554 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003555{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003556 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003557 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003558 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003559 struct lys_node_container *cont;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003560 const char *value;
3561 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003562 int c_tpdf = 0, c_must = 0, c_ftrs = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003563
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003564 /* init */
3565 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003566
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003567 cont = calloc(1, sizeof *cont);
Radek Krejci76512572015-08-04 09:47:08 +02003568 cont->nodetype = LYS_CONTAINER;
3569 cont->prev = (struct lys_node *)cont;
3570 retval = (struct lys_node *)cont;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003571
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003572 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_CONFIG | OPT_NACMEXT
3573 | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003574 goto error;
3575 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003576
Radek Krejcia9544502015-08-14 08:24:29 +02003577 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3578
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003579 /* process container's specific children */
3580 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci6764bb32015-07-03 15:16:04 +02003581 if (!sub->ns) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003582 /* garbage */
3583 lyxml_free_elem(module->ctx, sub);
3584 continue;
3585 }
3586
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003587 if (!strcmp(sub->name, "presence")) {
3588 if (cont->presence) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003589 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003590 goto error;
3591 }
3592 GETVAL(value, sub, "value");
3593 cont->presence = lydict_insert(module->ctx, value, strlen(value));
Radek Krejci800af702015-06-02 13:46:01 +02003594
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003595 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003596 } else if (!strcmp(sub->name, "when")) {
3597 if (cont->when) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003598 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003599 goto error;
3600 }
3601
3602 cont->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003603 if (!cont->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003604 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02003605 goto error;
3606 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003607 if (unres_add_node(module, unres, cont->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
3608 goto error;
3609 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003610 lyxml_free_elem(module->ctx, sub);
Radek Krejci4c31f122015-06-02 14:51:22 +02003611
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003612 /* data statements */
3613 } else if (!strcmp(sub->name, "container") ||
3614 !strcmp(sub->name, "leaf-list") ||
3615 !strcmp(sub->name, "leaf") ||
3616 !strcmp(sub->name, "list") ||
3617 !strcmp(sub->name, "choice") ||
3618 !strcmp(sub->name, "uses") ||
3619 !strcmp(sub->name, "grouping") ||
3620 !strcmp(sub->name, "anyxml")) {
3621 lyxml_unlink_elem(sub);
3622 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003624 /* array counters */
3625 } else if (!strcmp(sub->name, "typedef")) {
3626 c_tpdf++;
3627 } else if (!strcmp(sub->name, "must")) {
3628 c_must++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003629 } else if (!strcmp(sub->name, "if-feature")) {
3630 c_ftrs++;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003631 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003632 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003633 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003634 }
3635 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003636
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003637 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3638 if (c_tpdf) {
3639 cont->tpdf = calloc(c_tpdf, sizeof *cont->tpdf);
3640 }
3641 if (c_must) {
3642 cont->must = calloc(c_must, sizeof *cont->must);
3643 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003644 if (c_ftrs) {
3645 cont->features = calloc(c_ftrs, sizeof *cont->features);
3646 }
Radek Krejci800af702015-06-02 13:46:01 +02003647
Radek Krejci73adb602015-07-02 18:07:40 +02003648 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003649 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003650 r = fill_yin_typedef(module, retval, sub, &cont->tpdf[cont->tpdf_size++], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003651 if (r) {
3652 goto error;
3653 }
3654 } else if (!strcmp(sub->name, "must")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003655 r = fill_yin_must(module, sub, &cont->must[cont->must_size++]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003656 if (r) {
3657 goto error;
3658 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003659 if (unres_add_node(module, unres, &cont->must[cont->must_size-1], UNRES_MUST, retval,
3660 LOGLINE(sub)) == -1) {
3661 goto error;
3662 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02003663 } else if (!strcmp(sub->name, "if-feature")) {
3664 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02003665 if (unres_add_str(module, unres, &cont->features[cont->features_size++], UNRES_IFFEAT, value,
3666 LOGLINE(sub)) == -1) {
3667 goto error;
3668 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003669 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003670 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003671
Radek Krejci10c760e2015-08-14 14:45:43 +02003672 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003673 goto error;
3674 }
3675
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003676 /* last part - process data nodes */
3677 LY_TREE_FOR_SAFE(root.child, next, sub) {
3678 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003679 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003680 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003681 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003682 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003683 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003684 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003685 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003686 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003687 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003688 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003689 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003690 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003691 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003692 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003693 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003694 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003695 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003696 goto error;
3697 }
Radek Krejci73adb602015-07-02 18:07:40 +02003698
3699 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003700 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003701
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003702 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003703
3704error:
3705
Radek Krejci1d82ef62015-08-07 14:44:40 +02003706 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003707 while (root.child) {
3708 lyxml_free_elem(module->ctx, root.child);
3709 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003710
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003711 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003712}
3713
Radek Krejci76512572015-08-04 09:47:08 +02003714static struct lys_node *
Radek Krejci1d82ef62015-08-07 14:44:40 +02003715read_yin_grouping(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02003716 struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02003717{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003718 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003719 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003720 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003721 struct lys_node_grp *grp;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003722 int r;
3723 int c_tpdf = 0;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003724
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003725 /* init */
3726 memset(&root, 0, sizeof root);
Radek Krejcie0674f82015-06-15 13:58:51 +02003727
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003728 grp = calloc(1, sizeof *grp);
Radek Krejci76512572015-08-04 09:47:08 +02003729 grp->nodetype = LYS_GROUPING;
3730 grp->prev = (struct lys_node *)grp;
3731 retval = (struct lys_node *)grp;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003732
Michal Vasko71e1aa82015-08-12 12:17:51 +02003733 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003734 goto error;
3735 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003736
Radek Krejcia9544502015-08-14 08:24:29 +02003737 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3738
Radek Krejci1d82ef62015-08-07 14:44:40 +02003739 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003740 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3741 /* garbage */
3742 lyxml_free_elem(module->ctx, sub);
3743 continue;
3744 }
3745
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003746 /* data statements */
3747 if (!strcmp(sub->name, "container") ||
3748 !strcmp(sub->name, "leaf-list") ||
3749 !strcmp(sub->name, "leaf") ||
3750 !strcmp(sub->name, "list") ||
3751 !strcmp(sub->name, "choice") ||
3752 !strcmp(sub->name, "uses") ||
3753 !strcmp(sub->name, "grouping") ||
3754 !strcmp(sub->name, "anyxml")) {
3755 lyxml_unlink_elem(sub);
3756 lyxml_add_child(&root, sub);
Radek Krejcida04f4a2015-05-21 12:54:09 +02003757
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003758 /* array counters */
3759 } else if (!strcmp(sub->name, "typedef")) {
3760 c_tpdf++;
3761 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003762 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003763 goto error;
3764 }
3765 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003766
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003767 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3768 if (c_tpdf) {
3769 grp->tpdf = calloc(c_tpdf, sizeof *grp->tpdf);
3770 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003771 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003772 r = fill_yin_typedef(module, retval, sub, &grp->tpdf[grp->tpdf_size++], unres);
Radek Krejci25d782a2015-05-22 15:03:23 +02003773
Radek Krejci73adb602015-07-02 18:07:40 +02003774 if (r) {
3775 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003776 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003777 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003778
Radek Krejci10c760e2015-08-14 14:45:43 +02003779 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003780 goto error;
3781 }
3782
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003783 /* last part - process data nodes */
3784 LY_TREE_FOR_SAFE(root.child, next, sub) {
3785 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003786 node = read_yin_container(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003787 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003788 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003789 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003790 node = read_yin_leaf(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003791 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003792 node = read_yin_list(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003793 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003794 node = read_yin_choice(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003795 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003796 node = read_yin_uses(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003797 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003798 node = read_yin_grouping(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003799 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003800 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003801 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003802 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003803 goto error;
3804 }
Radek Krejci73adb602015-07-02 18:07:40 +02003805
3806 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003807 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003808
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003809 return retval;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003810
3811error:
3812
Radek Krejci1d82ef62015-08-07 14:44:40 +02003813 lys_node_free(retval);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003814 while (root.child) {
3815 lyxml_free_elem(module->ctx, root.child);
3816 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02003817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003818 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02003819}
3820
Radek Krejci76512572015-08-04 09:47:08 +02003821static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003822read_yin_input_output(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3823 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02003824{
Radek Krejcie0674f82015-06-15 13:58:51 +02003825 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003826 struct lys_node *node = NULL;
Radek Krejci31fc30d2015-08-13 08:27:38 +02003827 struct lys_node *retval = NULL;
Radek Krejci4608ada2015-08-05 16:04:37 +02003828 struct lys_node_rpc_inout *inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003829 int r;
3830 int c_tpdf = 0;
3831
Radek Krejcie0674f82015-06-15 13:58:51 +02003832 /* init */
3833 memset(&root, 0, sizeof root);
3834
Michal Vasko38d01f72015-06-15 09:41:06 +02003835 inout = calloc(1, sizeof *inout);
Radek Krejci6acc8012015-08-13 09:07:04 +02003836 inout->prev = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003837
3838 if (!strcmp(yin->name, "input")) {
Radek Krejci76512572015-08-04 09:47:08 +02003839 inout->nodetype = LYS_INPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003840 } else if (!strcmp(yin->name, "output")) {
Radek Krejci76512572015-08-04 09:47:08 +02003841 inout->nodetype = LYS_OUTPUT;
Michal Vasko38d01f72015-06-15 09:41:06 +02003842 } else {
Michal Vasko0c888fd2015-08-11 15:54:08 +02003843 LOGINT;
Radek Krejci6acc8012015-08-13 09:07:04 +02003844 free(inout);
Michal Vasko0c888fd2015-08-11 15:54:08 +02003845 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003846 }
3847
Radek Krejci76512572015-08-04 09:47:08 +02003848 retval = (struct lys_node *)inout;
Michal Vasko38d01f72015-06-15 09:41:06 +02003849
Radek Krejci6a113852015-07-03 16:04:20 +02003850 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT)) {
Michal Vaskoebeac942015-06-15 12:11:50 +02003851 goto error;
3852 }
3853
Radek Krejcia9544502015-08-14 08:24:29 +02003854 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3855
Michal Vasko38d01f72015-06-15 09:41:06 +02003856 /* data statements */
3857 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003858 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3859 /* garbage */
3860 lyxml_free_elem(module->ctx, sub);
3861 continue;
3862 }
3863
Michal Vasko38d01f72015-06-15 09:41:06 +02003864 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003865 !strcmp(sub->name, "leaf-list") ||
3866 !strcmp(sub->name, "leaf") ||
3867 !strcmp(sub->name, "list") ||
3868 !strcmp(sub->name, "choice") ||
3869 !strcmp(sub->name, "uses") ||
3870 !strcmp(sub->name, "grouping") ||
3871 !strcmp(sub->name, "anyxml")) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003872 lyxml_unlink_elem(sub);
3873 lyxml_add_child(&root, sub);
3874
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003875 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02003876 } else if (!strcmp(sub->name, "typedef")) {
3877 c_tpdf++;
Radek Krejcid2bfa792015-07-02 16:45:29 +02003878
Michal Vasko38d01f72015-06-15 09:41:06 +02003879 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003880 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02003881 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003882 }
3883 }
3884
3885 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3886 if (c_tpdf) {
3887 inout->tpdf = calloc(c_tpdf, sizeof *inout->tpdf);
3888 }
3889
Radek Krejci73adb602015-07-02 18:07:40 +02003890 LY_TREE_FOR(yin->child, sub) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02003891 r = fill_yin_typedef(module, retval, sub, &inout->tpdf[inout->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003892
Radek Krejci73adb602015-07-02 18:07:40 +02003893 if (r) {
3894 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02003895 }
Michal Vasko38d01f72015-06-15 09:41:06 +02003896 }
3897
Radek Krejci10c760e2015-08-14 14:45:43 +02003898 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02003899 goto error;
3900 }
3901
Michal Vasko38d01f72015-06-15 09:41:06 +02003902 /* last part - process data nodes */
3903 LY_TREE_FOR_SAFE(root.child, next, sub) {
3904 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003905 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003906 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003907 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003908 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003909 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003910 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003911 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003912 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003913 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003914 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003915 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003916 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003917 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003918 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02003919 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02003920 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02003921 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02003922 goto error;
3923 }
Radek Krejci73adb602015-07-02 18:07:40 +02003924
3925 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02003926 }
3927
Michal Vasko38d01f72015-06-15 09:41:06 +02003928 return retval;
3929
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003930error:
Michal Vasko38d01f72015-06-15 09:41:06 +02003931
Radek Krejci1d82ef62015-08-07 14:44:40 +02003932 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02003933 while (root.child) {
3934 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02003935 }
3936
3937 return NULL;
3938}
3939
Radek Krejci76512572015-08-04 09:47:08 +02003940static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02003941read_yin_notif(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
3942 struct unres_schema *unres)
Michal Vasko0ea41032015-06-16 08:53:55 +02003943{
Michal Vaskoc6551b32015-06-16 10:51:43 +02003944 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02003945 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02003946 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02003947 struct lys_node_notif *notif;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003948 const char *value;
Michal Vasko0ea41032015-06-16 08:53:55 +02003949 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003950 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko0ea41032015-06-16 08:53:55 +02003951
Michal Vaskoc6551b32015-06-16 10:51:43 +02003952 memset(&root, 0, sizeof root);
3953
Michal Vasko0ea41032015-06-16 08:53:55 +02003954 notif = calloc(1, sizeof *notif);
Radek Krejci76512572015-08-04 09:47:08 +02003955 notif->nodetype = LYS_NOTIF;
3956 notif->prev = (struct lys_node *)notif;
3957 retval = (struct lys_node *)notif;
Michal Vasko0ea41032015-06-16 08:53:55 +02003958
Radek Krejci6a113852015-07-03 16:04:20 +02003959 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003960 goto error;
3961 }
3962
Radek Krejcia9544502015-08-14 08:24:29 +02003963 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
3964
Michal Vasko0ea41032015-06-16 08:53:55 +02003965 /* process rpc's specific children */
3966 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02003967 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
3968 /* garbage */
3969 lyxml_free_elem(module->ctx, sub);
3970 continue;
3971 }
3972
Michal Vasko0ea41032015-06-16 08:53:55 +02003973 /* data statements */
3974 if (!strcmp(sub->name, "container") ||
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003975 !strcmp(sub->name, "leaf-list") ||
3976 !strcmp(sub->name, "leaf") ||
3977 !strcmp(sub->name, "list") ||
3978 !strcmp(sub->name, "choice") ||
3979 !strcmp(sub->name, "uses") ||
3980 !strcmp(sub->name, "grouping") ||
3981 !strcmp(sub->name, "anyxml")) {
Michal Vasko0ea41032015-06-16 08:53:55 +02003982 lyxml_unlink_elem(sub);
3983 lyxml_add_child(&root, sub);
3984
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02003985 /* array counters */
Michal Vasko0ea41032015-06-16 08:53:55 +02003986 } else if (!strcmp(sub->name, "typedef")) {
3987 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02003988 } else if (!strcmp(sub->name, "if-feature")) {
3989 c_ftrs++;
Michal Vasko0ea41032015-06-16 08:53:55 +02003990 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02003991 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko0ea41032015-06-16 08:53:55 +02003992 goto error;
Michal Vasko0ea41032015-06-16 08:53:55 +02003993 }
3994 }
3995
3996 /* middle part - process nodes with cardinality of 0..n except the data nodes */
3997 if (c_tpdf) {
3998 notif->tpdf = calloc(c_tpdf, sizeof *notif->tpdf);
3999 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004000 if (c_ftrs) {
4001 notif->features = calloc(c_ftrs, sizeof *notif->features);
4002 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004003
Radek Krejci73adb602015-07-02 18:07:40 +02004004 LY_TREE_FOR(yin->child, sub) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004005 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004006 r = fill_yin_typedef(module, retval, sub, &notif->tpdf[notif->tpdf_size++], unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004007
4008 if (r) {
4009 goto error;
4010 }
Radek Krejci0b24d752015-07-02 15:02:27 +02004011 } else if (!strcmp(sub->name, "if-features")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004012 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004013 if (unres_add_str(module, unres, &notif->features[notif->features_size++], UNRES_IFFEAT, value,
4014 LOGLINE(sub)) == -1) {
4015 goto error;
4016 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004017 }
Michal Vasko0ea41032015-06-16 08:53:55 +02004018 }
4019
Radek Krejci10c760e2015-08-14 14:45:43 +02004020 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004021 goto error;
4022 }
4023
Michal Vasko0ea41032015-06-16 08:53:55 +02004024 /* last part - process data nodes */
4025 LY_TREE_FOR_SAFE(root.child, next, sub) {
4026 if (!strcmp(sub->name, "container")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004027 node = read_yin_container(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004028 } else if (!strcmp(sub->name, "leaf-list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004029 node = read_yin_leaflist(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004030 } else if (!strcmp(sub->name, "leaf")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004031 node = read_yin_leaf(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004032 } else if (!strcmp(sub->name, "list")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004033 node = read_yin_list(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004034 } else if (!strcmp(sub->name, "choice")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004035 node = read_yin_choice(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004036 } else if (!strcmp(sub->name, "uses")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004037 node = read_yin_uses(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004038 } else if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004039 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004040 } else if (!strcmp(sub->name, "anyxml")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004041 node = read_yin_anyxml(module, retval, sub, resolve, unres);
Michal Vasko0ea41032015-06-16 08:53:55 +02004042 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004043 if (!node) {
Michal Vasko0ea41032015-06-16 08:53:55 +02004044 goto error;
4045 }
Radek Krejci73adb602015-07-02 18:07:40 +02004046
4047 lyxml_free_elem(module->ctx, sub);
Michal Vasko0ea41032015-06-16 08:53:55 +02004048 }
4049
Michal Vasko0ea41032015-06-16 08:53:55 +02004050 return retval;
4051
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004052error:
Michal Vasko0ea41032015-06-16 08:53:55 +02004053
Radek Krejci1d82ef62015-08-07 14:44:40 +02004054 lys_node_free(retval);
Michal Vasko0ea41032015-06-16 08:53:55 +02004055 while (root.child) {
4056 lyxml_free_elem(module->ctx, root.child);
4057 }
4058
4059 return NULL;
4060}
4061
Radek Krejci76512572015-08-04 09:47:08 +02004062static struct lys_node *
Michal Vaskof02e3742015-08-05 16:27:02 +02004063read_yin_rpc(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
4064 struct unres_schema *unres)
Michal Vasko38d01f72015-06-15 09:41:06 +02004065{
Radek Krejcie0674f82015-06-15 13:58:51 +02004066 struct lyxml_elem *sub, *next, root;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004067 struct lys_node *node = NULL;
Radek Krejci76512572015-08-04 09:47:08 +02004068 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004069 struct lys_node_rpc *rpc;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004070 const char *value;
Michal Vasko38d01f72015-06-15 09:41:06 +02004071 int r;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004072 int c_tpdf = 0, c_ftrs = 0;
Michal Vasko38d01f72015-06-15 09:41:06 +02004073
Radek Krejcie0674f82015-06-15 13:58:51 +02004074 /* init */
4075 memset(&root, 0, sizeof root);
4076
Michal Vasko38d01f72015-06-15 09:41:06 +02004077 rpc = calloc(1, sizeof *rpc);
Radek Krejci76512572015-08-04 09:47:08 +02004078 rpc->nodetype = LYS_RPC;
4079 rpc->prev = (struct lys_node *)rpc;
4080 retval = (struct lys_node *)rpc;
Michal Vasko38d01f72015-06-15 09:41:06 +02004081
Radek Krejci6a113852015-07-03 16:04:20 +02004082 if (read_yin_common(module, parent, retval, yin, OPT_IDENT | OPT_MODULE | OPT_NACMEXT)) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004083 goto error;
4084 }
4085
Radek Krejcia9544502015-08-14 08:24:29 +02004086 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4087
Michal Vasko38d01f72015-06-15 09:41:06 +02004088 /* process rpc's specific children */
4089 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004090 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4091 /* garbage */
4092 lyxml_free_elem(module->ctx, sub);
4093 continue;
4094 }
4095
Michal Vasko38d01f72015-06-15 09:41:06 +02004096 if (!strcmp(sub->name, "input")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004097 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004098 && (rpc->child->nodetype == LYS_INPUT
4099 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004100 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004101 goto error;
4102 }
4103 lyxml_unlink_elem(sub);
4104 lyxml_add_child(&root, sub);
4105 } else if (!strcmp(sub->name, "output")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004106 if (rpc->child
Radek Krejci76512572015-08-04 09:47:08 +02004107 && (rpc->child->nodetype == LYS_INPUT
4108 || (rpc->child->next && rpc->child->next->nodetype == LYS_INPUT))) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004109 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004110 goto error;
4111 }
4112 lyxml_unlink_elem(sub);
4113 lyxml_add_child(&root, sub);
4114
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004115 /* data statements */
Michal Vasko38d01f72015-06-15 09:41:06 +02004116 } else if (!strcmp(sub->name, "grouping")) {
4117 lyxml_unlink_elem(sub);
4118 lyxml_add_child(&root, sub);
4119
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004120 /* array counters */
Michal Vasko38d01f72015-06-15 09:41:06 +02004121 } else if (!strcmp(sub->name, "typedef")) {
4122 c_tpdf++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004123 } else if (!strcmp(sub->name, "if-feature")) {
4124 c_ftrs++;
Michal Vasko38d01f72015-06-15 09:41:06 +02004125 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004126 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Michal Vasko38d01f72015-06-15 09:41:06 +02004127 goto error;
Michal Vasko38d01f72015-06-15 09:41:06 +02004128 }
4129 }
4130
4131 /* middle part - process nodes with cardinality of 0..n except the data nodes */
4132 if (c_tpdf) {
4133 rpc->tpdf = calloc(c_tpdf, sizeof *rpc->tpdf);
4134 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004135 if (c_ftrs) {
4136 rpc->features = calloc(c_ftrs, sizeof *rpc->features);
4137 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004138
Radek Krejci73adb602015-07-02 18:07:40 +02004139 LY_TREE_FOR(yin->child, sub) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004140 if (!strcmp(sub->name, "typedef")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004141 r = fill_yin_typedef(module, retval, sub, &rpc->tpdf[rpc->tpdf_size++], unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004142
4143 if (r) {
4144 goto error;
4145 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004146 } else if (!strcmp(sub->name, "if-feature")) {
4147 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004148 if (unres_add_str(module, unres, &rpc->features[rpc->features_size++], UNRES_IFFEAT, value,
4149 LOGLINE(sub)) == -1) {
4150 goto error;
4151 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004152 }
Michal Vasko38d01f72015-06-15 09:41:06 +02004153 }
4154
Radek Krejci10c760e2015-08-14 14:45:43 +02004155 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004156 goto error;
4157 }
4158
Michal Vasko38d01f72015-06-15 09:41:06 +02004159 /* last part - process data nodes */
4160 LY_TREE_FOR_SAFE(root.child, next, sub) {
4161 if (!strcmp(sub->name, "grouping")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004162 node = read_yin_grouping(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004163 } else if (!strcmp(sub->name, "input")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004164 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004165 } else if (!strcmp(sub->name, "output")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004166 node = read_yin_input_output(module, retval, sub, resolve, unres);
Michal Vasko38d01f72015-06-15 09:41:06 +02004167 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004168 if (!node) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004169 goto error;
4170 }
Radek Krejci73adb602015-07-02 18:07:40 +02004171
4172 lyxml_free_elem(module->ctx, sub);
Michal Vasko38d01f72015-06-15 09:41:06 +02004173 }
4174
Michal Vasko38d01f72015-06-15 09:41:06 +02004175 return retval;
4176
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004177error:
Michal Vasko38d01f72015-06-15 09:41:06 +02004178
Radek Krejci1d82ef62015-08-07 14:44:40 +02004179 lys_node_free(retval);
Michal Vasko3a9abf82015-06-17 10:18:26 +02004180 while (root.child) {
4181 lyxml_free_elem(module->ctx, root.child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004182 }
4183
4184 return NULL;
4185}
4186
Radek Krejci74705112015-06-05 10:25:44 +02004187/*
4188 * resolve - referenced grouping should be bounded to the namespace (resolved)
4189 * only when uses does not appear in grouping. In a case of grouping's uses,
4190 * we just get information but we do not apply augment or refine to it.
4191 */
Radek Krejci76512572015-08-04 09:47:08 +02004192static struct lys_node *
Radek Krejcia9544502015-08-14 08:24:29 +02004193read_yin_uses(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, int resolve,
Michal Vaskof02e3742015-08-05 16:27:02 +02004194 struct unres_schema *unres)
Radek Krejci74705112015-06-05 10:25:44 +02004195{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004196 struct lyxml_elem *sub, *next;
Radek Krejci76512572015-08-04 09:47:08 +02004197 struct lys_node *retval;
Radek Krejcib8048692015-08-05 13:36:34 +02004198 struct lys_node_uses *uses;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004199 const char *value;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004200 int c_ref = 0, c_aug = 0, c_ftrs = 0;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004201 int r;
Radek Krejci74705112015-06-05 10:25:44 +02004202
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004203 uses = calloc(1, sizeof *uses);
Radek Krejci76512572015-08-04 09:47:08 +02004204 uses->nodetype = LYS_USES;
4205 uses->prev = (struct lys_node *)uses;
4206 retval = (struct lys_node *)uses;
Radek Krejci74705112015-06-05 10:25:44 +02004207
Radek Krejcia9544502015-08-14 08:24:29 +02004208 GETVAL(value, yin, "name");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004209 uses->name = lydict_insert(module->ctx, value, 0);
Radek Krejci106efc02015-06-10 14:36:27 +02004210
Radek Krejcia9544502015-08-14 08:24:29 +02004211 if (read_yin_common(module, parent, retval, yin, OPT_MODULE | OPT_NACMEXT | (resolve ? OPT_INHERIT : 0))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004212 goto error;
4213 }
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004214
Radek Krejcia9544502015-08-14 08:24:29 +02004215 LOGDBG("YIN: parsing %s statement \"%s\"", yin->name, retval->name);
4216
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004217 /* get other properties of uses */
Radek Krejcia9544502015-08-14 08:24:29 +02004218 LY_TREE_FOR_SAFE(yin->child, next, sub) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004219 if (!sub->ns || strcmp(sub->ns->value, LY_NSYIN)) {
4220 /* garbage */
4221 lyxml_free_elem(module->ctx, sub);
4222 continue;
4223 }
4224
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004225 if (!strcmp(sub->name, "refine")) {
4226 c_ref++;
4227 } else if (!strcmp(sub->name, "augment")) {
4228 c_aug++;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004229 } else if (!strcmp(sub->name, "if-feature")) {
Radek Krejci56e89772015-06-19 10:00:54 +02004230 c_ftrs++;
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004231 } else if (!strcmp(sub->name, "when")) {
4232 if (uses->when) {
Radek Krejcia9544502015-08-14 08:24:29 +02004233 LOGVAL(LYE_TOOMANY, LOGLINE(sub), sub->name, yin->name);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004234 goto error;
4235 }
4236
4237 uses->when = read_yin_when(module, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004238 if (!uses->when) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004239 lyxml_free_elem(module->ctx, sub);
Radek Krejcib0af6ba2015-06-18 15:01:03 +02004240 goto error;
4241 }
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004242 if (unres_add_node(module, unres, uses->when, UNRES_WHEN, retval, LOGLINE(sub)) == -1) {
4243 goto error;
4244 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004245 lyxml_free_elem(module->ctx, sub);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004246 } else {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004247 LOGVAL(LYE_INSTMT, LOGLINE(sub), sub->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004248 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004249 }
4250 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004251
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004252 /* process properties with cardinality 0..n */
4253 if (c_ref) {
4254 uses->refine = calloc(c_ref, sizeof *uses->refine);
4255 }
4256 if (c_aug) {
4257 uses->augment = calloc(c_aug, sizeof *uses->augment);
4258 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004259 if (c_ftrs) {
4260 uses->features = calloc(c_ftrs, sizeof *uses->features);
4261 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004262
Radek Krejci10c760e2015-08-14 14:45:43 +02004263 if (lys_node_addchild(parent, module, retval)) {
Michal Vasko3a0043f2015-08-12 12:11:30 +02004264 goto error;
4265 }
4266
Radek Krejcia9544502015-08-14 08:24:29 +02004267 LY_TREE_FOR(yin->child, sub) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004268 if (!strcmp(sub->name, "refine")) {
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004269 r = fill_yin_refine(module, sub, &uses->refine[uses->refine_size++], uses, unres);
4270 if (r) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004271 goto error;
4272 }
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004273 } else if (!strcmp(sub->name, "augment")) {
4274 r = fill_yin_augment(module, retval, sub, &uses->augment[uses->augment_size++], unres);
4275 if (r) {
4276 goto error;
4277 }
4278 } else if (!strcmp(sub->name, "if-feature")) {
4279 GETVAL(value, sub, "name");
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004280 if (unres_add_str(module, unres, &uses->features[uses->features_size++], UNRES_IFFEAT, value,
4281 LOGLINE(sub)) == -1) {
4282 goto error;
4283 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004284 }
4285 }
Radek Krejci3bde87f2015-06-05 16:51:58 +02004286
Michal Vasko3ab70fc2015-08-17 14:06:23 +02004287 if (unres_add_node(module, unres, uses, UNRES_USES, NULL, LOGLINE(yin)) == -1) {
4288 goto error;
4289 }
Radek Krejci74705112015-06-05 10:25:44 +02004290
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004291 if (resolve) {
4292 /* inherit config flag */
4293 if (parent) {
Radek Krejci1574a8d2015-08-03 14:16:52 +02004294 retval->flags |= parent->flags & LYS_CONFIG_MASK;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004295 } else {
4296 /* default config is true */
Radek Krejci1574a8d2015-08-03 14:16:52 +02004297 retval->flags |= LYS_CONFIG_W;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004298 }
4299 }
Radek Krejcib388c152015-06-04 17:03:03 +02004300
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004301 return retval;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004302
4303error:
4304
Radek Krejci1d82ef62015-08-07 14:44:40 +02004305 lys_node_free(retval);
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004306
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004307 return NULL;
Radek Krejcic7c9a6c2015-05-25 16:35:06 +02004308}
4309
Radek Krejciefaeba32015-05-27 14:30:57 +02004310/* common code for yin_read_module() and yin_read_submodule() */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004311static int
Michal Vaskof02e3742015-08-05 16:27:02 +02004312read_sub_module(struct lys_module *module, struct lyxml_elem *yin, struct unres_schema *unres)
Radek Krejcida04f4a2015-05-21 12:54:09 +02004313{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004314 struct ly_ctx *ctx = module->ctx;
Radek Krejcib8048692015-08-05 13:36:34 +02004315 struct lys_submodule *submodule = (struct lys_submodule *)module;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004316 struct lyxml_elem *next, *child, *child2, root, grps, rpcs, notifs;
4317 struct lys_node *node = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004318 const char *value;
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004319 int i, r;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004320 int belongsto_flag = 0;
Radek Krejci3cf9e222015-06-18 11:37:50 +02004321 /* counters */
Radek Krejcieb00f512015-07-01 16:44:58 +02004322 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 +02004323
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004324 /* init */
4325 memset(&root, 0, sizeof root);
4326 memset(&grps, 0, sizeof grps);
4327 memset(&rpcs, 0, sizeof rpcs);
Michal Vasko0ea41032015-06-16 08:53:55 +02004328 memset(&notifs, 0, sizeof notifs);
Radek Krejcie0674f82015-06-15 13:58:51 +02004329
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004330 /*
4331 * in the first run, we process elements with cardinality of 1 or 0..1 and
4332 * count elements with cardinality 0..n. Data elements (choices, containers,
4333 * leafs, lists, leaf-lists) are moved aside to be processed last, since we
4334 * need have all top-level and groupings already prepared at that time. In
4335 * the middle loop, we process other elements with carinality of 0..n since
4336 * we need to allocate arrays to store them.
4337 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004338 LY_TREE_FOR_SAFE(yin->child, next, child) {
4339 if (!child->ns || strcmp(child->ns->value, LY_NSYIN)) {
Radek Krejci0d70c372015-07-02 16:23:10 +02004340 /* garbage */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004341 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004342 continue;
4343 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004344
Radek Krejci1d82ef62015-08-07 14:44:40 +02004345 if (!module->type && !strcmp(child->name, "namespace")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004346 if (module->ns) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004347 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004348 goto error;
4349 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004350 GETVAL(value, child, "uri");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004351 module->ns = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004352 lyxml_free_elem(ctx, child);
4353 } else if (!module->type && !strcmp(child->name, "prefix")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004354 if (module->prefix) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004355 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004356 goto error;
4357 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004358 GETVAL(value, child, "value");
4359 if (check_identifier(value, LY_IDENT_PREFIX, LOGLINE(child), module, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004360 goto error;
4361 }
4362 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci1d82ef62015-08-07 14:44:40 +02004363 lyxml_free_elem(ctx, child);
4364 } else if (module->type && !strcmp(child->name, "belongs-to")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004365 if (belongsto_flag) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004366 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004367 goto error;
4368 }
4369 belongsto_flag = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004370 GETVAL(value, child, "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004371 while (submodule->belongsto->type) {
Radek Krejcib8048692015-08-05 13:36:34 +02004372 submodule->belongsto = ((struct lys_submodule *)submodule->belongsto)->belongsto;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004373 }
4374 if (value != submodule->belongsto->name) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004375 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004376 goto error;
4377 }
Radek Krejcif3886932015-06-04 17:36:06 +02004378
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004379 /* get the prefix substatement, start with checks */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004380 if (!child->child) {
4381 LOGVAL(LYE_MISSSTMT2, LOGLINE(child), "prefix", child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004382 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004383 } else if (strcmp(child->child->name, "prefix")) {
4384 LOGVAL(LYE_INSTMT, LOGLINE(child->child), child->child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004385 goto error;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004386 } else if (child->child->next) {
4387 LOGVAL(LYE_INSTMT, LOGLINE(child->child->next), child->child->next->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004388 goto error;
4389 }
4390 /* and now finally get the value */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004391 GETVAL(value, child->child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004392 /* check here differs from a generic prefix check, since this prefix
4393 * don't have to be unique
Michal Vasko38d01f72015-06-15 09:41:06 +02004394 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004395 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(child->child), NULL, NULL)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004396 goto error;
4397 }
4398 module->prefix = lydict_insert(ctx, value, strlen(value));
Radek Krejci0af13872015-05-30 11:50:52 +02004399
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004400 /* we are done with belongs-to */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004401 lyxml_free_elem(ctx, child);
Radek Krejcieb00f512015-07-01 16:44:58 +02004402
4403 /* counters (statements with n..1 cardinality) */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004404 } else if (!strcmp(child->name, "import")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004405 c_imp++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004406 } else if (!strcmp(child->name, "revision")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004407 c_rev++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004408 } else if (!strcmp(child->name, "typedef")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004409 c_tpdf++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004410 } else if (!strcmp(child->name, "identity")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004411 c_ident++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004412 } else if (!strcmp(child->name, "include")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004413 c_inc++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004414 } else if (!strcmp(child->name, "augment")) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004415 c_aug++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004416 } else if (!strcmp(child->name, "feature")) {
Radek Krejci3cf9e222015-06-18 11:37:50 +02004417 c_ftrs++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004418 } else if (!strcmp(child->name, "deviation")) {
Radek Krejcieb00f512015-07-01 16:44:58 +02004419 c_dev++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004420
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004421 /* data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004422 } else if (!strcmp(child->name, "container") ||
4423 !strcmp(child->name, "leaf-list") ||
4424 !strcmp(child->name, "leaf") ||
4425 !strcmp(child->name, "list") ||
4426 !strcmp(child->name, "choice") ||
4427 !strcmp(child->name, "uses") ||
4428 !strcmp(child->name, "anyxml")) {
4429 lyxml_unlink_elem(child);
4430 lyxml_add_child(&root, child);
4431 } else if (!strcmp(child->name, "grouping")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004432 /* keep groupings separated and process them before other data statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004433 lyxml_unlink_elem(child);
4434 lyxml_add_child(&grps, child);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004435
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004436 /* optional statements */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004437 } else if (!strcmp(child->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004438 if (module->dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004439 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004440 goto error;
4441 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004442 module->dsc = read_yin_subnode(ctx, child, "text");
4443 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004444 if (!module->dsc) {
4445 goto error;
4446 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004447 } else if (!strcmp(child->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004448 if (module->ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004449 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004450 goto error;
4451 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004452 module->ref = read_yin_subnode(ctx, child, "text");
4453 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004454 if (!module->ref) {
4455 goto error;
4456 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004457 } else if (!strcmp(child->name, "organization")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004458 if (module->org) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004459 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004460 goto error;
4461 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004462 module->org = read_yin_subnode(ctx, child, "text");
4463 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004464 if (!module->org) {
4465 goto error;
4466 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004467 } else if (!strcmp(child->name, "contact")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004468 if (module->contact) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004469 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004470 goto error;
4471 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004472 module->contact = read_yin_subnode(ctx, child, "text");
4473 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004474 if (!module->contact) {
4475 goto error;
4476 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004477 } else if (!strcmp(child->name, "yang-version")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004478 /* TODO: support YANG 1.1 ? */
4479 if (module->version) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004480 LOGVAL(LYE_TOOMANY, LOGLINE(child), child->name, yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004481 goto error;
4482 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004483 GETVAL(value, child, "value");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004484 if (strcmp(value, "1")) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004485 LOGVAL(LYE_INARG, LOGLINE(child), value, "yang-version");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004486 goto error;
4487 }
4488 module->version = 1;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004489 lyxml_free_elem(ctx, child);
Michal Vasko38d01f72015-06-15 09:41:06 +02004490
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004491 /* rpcs & notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004492 } else if (!strcmp(child->name, "rpc")) {
4493 lyxml_unlink_elem(child);
4494 lyxml_add_child(&rpcs, child);
4495 } else if (!strcmp(child->name, "notification")) {
4496 lyxml_unlink_elem(child);
4497 lyxml_add_child(&notifs, child);
Radek Krejci5166a892015-07-02 16:44:24 +02004498
Radek Krejci1d82ef62015-08-07 14:44:40 +02004499 } else if (!strcmp(child->name, "extension")) {
4500 GETVAL(value, child, "name");
Radek Krejci5166a892015-07-02 16:44:24 +02004501
Radek Krejci6764bb32015-07-03 15:16:04 +02004502 /* we have 2 supported (hardcoded) extensions:
4503 * NACM's default-deny-write and default-deny-all
4504 */
4505 if (strcmp(module->ns, LY_NSNACM) ||
4506 (strcmp(value, "default-deny-write") && strcmp(value, "default-deny-all"))) {
4507 LOGWRN("Not supported \"%s\" extension statement found, ignoring.", value);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004508 lyxml_free_elem(ctx, child);
Radek Krejci6764bb32015-07-03 15:16:04 +02004509 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004510 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004511 LOGVAL(LYE_INSTMT, LOGLINE(child), child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004512 goto error;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004513 }
4514 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004515
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004516 if (!submodule) {
4517 /* check for mandatory statements */
4518 if (!module->ns) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004519 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "namespace", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004520 goto error;
4521 }
4522 if (!module->prefix) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004523 LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), "prefix", "module");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004524 goto error;
4525 }
4526 }
Radek Krejcibb3257d2015-05-21 23:03:51 +02004527
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004528 /* allocate arrays for elements with cardinality of 0..n */
4529 if (c_imp) {
4530 module->imp = calloc(c_imp, sizeof *module->imp);
4531 }
4532 if (c_rev) {
4533 module->rev = calloc(c_rev, sizeof *module->rev);
4534 }
4535 if (c_tpdf) {
4536 module->tpdf = calloc(c_tpdf, sizeof *module->tpdf);
4537 }
4538 if (c_ident) {
4539 module->ident = calloc(c_ident, sizeof *module->ident);
4540 }
4541 if (c_inc) {
4542 module->inc = calloc(c_inc, sizeof *module->inc);
4543 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004544 if (c_aug) {
4545 module->augment = calloc(c_aug, sizeof *module->augment);
4546 }
Radek Krejci3cf9e222015-06-18 11:37:50 +02004547 if (c_ftrs) {
4548 module->features = calloc(c_ftrs, sizeof *module->features);
4549 }
Radek Krejcieb00f512015-07-01 16:44:58 +02004550 if (c_dev) {
4551 module->deviation = calloc(c_dev, sizeof *module->deviation);
4552 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004553
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004554 /* middle part - process nodes with cardinality of 0..n except the data nodes */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004555 LY_TREE_FOR(yin->child, child) {
4556 if (!strcmp(child->name, "import")) {
4557 r = fill_yin_import(module, child, &module->imp[module->imp_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004558 module->imp_size++;
4559 if (r) {
4560 goto error;
4561 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004562
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004563 /* check duplicities in imported modules */
4564 for (i = 0; i < module->imp_size - 1; i++) {
4565 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004566 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004567 goto error;
4568 }
4569 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004570 } else if (!strcmp(child->name, "include")) {
4571 r = fill_yin_include(module, child, &module->inc[module->inc_size]);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004572 module->inc_size++;
4573 if (r) {
4574 goto error;
4575 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004576
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004577 /* check duplications in include submodules */
4578 for (i = 0; i < module->inc_size - 1; i++) {
4579 if (!strcmp(module->inc[i].submodule->name, module->inc[module->inc_size - 1].submodule->name)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004580 LOGVAL(LYE_SPEC, LOGLINE(child), "Importing module \"%s\" repeatedly.",
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004581 module->inc[i].submodule->name);
4582 goto error;
4583 }
4584 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004585 } else if (!strcmp(child->name, "revision")) {
4586 GETVAL(value, child, "date");
4587 if (check_date(value, LOGLINE(child))) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004588 goto error;
4589 }
4590 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4591 /* check uniqueness of the revision date - not required by RFC */
4592 for (i = 0; i < module->rev_size; i++) {
4593 if (!strcmp(value, module->rev[i].date)) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004594 LOGVAL(LYE_INARG, LOGLINE(child), value, child->name);
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004595 LOGVAL(LYE_SPEC, 0, "Revision is not unique.");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004596 }
4597 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004598
Radek Krejci1d82ef62015-08-07 14:44:40 +02004599 LY_TREE_FOR(child->child, child2) {
4600 if (!strcmp(child2->name, "description")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004601 if (module->rev[module->rev_size].dsc) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004602 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004603 goto error;
4604 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004605 module->rev[module->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004606 if (!module->rev[module->rev_size].dsc) {
4607 goto error;
4608 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004609 } else if (!strcmp(child2->name, "reference")) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004610 if (module->rev[module->rev_size].ref) {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004611 LOGVAL(LYE_TOOMANY, LOGLINE(child), child2->name, child->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004612 goto error;
4613 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004614 module->rev[module->rev_size].ref = read_yin_subnode(ctx, child2, "text");
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004615 if (!module->rev[module->rev_size].ref) {
4616 goto error;
4617 }
4618 } else {
Radek Krejci1d82ef62015-08-07 14:44:40 +02004619 LOGVAL(LYE_INSTMT, LOGLINE(child2), child2->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004620 goto error;
4621 }
4622 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004623
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004624 /* keep the latest revision at position 0 */
4625 if (module->rev_size && strcmp(module->rev[module->rev_size].date, module->rev[0].date) > 0) {
4626 /* switch their position */
4627 value = strdup(module->rev[0].date);
4628 memcpy(module->rev[0].date, module->rev[module->rev_size].date, LY_REV_SIZE - 1);
4629 memcpy(module->rev[module->rev_size].date, value, LY_REV_SIZE - 1);
4630 free((char *)value);
Radek Krejcice7fb782015-05-29 16:52:34 +02004631
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004632 if (module->rev[0].dsc != module->rev[module->rev_size].dsc) {
4633 value = module->rev[0].dsc;
4634 module->rev[0].dsc = module->rev[module->rev_size].dsc;
4635 module->rev[module->rev_size].dsc = value;
4636 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004637
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004638 if (module->rev[0].ref != module->rev[module->rev_size].ref) {
4639 value = module->rev[0].ref;
4640 module->rev[0].ref = module->rev[module->rev_size].ref;
4641 module->rev[module->rev_size].ref = value;
4642 }
4643 }
Radek Krejcice7fb782015-05-29 16:52:34 +02004644
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004645 module->rev_size++;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004646 } else if (!strcmp(child->name, "typedef")) {
4647 r = fill_yin_typedef(module, NULL, child, &module->tpdf[module->tpdf_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004648 module->tpdf_size++;
Radek Krejci25d782a2015-05-22 15:03:23 +02004649
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004650 if (r) {
4651 goto error;
4652 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004653 } else if (!strcmp(child->name, "identity")) {
4654 r = fill_yin_identity(module, child, &module->ident[module->ident_size], unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004655 module->ident_size++;
Radek Krejci6793db02015-05-22 17:49:54 +02004656
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004657 if (r) {
4658 goto error;
4659 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004660 } else if (!strcmp(child->name, "feature")) {
4661 r = fill_yin_feature(module, child, &module->features[module->features_size], unres);
Radek Krejci3cf9e222015-06-18 11:37:50 +02004662 module->features_size++;
4663
4664 if (r) {
4665 goto error;
4666 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004667 } else if (!strcmp(child->name, "augment")) {
4668 r = fill_yin_augment(module, NULL, child, &module->augment[module->augment_size], unres);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004669 module->augment_size++;
4670
4671 if (r) {
4672 goto error;
4673 }
4674
4675 /* node is reconnected into the augment, so we have to skip its free at the end of the loop */
4676 continue;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004677 } else if (!strcmp(child->name, "deviation")) {
4678 r = fill_yin_deviation(module, child, &module->deviation[module->deviation_size]);
Radek Krejcieb00f512015-07-01 16:44:58 +02004679 module->deviation_size++;
4680
4681 if (r) {
4682 goto error;
4683 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004684 }
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004685 }
Radek Krejcida04f4a2015-05-21 12:54:09 +02004686
Radek Krejcif5be10f2015-06-16 13:29:36 +02004687 /* process data nodes. Start with groupings to allow uses
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004688 * refer to them
4689 */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004690 LY_TREE_FOR_SAFE(grps.child, next, child) {
4691 node = read_yin_grouping(module, NULL, child, 0, unres);
4692 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004693 goto error;
4694 }
Radek Krejci74705112015-06-05 10:25:44 +02004695
Radek Krejci1d82ef62015-08-07 14:44:40 +02004696 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004697 }
Radek Krejci74705112015-06-05 10:25:44 +02004698
Radek Krejcif5be10f2015-06-16 13:29:36 +02004699 /* parse data nodes, ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004700 LY_TREE_FOR_SAFE(root.child, next, child) {
Radek Krejcida04f4a2015-05-21 12:54:09 +02004701
Radek Krejci1d82ef62015-08-07 14:44:40 +02004702 if (!strcmp(child->name, "container")) {
4703 node = read_yin_container(module, NULL, child, 1, unres);
4704 } else if (!strcmp(child->name, "leaf-list")) {
4705 node = read_yin_leaflist(module, NULL, child, 1, unres);
4706 } else if (!strcmp(child->name, "leaf")) {
4707 node = read_yin_leaf(module, NULL, child, 1, unres);
4708 } else if (!strcmp(child->name, "list")) {
4709 node = read_yin_list(module, NULL, child, 1, unres);
4710 } else if (!strcmp(child->name, "choice")) {
4711 node = read_yin_choice(module, NULL, child, 1, unres);
4712 } else if (!strcmp(child->name, "uses")) {
4713 node = read_yin_uses(module, NULL, child, 1, unres);
4714 } else if (!strcmp(child->name, "anyxml")) {
4715 node = read_yin_anyxml(module, NULL, child, 1, unres);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004716 }
Radek Krejci1d82ef62015-08-07 14:44:40 +02004717 if (!node) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004718 goto error;
4719 }
Radek Krejci25d782a2015-05-22 15:03:23 +02004720
Radek Krejci1d82ef62015-08-07 14:44:40 +02004721 lyxml_free_elem(ctx, child);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004722 }
Radek Krejcif5be10f2015-06-16 13:29:36 +02004723
4724 /* ... rpcs ... */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004725 LY_TREE_FOR_SAFE(rpcs.child, next, child) {
4726 node = read_yin_rpc(module, NULL, child, 0, unres);
4727 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004728 goto error;
4729 }
4730
Radek Krejci1d82ef62015-08-07 14:44:40 +02004731 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004732 }
4733
4734 /* ... and notifications */
Radek Krejci1d82ef62015-08-07 14:44:40 +02004735 LY_TREE_FOR_SAFE(notifs.child, next, child) {
4736 node = read_yin_notif(module, NULL, child, 0, unres);
4737 if (!node) {
Radek Krejcif5be10f2015-06-16 13:29:36 +02004738 goto error;
4739 }
4740
Radek Krejci1d82ef62015-08-07 14:44:40 +02004741 lyxml_free_elem(ctx, child);
Radek Krejcif5be10f2015-06-16 13:29:36 +02004742 }
4743
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004744 return EXIT_SUCCESS;
Radek Krejciefaeba32015-05-27 14:30:57 +02004745
4746error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004747 /* cleanup */
4748 while (root.child) {
4749 lyxml_free_elem(module->ctx, root.child);
4750 }
4751 while (grps.child) {
4752 lyxml_free_elem(module->ctx, grps.child);
4753 }
4754 while (rpcs.child) {
Michal Vasko38d01f72015-06-15 09:41:06 +02004755 lyxml_free_elem(module->ctx, rpcs.child);
4756 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004757
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004758 free(unres->item);
4759 unres->item = NULL;
4760 free(unres->type);
4761 unres->type = NULL;
Radek Krejci1d82ef62015-08-07 14:44:40 +02004762 free(unres->str_snode);
4763 unres->str_snode = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004764#ifndef NDEBUG
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004765 free(unres->line);
4766 unres->line = NULL;
Michal Vaskoc07187d2015-08-13 15:20:57 +02004767#endif
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004768 unres->count = 0;
Radek Krejci8de7b0f2015-07-02 11:43:42 +02004769
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004770 return EXIT_FAILURE;
Radek Krejciefaeba32015-05-27 14:30:57 +02004771}
4772
Radek Krejcib8048692015-08-05 13:36:34 +02004773struct lys_submodule *
Michal Vaskof02e3742015-08-05 16:27:02 +02004774yin_read_submodule(struct lys_module *module, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004775{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004776 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004777 struct lys_submodule *submodule = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004778 const char *value;
Radek Krejciefaeba32015-05-27 14:30:57 +02004779
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004780 assert(module->ctx);
Radek Krejciefaeba32015-05-27 14:30:57 +02004781
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004782 yin = lyxml_read(module->ctx, data, 0);
4783 if (!yin) {
4784 return NULL;
4785 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004786
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004787 /* check root element */
4788 if (!yin->name || strcmp(yin->name, "submodule")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004789 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004790 goto error;
4791 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004792
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004793 GETVAL(value, yin, "name");
4794 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4795 goto error;
4796 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004797
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004798 submodule = calloc(1, sizeof *submodule);
4799 if (!submodule) {
4800 LOGMEM;
4801 goto error;
4802 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004803
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004804 submodule->ctx = module->ctx;
4805 submodule->name = lydict_insert(submodule->ctx, value, strlen(value));
4806 submodule->type = 1;
4807 submodule->belongsto = module;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004808 submodule->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004809
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004810 LOGVRB("reading submodule %s", submodule->name);
Radek Krejcib8048692015-08-05 13:36:34 +02004811 if (read_sub_module((struct lys_module *)submodule, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004812 goto error;
4813 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004814
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004815 /* cleanup */
4816 lyxml_free_elem(module->ctx, yin);
Radek Krejciefaeba32015-05-27 14:30:57 +02004817
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004818 LOGVRB("submodule %s successfully parsed", submodule->name);
Radek Krejciefaeba32015-05-27 14:30:57 +02004819
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004820 return submodule;
Radek Krejciefaeba32015-05-27 14:30:57 +02004821
4822error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004823 /* cleanup */
4824 lyxml_free_elem(module->ctx, yin);
Radek Krejci1d82ef62015-08-07 14:44:40 +02004825 lys_submodule_free(submodule);
Radek Krejciefaeba32015-05-27 14:30:57 +02004826
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004827 return NULL;
Radek Krejciefaeba32015-05-27 14:30:57 +02004828}
4829
Radek Krejcib8048692015-08-05 13:36:34 +02004830struct lys_module *
Michal Vaskof02e3742015-08-05 16:27:02 +02004831yin_read_module(struct ly_ctx *ctx, const char *data, int implement, struct unres_schema *unres)
Radek Krejciefaeba32015-05-27 14:30:57 +02004832{
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004833 struct lyxml_elem *yin;
Radek Krejcib8048692015-08-05 13:36:34 +02004834 struct lys_module *module = NULL, **newlist = NULL;
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004835 const char *value;
4836 int i;
Radek Krejciefaeba32015-05-27 14:30:57 +02004837
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004838 yin = lyxml_read(ctx, data, 0);
4839 if (!yin) {
4840 return NULL;
4841 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004842
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004843 /* check root element */
4844 if (!yin->name || strcmp(yin->name, "module")) {
Michal Vaskoe7fc19c2015-08-05 16:24:39 +02004845 LOGVAL(LYE_INSTMT, LOGLINE(yin), yin->name);
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004846 goto error;
4847 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004848
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004849 GETVAL(value, yin, "name");
4850 if (check_identifier(value, LY_IDENT_NAME, LOGLINE(yin), NULL, NULL)) {
4851 goto error;
4852 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004853
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004854 module = calloc(1, sizeof *module);
4855 if (!module) {
4856 LOGMEM;
4857 goto error;
4858 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004859
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004860 module->ctx = ctx;
4861 module->name = lydict_insert(ctx, value, strlen(value));
4862 module->type = 0;
Michal Vaskod8aa32d2015-07-24 11:50:01 +02004863 module->implemented = (implement ? 1 : 0);
Radek Krejciefaeba32015-05-27 14:30:57 +02004864
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004865 LOGVRB("reading module %s", module->name);
Michal Vaskoc3d9f8c2015-07-31 14:37:24 +02004866 if (read_sub_module(module, yin, unres)) {
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004867 goto error;
4868 }
Radek Krejciefaeba32015-05-27 14:30:57 +02004869
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004870 /* add to the context's list of modules */
4871 if (ctx->models.used == ctx->models.size) {
4872 newlist = realloc(ctx->models.list, ctx->models.size * 2);
4873 if (!newlist) {
4874 LOGMEM;
4875 goto error;
4876 }
4877 for (i = ctx->models.size; i < ctx->models.size * 2; i++) {
4878 newlist[i] = NULL;
4879 }
4880 ctx->models.size *= 2;
4881 ctx->models.list = newlist;
4882 }
4883 for (i = 0; ctx->models.list[i]; i++) {
4884 /* check name (name/revision) and namespace uniqueness */
4885 if (!strcmp(ctx->models.list[i]->name, module->name)) {
Radek Krejci63a91a92015-07-29 13:31:04 +02004886 if (ctx->models.list[i]->rev_size == module->rev_size) {
4887 /* both have the same number of revisions */
4888 if (!module->rev_size || !strcmp(ctx->models.list[i]->rev[0].date, module->rev[0].date)) {
4889 /* both have the same revision -> we already have the same module */
4890 /* so free the new one and update the old one's implement flag if needed */
4891 lyxml_free_elem(ctx, yin);
4892 lys_free(module);
Michal Vaskoaa211572015-08-13 13:55:39 +02004893 unres->count = 0;
Radek Krejci63a91a92015-07-29 13:31:04 +02004894
4895 LOGVRB("module %s already in context", ctx->models.list[i]->name);
4896
4897 if (implement && !ctx->models.list[i]->implemented) {
4898 lyp_set_implemented(ctx->models.list[i]);
4899 }
4900 return ctx->models.list[i];
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004901 }
4902 }
Radek Krejcif647e612015-07-30 11:36:07 +02004903 /* else (both elses) keep searching, for now the caller is just adding
4904 * another revision of an already present schema
4905 */
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004906 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
4907 LOGERR(LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\"",
4908 ctx->models.list[i]->name, module->name, module->ns);
4909 goto error;
4910 }
4911 }
4912 ctx->models.list[i] = module;
4913 ctx->models.used++;
Michal Vasko68cffd72015-08-03 12:50:11 +02004914 ctx->models.module_set_id++;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004915
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004916 /* cleanup */
4917 lyxml_free_elem(ctx, yin);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004918
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004919 LOGVRB("module %s successfully parsed", module->name);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004920
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004921 return module;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004922
4923error:
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004924 /* cleanup */
4925 lyxml_free_elem(ctx, yin);
Radek Krejci912da452015-07-29 14:10:06 +02004926 lys_free(module);
Radek Krejcida04f4a2015-05-21 12:54:09 +02004927
Radek Krejci6e4ffbb2015-06-16 10:34:41 +02004928 return NULL;
Radek Krejcida04f4a2015-05-21 12:54:09 +02004929}