blob: b854993bf0fe3086a548ad88b9a92fb984485b13 [file] [log] [blame]
Pavol Vican021488a2016-01-25 23:56:12 +01001/**
2 * @file parser_yang.c
3 * @author Pavol Vican
4 * @brief YANG parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Pavol Vican9a3a7212016-03-23 10:04:00 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Pavol Vican021488a2016-01-25 23:56:12 +010013 */
14
Pavol Vican5de33492016-02-22 14:03:24 +010015#include <ctype.h>
Pavol Vican021488a2016-01-25 23:56:12 +010016#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010017#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010018#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010019#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010020
Michal Vaskofe7e5a72016-05-02 14:49:23 +020021static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010022yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010023{
Pavol Vicanbf805472016-01-26 14:24:56 +010024 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010025 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010026 free(value);
27 return 1;
28 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010029 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010030 return 0;
31 }
32}
33
Pavol Vican810892e2016-07-12 16:55:34 +020034static int
35yang_check_typedef_identif(struct lys_node *root, struct lys_node *node, char *id)
36{
37 struct lys_node *child, *next;
38 int size;
39 struct lys_tpdf *tpdf;
40
Pavol Vican810892e2016-07-12 16:55:34 +020041 if (root) {
42 node = root;
43 }
44
45 do {
46 LY_TREE_DFS_BEGIN(node, next, child) {
47 if (child->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_GROUPING | LYS_RPC | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
48 switch (child->nodetype) {
49 case LYS_CONTAINER:
50 tpdf = ((struct lys_node_container *)child)->tpdf;
51 size = ((struct lys_node_container *)child)->tpdf_size;
52 break;
53 case LYS_LIST:
54 tpdf = ((struct lys_node_list *)child)->tpdf;
55 size = ((struct lys_node_list *)child)->tpdf_size;
56 break;
57 case LYS_GROUPING:
58 tpdf = ((struct lys_node_grp *)child)->tpdf;
59 size = ((struct lys_node_grp *)child)->tpdf_size;
60 break;
61 case LYS_RPC:
Radek Krejci71d51832016-07-14 15:59:06 +020062 tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
63 size = ((struct lys_node_rpc_action *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020064 break;
65 case LYS_INPUT:
66 case LYS_OUTPUT:
Radek Krejci71d51832016-07-14 15:59:06 +020067 tpdf = ((struct lys_node_inout *)child)->tpdf;
68 size = ((struct lys_node_inout *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020069 break;
70 case LYS_NOTIF:
71 tpdf = ((struct lys_node_notif *)child)->tpdf;
72 size = ((struct lys_node_notif *)child)->tpdf_size;
73 break;
74 default:
75 size = 0;
76 break;
77 }
Radek Krejcifc824a42016-07-14 15:48:38 +020078 if (size && dup_typedef_check(id, tpdf, size)) {
Pavol Vican810892e2016-07-12 16:55:34 +020079 LOGVAL(LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
80 return EXIT_FAILURE;
81 }
Michal Vasko3767fb22016-07-21 12:10:57 +020082 }
Pavol Vican810892e2016-07-12 16:55:34 +020083 LY_TREE_DFS_END(node, next, child)}
84 } while (root && (node = node->next));
85 return EXIT_SUCCESS;
86}
87
Michal Vaskofe7e5a72016-05-02 14:49:23 +020088int
Pavol Vican5f0316a2016-04-05 21:21:11 +020089yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010090{
Pavol Vican6eb14e82016-02-03 12:27:13 +010091 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010092
93 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010094 case MODULE_KEYWORD:
95 module->name = lydict_insert_zc(module->ctx, value);
96 break;
97 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010098 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010099 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100100 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100101 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100102 break;
103 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100104 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100105 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200106 default:
107 free(value);
108 LOGINT;
109 ret = EXIT_FAILURE;
110 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100111 }
112
Pavol Vican021488a2016-01-25 23:56:12 +0100113 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +0100114}
115
Michal Vaskofe7e5a72016-05-02 14:49:23 +0200116int
Pavol Vicand0b64c12016-07-15 09:56:19 +0200117yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
118{
119 int ret = EXIT_SUCCESS;
120
121 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +0200122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
123 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +0200124 } else {
125 if (!strcmp(value, "1")) {
126 if (submodule) {
127 if (module->version > 1) {
128 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
129 ret = EXIT_FAILURE;
130 }
131 } else {
132 module->version = 1;
133 }
134 } else if (!strcmp(value, "1.1")) {
135 if (submodule) {
136 if (module->version != 2) {
137 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
138 ret = EXIT_FAILURE;
139 }
140 } else {
141 module->version = 2;
142 }
143 } else {
144 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
145 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200146 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200147 }
148 free(value);
149 return ret;
150}
151
152int
Pavol Vicane024ab72016-07-27 14:27:43 +0200153yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100154{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100155 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100156
Pavol Vican0adf01d2016-03-22 12:29:33 +0100157 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100158 free(value);
159 return EXIT_FAILURE;
160 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200161
162 if (imp) {
163 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
164 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100166 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100167
Pavol Vicanbf805472016-01-26 14:24:56 +0100168 return ret;
169}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100170
Pavol Vican6eb14e82016-02-03 12:27:13 +0100171int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100173{
Pavol Vican0da132e2016-03-21 12:03:03 +0100174 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200175 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100176
Pavol Vicane024ab72016-07-27 14:27:43 +0200177 if (!imp->prefix) {
178 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
179 return EXIT_FAILURE;
180 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100181 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100182 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +0100183 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200184 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100185 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200186 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100187 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100188
Pavol Vican6eb14e82016-02-03 12:27:13 +0100189 return EXIT_SUCCESS;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100190}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100191
192int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100193yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100194{
195 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100196 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100197
198 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100199 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100200 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100201 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100202 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200203 } else if (!strcmp("import", where)){
204 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
205 } else if (!strcmp("include", where)){
206 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100207 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100208 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100209 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100210 }
211 return ret;
212}
213
214int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100215yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100216{
217 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100218 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100219
220 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100221 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100222 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100223 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100224 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200225 } else if (!strcmp("import", where)){
226 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
227 } else if (!strcmp("include", where)){
228 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100229 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100230 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100231 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100232 }
233 return ret;
234}
Pavol Vicanbedff692016-02-03 14:29:17 +0100235
236void *
237yang_read_revision(struct lys_module *module, char *value)
238{
239 struct lys_revision *retval;
240
Pavol Vican1eeb1992016-02-09 11:10:45 +0100241 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100242
243 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100244 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100245 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
246 memcpy(module->rev[0].date, value, LY_REV_SIZE);
247 retval->dsc = module->rev[0].dsc;
248 retval->ref = module->rev[0].ref;
249 retval = module->rev;
250 retval->dsc = NULL;
251 retval->ref = NULL;
252 } else {
253 memcpy(retval->date, value, LY_REV_SIZE);
254 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100255 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100256 free(value);
257 return retval;
258}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100259
260int
Pavol Vicana1827962016-02-29 15:39:42 +0100261yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100262{
Pavol Vican45ccc592016-03-09 18:53:48 +0100263 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100264 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
265 LOGMEM;
266 return EXIT_FAILURE;
267 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100268 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100269 }
270 }
271 (*size)++;
272 return EXIT_SUCCESS;
273}
Pavol Vicane1354e92016-02-09 14:02:09 +0100274
275void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100276yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100277{
278 struct lys_feature *retval;
279
280 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100281 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100282 goto error;
283 }
284 retval = &module->features[module->features_size];
285 retval->name = lydict_insert_zc(module->ctx, value);
286 retval->module = module;
287 module->features_size++;
288 return retval;
289
290error:
291 free(value);
292 return NULL;
293}
294
295int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200296yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, enum yytokentype type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100297{
298 const char *exp;
299 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100300 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200301 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100302 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200303 struct lys_type_enum *e;
304 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200305 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100306
Michal Vasko97b32be2016-07-25 10:59:53 +0200307 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
309 free(value);
310 return EXIT_FAILURE;
311 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100312
Michal Vasko56d082c2016-10-25 14:00:42 +0200313 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100314 free(value);
315 return EXIT_FAILURE;
316 }
317 free(value);
318
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200319 switch (type) {
320 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100321 f = (struct lys_feature *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200322 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, 1, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200323 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200324 break;
325 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200326 i = (struct lys_ident *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200327 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, 0, unres);
Pavol Vican4df80542016-08-08 09:37:55 +0200328 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200329 break;
330 case ENUM_KEYWORD:
331 e = &((struct yang_type *)ptr)->type->info.enums.enm[((struct yang_type *)ptr)->type->info.enums.count - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200332 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp,
333 (struct lys_node *)((struct yang_type *)ptr)->type->parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200334 e->iffeature_size++;
335 break;
336 case BIT_KEYWORD:
337 b = &((struct yang_type *)ptr)->type->info.bits.bit[((struct yang_type *)ptr)->type->info.bits.count - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200338 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp,
339 (struct lys_node *)((struct yang_type *)ptr)->type->parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200340 b->iffeature_size++;
341 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200342 case REFINE_KEYWORD:
343 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200344 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, 0, unres);
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200345 r->iffeature_size++;
346 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200347 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100348 n = (struct lys_node *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200349 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, 0, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200350 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200351 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100352 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100353 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100354
Radek Krejci9ff0a922016-07-14 13:08:05 +0200355 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100356 return EXIT_FAILURE;
357 }
358 return EXIT_SUCCESS;
359}
360
Pavol Vican4fb66c92016-03-17 10:32:27 +0100361int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200362yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100363{
364 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100365 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100366 return EXIT_FAILURE;
367 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200368 if (shortint) {
369 *((uint8_t *)flags) |= (uint8_t)value;
370 } else {
371 *flags |= value;
372 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100373 return EXIT_SUCCESS;
374 }
375}
376
Pavol Vicanbbdef532016-02-09 14:52:12 +0100377void *
378yang_read_identity(struct lys_module *module, char *value)
379{
380 struct lys_ident *ret;
381
382 ret = &module->ident[module->ident_size];
383 ret->name = lydict_insert_zc(module->ctx, value);
384 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200385 if (dup_identities_check(ret->name, module)) {
386 lydict_remove(module->ctx, ret->name);
387 return NULL;
388 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100389 module->ident_size++;
390 return ret;
391}
392
393int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100394yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100395{
396 const char *exp;
397
Pavol Vican0adf01d2016-03-22 12:29:33 +0100398 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100399 free(value);
400 if (!exp) {
401 return EXIT_FAILURE;
402 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200403
404 /* temporarily decrement identity_size due to resolve base */
405 module->ident_size--;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100406 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100407 lydict_remove(module->ctx, exp);
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200408 /* undo change identity_size */
409 module->ident_size++;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100410 return EXIT_FAILURE;
411 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200412 /* undo change identity_size */
413 module->ident_size++;
Pavol Vican44dde2c2016-02-10 11:18:14 +0100414
Pavol Vicanbbdef532016-02-09 14:52:12 +0100415 lydict_remove(module->ctx, exp);
416 return EXIT_SUCCESS;
417}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100418
419void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200420yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100421{
422 struct lys_restr *retval;
423
424 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100425 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100426 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100427 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200428 case ANYDATA_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100429 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200430 retval = &((struct lys_node_anydata *)node)->must[((struct lys_node_anydata *)node)->must_size++];
Pavol Vican096c6db2016-02-11 15:08:10 +0100431 break;
432 case LEAF_KEYWORD:
433 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100434 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100435 case LEAF_LIST_KEYWORD:
436 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
437 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100438 case LIST_KEYWORD:
439 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
440 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100441 case REFINE_KEYWORD:
442 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
443 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100444 case ADD_KEYWORD:
445 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
446 memset(retval, 0, sizeof *retval);
447 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100448 case DELETE_KEYWORD:
449 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
450 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200451 case NOTIFICATION_KEYWORD:
452 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
453 break;
454 case INPUT_KEYWORD:
455 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
456 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200457 default:
458 goto error;
459 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100460 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100461 retval->expr = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200462 if (!retval->expr) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100463 goto error;
464 }
465 free(value);
466 return retval;
467
468error:
469 free(value);
470 return NULL;
471}
472
473int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100474yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100475{
476 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100477
Pavol Vicandde090a2016-08-30 15:12:14 +0200478 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100479 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100480 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200481 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100482 }
483 return ret;
484}
Pavol Vicanb5687112016-02-09 22:35:59 +0100485
486int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100487yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100488{
489 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100490 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100491 free(value);
492 return EXIT_FAILURE;
493 } else {
494 cont->presence = lydict_insert_zc(module->ctx, value);
495 return EXIT_SUCCESS;
496 }
497}
498
Pavol Vican235dbd42016-02-10 10:34:19 +0100499void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200500yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100501{
502 struct lys_when *retval;
503
504 retval = calloc(1, sizeof *retval);
505 if (!retval) {
506 LOGMEM;
507 free(value);
508 return NULL;
509 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100510 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200511 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100512 goto error;
513 }
514 switch (type) {
515 case CONTAINER_KEYWORD:
516 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100517 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100518 goto error;
519 }
520 ((struct lys_node_container *)node)->when = retval;
521 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200522 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100523 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200524 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200525 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100526 goto error;
527 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200528 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100529 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100530 case CHOICE_KEYWORD:
531 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100532 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100533 goto error;
534 }
535 ((struct lys_node_choice *)node)->when = retval;
536 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100537 case CASE_KEYWORD:
538 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100539 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100540 goto error;
541 }
542 ((struct lys_node_case *)node)->when = retval;
543 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100544 case LEAF_KEYWORD:
545 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100546 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100547 goto error;
548 }
549 ((struct lys_node_leaf *)node)->when = retval;
550 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100551 case LEAF_LIST_KEYWORD:
552 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100553 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100554 goto error;
555 }
556 ((struct lys_node_leaflist *)node)->when = retval;
557 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100558 case LIST_KEYWORD:
559 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100560 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100561 goto error;
562 }
563 ((struct lys_node_list *)node)->when = retval;
564 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100565 case USES_KEYWORD:
566 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100567 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100568 goto error;
569 }
570 ((struct lys_node_uses *)node)->when = retval;
571 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100572 case AUGMENT_KEYWORD:
573 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100574 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100575 goto error;
576 }
577 ((struct lys_node_augment *)node)->when = retval;
578 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200579 default:
580 goto error;
581 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100582 }
583 free(value);
584 return retval;
585
586error:
587 free(value);
588 lys_when_free(module->ctx, retval);
589 return NULL;
590}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100591
592void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100593yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100594{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100595 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100596
Pavol Vican7cadfe72016-02-11 12:33:34 +0100597 node = calloc(1, sizeof_struct);
598 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100599 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100600 LOGMEM;
601 return NULL;
602 }
Pavol Vican531a9132016-03-03 10:10:09 +0100603 if (value) {
604 node->name = lydict_insert_zc(module->ctx, value);
605 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100606 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100607 node->nodetype = nodetype;
608 node->prev = node;
609
610 /* insert the node into the schema tree */
611 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100612 if (value) {
613 lydict_remove(module->ctx, node->name);
614 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100615 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100616 return NULL;
617 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100618 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100619}
620
Pavol Vican8c793992016-07-15 10:44:57 +0200621void *
622yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
623{
624 struct lys_node *node;
625
Michal Vaskobb174852016-07-25 11:00:21 +0200626 if (module->version != 2) {
627 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
628 return NULL;
629 }
630
Pavol Vican8c793992016-07-15 10:44:57 +0200631 for (node = parent; node; node = lys_parent(node)) {
Radek Krejci24681f12016-10-06 10:42:21 +0200632 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vicanbbe77822016-07-15 12:53:07 +0200633 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200634 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
635 return NULL;
636 }
637 }
638 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
639}
640
Pavol Vican8c82fa82016-02-10 13:13:24 +0100641int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200642yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100643{
644 int ret;
645
646 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100647 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100648 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100649 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100650 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100651 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100652 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200653 default:
654 free(value);
655 LOGINT;
656 ret = EXIT_FAILURE;
657 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100658 }
659 return ret;
660}
661
662int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200663yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100664{
665 int ret;
666
667 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100668 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100669 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100670 break;
671 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100672 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100673 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100674 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100675 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100676 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200677 default:
678 free(value);
679 LOGINT;
680 ret = EXIT_FAILURE;
681 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100682 }
683 return ret;
684}
Pavol Vican5de33492016-02-22 14:03:24 +0100685
686int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100687yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100688{
689 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100690 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100691
692 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200693 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100694 while ((value = strpbrk(value, " \t\n"))) {
695 list->keys_size++;
696 while (isspace(*value)) {
697 value++;
698 }
699 }
700 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100701
702 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100703 list->keys = calloc(list->keys_size, sizeof *list->keys);
704 if (!list->keys) {
705 LOGMEM;
Radek Krejci5c08a992016-11-02 13:30:04 +0100706 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100707 }
Radek Krejci5c08a992016-11-02 13:30:04 +0100708 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
709 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
710 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100711 }
Pavol Vican5de33492016-02-22 14:03:24 +0100712 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100713}
714
715int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100716yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres)
Pavol Vican85f12022016-03-05 16:30:35 +0100717{
718 int i, j;
719 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200720 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100721
722 /* count the number of unique leafs in the value */
723 vaux = value;
724 while ((vaux = strpbrk(vaux, " \t\n"))) {
725 unique->expr_size++;
726 while (isspace(*vaux)) {
727 vaux++;
728 }
729 }
730 unique->expr_size++;
731 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
732 if (!unique->expr) {
733 LOGMEM;
734 goto error;
735 }
736
737 for (i = 0; i < unique->expr_size; i++) {
738 vaux = strpbrk(value, " \t\n");
739 if (!vaux) {
740 /* the last token, lydict_insert() will count its size on its own */
741 vaux = value;
742 }
743
744 /* store token into unique structure */
745 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
746
747 /* check that the expression does not repeat */
748 for (j = 0; j < i; j++) {
749 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100750 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
751 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100752 goto error;
753 }
754 }
755 /* try to resolve leaf */
756 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200757 unique_info = malloc(sizeof *unique_info);
758 unique_info->list = (struct lys_node *)list;
759 unique_info->expr = unique->expr[i];
760 unique_info->trg_type = &unique->trg_type;
761 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200762 goto error;
763 }
Pavol Vican85f12022016-03-05 16:30:35 +0100764 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200765 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100766 goto error;
767 }
768 }
769
770 /* move to next token */
771 value = vaux;
772 while(isspace(*value)) {
773 value++;
774 }
775 }
776
777 return EXIT_SUCCESS;
778
779error:
780 return EXIT_FAILURE;
781}
782
783int
Pavol Vican5de33492016-02-22 14:03:24 +0100784yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
785{
786 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100787 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100788
789 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100790 str = (char *)list->unique[k].expr;
791 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100792 goto error;
793 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100794 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100795 }
796 return EXIT_SUCCESS;
797
798error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100799 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100800 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100801}
802
Pavol Vican07f220f2016-09-02 13:04:37 +0200803int
Pavol Vican81344ac2016-09-02 14:23:06 +0200804yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100805{
Pavol Vican81344ac2016-09-02 14:23:06 +0200806 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
807 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
808 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100809 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200810 if (stype->type->info.lref.path) {
811 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
812 goto error;
813 }
814 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
815 stype->base = LY_TYPE_LEAFREF;
816 return EXIT_SUCCESS;
817
818error:
819 free(value);
820 return EXIT_FAILURE;
821}
822
823int
824yang_read_require_instance(struct yang_type *stype, int req)
825{
826 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
827 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
828 return EXIT_FAILURE;
829 }
830 if (stype->type->info.lref.req) {
831 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
832 return EXIT_FAILURE;
833 }
834 stype->type->info.lref.req = req;
835 stype->base = LY_TYPE_LEAFREF;
836 return EXIT_SUCCESS;
837}
838
839int
Pavol Vican07f220f2016-09-02 13:04:37 +0200840yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100841{
Pavol Vican07f220f2016-09-02 13:04:37 +0200842 const char *value;
843 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100844
Pavol Vican07f220f2016-09-02 13:04:37 +0200845 if (stype->base && stype->base != LY_TYPE_IDENT) {
846 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
847 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100848 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200849
850 stype->base = LY_TYPE_IDENT;
851 /* store in the JSON format */
852 value = transform_schema2json(module, expr);
853 free(expr);
854
855 if (!value) {
856 return EXIT_FAILURE;
857 }
858 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100859 lydict_remove(module->ctx, value);
860
861 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200862 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100863 }
864
Pavol Vican07f220f2016-09-02 13:04:37 +0200865 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100866}
867
Pavol Vican73e7c992016-02-24 12:18:05 +0100868int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200869yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100870{
Pavol Vican81344ac2016-09-02 14:23:06 +0200871 int i, j, rc, ret = -1;
872 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100873 const char *name, *value;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100874 LY_DATA_TYPE base = 0, base_tmp;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200875 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200876 struct lys_type *dertype;
877 struct lys_type_enum *enms_sc = NULL;
878 struct lys_type_bit *bits_sc = NULL;
879 struct lys_type_bit bit_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100880 struct yang_type *yang;
Pavol Vican73e7c992016-02-24 12:18:05 +0100881
Pavol Vican0adf01d2016-03-22 12:29:33 +0100882 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100883 if (!value) {
884 goto error;
885 }
886
887 i = parse_identifier(value);
888 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100889 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100890 lydict_remove(module->ctx, value);
891 goto error;
892 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200893 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100894 name = value;
895 if (value[i]) {
896 typ->type->module_name = lydict_insert(module->ctx, value, i);
897 name += i;
898 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100899 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100900 lydict_remove(module->ctx, value);
901 goto error;
902 }
903 ++name;
904 }
905
906 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100907 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100908 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200909 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100910 goto error;
911
Michal Vasko01c6fd22016-05-20 11:43:05 +0200912 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100913 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200914 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200915 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100916 ret = EXIT_FAILURE;
917 goto error;
918 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200919 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200920
Radek Krejci9b6aad22016-09-20 15:55:51 +0200921 if (typ->type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200922 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200923 * unresolved item left inside the grouping, LY_TYPE_ERR used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200924 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
925 if (siter) {
Radek Krejci6ff885d2017-01-03 14:06:22 +0100926#if __BYTE_ORDER == __LITTLE_ENDIAN
927 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]) {
Radek Krejcic13db382016-08-16 10:52:42 +0200928 LOGINT;
929 goto error;
930 }
Radek Krejci6ff885d2017-01-03 14:06:22 +0100931 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[1]--;
932#else
933 if (!((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]) {
934 LOGINT;
935 goto error;
936 }
937 ((uint8_t*)&((struct lys_node_grp *)siter)->flags)[0]--;
938#endif
Radek Krejcic13db382016-08-16 10:52:42 +0200939 } else {
940 LOGINT;
941 goto error;
942 }
943 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200944
945 /* check status */
946 if (lyp_check_status(typ->type->parent->flags, typ->type->parent->module, typ->type->parent->name,
947 typ->type->der->flags, typ->type->der->module, typ->type->der->name, parent)) {
948 goto error;
949 }
950
Pavol Vican8bd72e42016-08-29 09:53:05 +0200951 base = typ->base;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100952 base_tmp = typ->type->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100953 typ->type->base = typ->type->der->type.base;
954 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100955 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100956 }
957 switch (base) {
958 case LY_TYPE_STRING:
959 if (typ->type->base == LY_TYPE_BINARY) {
960 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100961 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100962 goto error;
963 }
964 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100965 if (typ->type->info.binary.length && lyp_check_length_range(typ->type->info.binary.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100966 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100967 goto error;
968 }
969 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100970 if (typ->type->info.str.length && lyp_check_length_range(typ->type->info.str.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100971 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100972 goto error;
973 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100974 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200975 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100976 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100977 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100978 break;
979 case LY_TYPE_DEC64:
980 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100981 /* mandatory sub-statement(s) check */
982 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
983 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100984 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100985 goto error;
986 }
987 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
988 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100989 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100990 goto error;
991 }
Radek Krejci4800f652016-09-08 14:02:52 +0200992
993 /* copy fraction-digits specification from parent type for easier internal use */
994 if (typ->type->der->type.der) {
995 typ->type->info.dec64.dig = typ->type->der->type.info.dec64.dig;
Radek Krejci4800f652016-09-08 14:02:52 +0200996 }
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200997 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
998 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
999 goto error;
1000 }
Pavol Vicanaff5c802016-02-24 15:56:45 +01001001 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
1002 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001003 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001004 goto error;
1005 }
1006 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001007 if (typ->type->info.num.range && lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001008 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001009 goto error;
1010 }
1011 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001012 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +01001013 goto error;
1014 }
1015 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001016 case LY_TYPE_ENUM:
1017 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001018 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001019 goto error;
1020 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001021 dertype = &typ->type->der->type;
1022
1023 if (!dertype->der) {
1024 if (!typ->type->info.enums.count) {
1025 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1026 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
1027 goto error;
1028 }
1029 } else {
1030 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1031 if (module->version < 2 && typ->type->info.enums.count) {
1032 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
1033 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
1034 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
1035 goto error;
1036 }
1037
1038 /* restricted enumeration type - the name MUST be used in the base type */
1039 enms_sc = dertype->info.enums.enm;
1040 for(i = 0; i < typ->type->info.enums.count; i++) {
1041 for (j = 0; j < dertype->info.enums.count; j++) {
1042 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
1043 break;
1044 }
1045 }
1046 if (j == dertype->info.enums.count) {
1047 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1048 goto error;
1049 }
1050
1051 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
1052 /* automatically assign value from base type */
1053 typ->type->info.enums.enm[i].value = enms_sc[j].value;
1054 } else {
1055 /* check that the assigned value corresponds to the original
1056 * value of the enum in the base type */
1057 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
1058 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
1059 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1060 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
1061 typ->type->info.enums.enm[i].name, enms_sc[j].value);
1062 goto error;
1063 }
1064 }
1065 }
Pavol Vican79a763d2016-02-25 15:41:27 +01001066 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001067 break;
Pavol Vican03a59442016-03-21 15:23:45 +01001068 case LY_TYPE_BITS:
1069 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001070 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +01001071 goto error;
1072 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001073 dertype = &typ->type->der->type;
1074
1075 if (!dertype->der) {
1076 if (!typ->type->info.bits.count) {
1077 /* type is derived directly from buit-in bits type and bit statement is required */
1078 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1079 goto error;
1080 }
1081 } else {
1082 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1083 if (module->version < 2 && typ->type->info.bits.count) {
1084 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1085 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1086 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1087 goto error;
1088 }
1089
1090 bits_sc = dertype->info.bits.bit;
1091 for (i = 0; i < typ->type->info.bits.count; i++) {
1092 for (j = 0; j < dertype->info.bits.count; j++) {
1093 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
1094 break;
1095 }
1096 }
1097 if (j == dertype->info.bits.count) {
1098 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1099 goto error;
1100 }
1101
1102 /* restricted bits type */
1103 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1104 /* automatically assign position from base type */
1105 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1106 } else {
1107 /* check that the assigned position corresponds to the original
1108 * position of the bit in the base type */
1109 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1110 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1111 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1112 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1113 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1114 goto error;
1115 }
1116 }
1117 }
Pavol Vican03a59442016-03-21 15:23:45 +01001118 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001119
1120 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1121 j = i;
1122
1123 /* keep them ordered by position */
1124 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1125 /* switch them */
1126 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1127 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1128 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1129 j--;
1130 }
Pavol Vican03a59442016-03-21 15:23:45 +01001131 }
1132 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001133 case LY_TYPE_LEAFREF:
Pavol Vican81344ac2016-09-02 14:23:06 +02001134 if (typ->type->base == LY_TYPE_INST) {
1135 if (typ->type->info.lref.path) {
1136 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +01001137 goto error;
1138 }
Pavol Vican81344ac2016-09-02 14:23:06 +02001139 if ((req = typ->type->info.lref.req)) {
1140 typ->type->info.inst.req = req;
1141 }
Pavol Vican191613a2016-02-26 16:21:32 +01001142 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +02001143 /* require-instance only YANG 1.1 */
1144 if (typ->type->info.lref.req && (module->version < 2)) {
1145 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
1146 goto error;
1147 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001148 /* flag resolving for later use */
1149 if (!tpdftype) {
1150 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1151 if (siter) {
1152 /* just a flag - do not resolve */
1153 tpdftype = 1;
1154 }
1155 }
1156
Pavol Vican6b072512016-04-04 10:50:21 +02001157 if (typ->type->info.lref.path) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001158 if (typ->type->der->type.der) {
1159 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1160 goto error;
1161 }
Pavol Vican191613a2016-02-26 16:21:32 +01001162 value = typ->type->info.lref.path;
1163 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001164 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001165 lydict_remove(module->ctx, value);
1166 if (!typ->type->info.lref.path) {
1167 goto error;
1168 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001169 /* try to resolve leafref path only when this is instantiated
1170 * leaf, so it is not:
1171 * - typedef's type,
1172 * - in grouping definition,
1173 * - just instantiated in a grouping definition,
1174 * because in those cases the nodes referenced in path might not be present
1175 * and it is not a bug. */
1176 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001177 goto error;
1178 }
Pavol Vican6b072512016-04-04 10:50:21 +02001179 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001180 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001181 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001182 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001183 /* copy leafref definition into the derived type */
1184 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1185 /* and resolve the path at the place we are (if not in grouping/typedef) */
1186 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001187 goto error;
1188 }
Radek Krejci742be352016-07-17 12:18:54 +02001189
Radek Krejci3a5501d2016-07-18 22:03:34 +02001190 /* add pointer to leafref target, only on leaves (not in typedefs) */
1191 if (typ->type->info.lref.target && lys_leaf_add_leafref_target(typ->type->info.lref.target, (struct lys_node *)typ->type->parent)) {
1192 goto error;
Radek Krejci742be352016-07-17 12:18:54 +02001193 }
Pavol Vican191613a2016-02-26 16:21:32 +01001194 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001195 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001196 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001197 goto error;
1198 }
1199 break;
1200 case LY_TYPE_IDENT:
Pavol Vican07f220f2016-09-02 13:04:37 +02001201 if (typ->type->base != LY_TYPE_IDENT) {
1202 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001203 goto error;
1204 }
Pavol Vican07f220f2016-09-02 13:04:37 +02001205 if (typ->type->der->type.der) {
1206 if (typ->type->info.ident.ref) {
1207 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1208 goto error;
1209 }
1210 } else {
1211 if (!typ->type->info.ident.ref) {
1212 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1213 goto error;
1214 }
1215 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001216 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001217 case LY_TYPE_UNION:
1218 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001219 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001220 goto error;
1221 }
1222 if (!typ->type->info.uni.types) {
1223 if (typ->type->der->type.der) {
1224 /* this is just a derived type with no additional type specified/required */
1225 break;
1226 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001227 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001228 goto error;
1229 }
1230 for (i = 0; i < typ->type->info.uni.count; i++) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001231 dertype = &typ->type->info.uni.types[i];
1232 if (dertype->base == LY_TYPE_DER || dertype->base == LY_TYPE_ERR) {
1233 yang = (struct yang_type *)dertype->der;
1234 dertype->der = NULL;
1235 if (yang_check_type(module, parent, yang, tpdftype, unres)) {
1236 dertype->der = (struct lys_tpdf *)yang;
1237 ret = EXIT_FAILURE;
1238 typ->type->base = base_tmp;
1239 base = 0;
1240 goto error;
1241 } else {
1242 lydict_remove(module->ctx, yang->name);
1243 free(yang);
1244 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001245 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001246 if (module->version < 2) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001247 if (dertype->base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001248 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1249 goto error;
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001250 } else if (dertype->base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001251 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1252 goto error;
1253 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001254 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001255 if ((dertype->base == LY_TYPE_INST) || (dertype->base == LY_TYPE_LEAFREF)
1256 || ((dertype->base == LY_TYPE_UNION) && dertype->info.uni.has_ptr_type)) {
1257 typ->type->info.uni.has_ptr_type = 1;
1258 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001259 }
1260 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001261
1262 default:
1263 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1264 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001265 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001266 goto error;
1267 }
1268 } else {
1269 LOGINT;
1270 goto error;
1271 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001272 }
1273 return EXIT_SUCCESS;
1274
1275error:
1276 if (typ->type->module_name) {
1277 lydict_remove(module->ctx, typ->type->module_name);
1278 typ->type->module_name = NULL;
1279 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001280 if (base) {
1281 typ->type->base = base;
1282 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001283 return ret;
1284}
1285
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001286void
1287yang_free_type_union(struct ly_ctx *ctx, struct lys_type *type)
1288{
1289 struct lys_type *stype;
1290 struct yang_type *yang;
1291 int i;
1292
1293 for (i = 0; i < type->info.uni.count; ++i) {
1294 stype = &type->info.uni.types[i];
1295 if (stype->base == LY_TYPE_DER || stype->base == LY_TYPE_ERR) {
1296 yang = (struct yang_type *)stype->der;
1297 stype->base = yang->base;
1298 lydict_remove(ctx, yang->name);
1299 free(yang);
1300 } else if (stype->base == LY_TYPE_UNION) {
1301 yang_free_type_union(ctx, stype);
1302 }
1303 }
1304}
1305
Pavol Vican73e7c992016-02-24 12:18:05 +01001306void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001307yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001308{
1309 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001310 struct type_deviation *dev;
1311 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001312
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001313 typ = calloc(1, sizeof *typ);
1314 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001315 LOGMEM;
1316 return NULL;
1317 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001318
1319 typ->flags = LY_YANG_STRUCTURE_FLAG;
1320 switch (type) {
1321 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001322 if (((struct lys_node_leaf *)parent)->type.der) {
1323 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1324 goto error;
1325 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001326 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1327 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1328 typ->type = &((struct lys_node_leaf *)parent)->type;
1329 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001330 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001331 if (((struct lys_node_leaflist *)parent)->type.der) {
1332 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1333 goto error;
1334 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001335 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1336 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1337 typ->type = &((struct lys_node_leaflist *)parent)->type;
1338 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001339 case UNION_KEYWORD:
1340 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1341 typ->type = (struct lys_type *)parent;
1342 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001343 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001344 if (((struct lys_tpdf *)parent)->type.der) {
1345 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1346 goto error;
1347 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001348 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1349 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001350 break;
1351 case REPLACE_KEYWORD:
1352 /* deviation replace type*/
1353 dev = (struct type_deviation *)parent;
1354 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001355 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001356 goto error;
1357 }
1358 /* check target node type */
1359 if (dev->target->nodetype == LYS_LEAF) {
1360 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1361 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1362 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1363 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001364 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1365 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001366 goto error;
1367 }
1368
1369 /* remove type and initialize it */
1370 lys_type_free(module->ctx, typ->type);
1371 tmp_parent = typ->type->parent;
1372 memset(typ->type, 0, sizeof *typ->type);
1373 typ->type->parent = tmp_parent;
1374
1375 /* replace it with the value specified in deviation */
1376 /* HACK for unres */
1377 typ->type->der = (struct lys_tpdf *)typ;
1378 dev->deviate->type = typ->type;
1379 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001380 default:
1381 goto error;
1382 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001383 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001384 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001385 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001386
1387error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001388 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001389 free(typ);
1390 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001391}
1392
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001393void
1394yang_delete_type(struct lys_module *module, struct yang_type *stype)
1395{
1396 int i;
1397
Pavol Vican77a95e52016-08-15 09:49:26 +02001398 if (!stype) {
1399 return;
1400 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001401 stype->type->base = stype->base;
1402 stype->type->der = NULL;
1403 lydict_remove(module->ctx, stype->name);
1404 if (stype->base == LY_TYPE_UNION) {
1405 for (i = 0; i < stype->type->info.uni.count; i++) {
1406 if (stype->type->info.uni.types[i].der) {
1407 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1408 }
1409 }
1410 }
1411 free(stype);
1412}
1413
Pavol Vican73e7c992016-02-24 12:18:05 +01001414void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001415yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001416{
1417 struct lys_restr **length;
1418
Pavol Vican6b072512016-04-04 10:50:21 +02001419 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001420 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001421 typ->base = LY_TYPE_STRING;
1422 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001423 length = &typ->type->info.binary.length;
1424 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001425 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001426 goto error;
1427 }
1428
1429 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001430 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001431 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001432 }
1433 *length = calloc(1, sizeof **length);
1434 if (!*length) {
1435 LOGMEM;
1436 goto error;
1437 }
1438 (*length)->expr = lydict_insert_zc(module->ctx, value);
1439 return *length;
1440
1441error:
1442 free(value);
1443 return NULL;
1444
1445}
Pavol Vican1c203db2016-02-24 14:05:23 +01001446
Pavol Vican6eecf302016-08-10 11:09:05 +02001447int
1448yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001449{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001450 char *buf;
1451 size_t len;
1452
Michal Vasko0aee5c12016-06-17 14:27:26 +02001453 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001454 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001455 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001456 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001457
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001458 len = strlen(value);
1459 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001460
1461 if (!buf) {
1462 LOGMEM;
1463 free(value);
1464 return EXIT_FAILURE;
1465 }
1466
1467 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001468 strcpy(&buf[1], value);
1469 free(value);
1470
Pavol Vican6eecf302016-08-10 11:09:05 +02001471 pattern->expr = lydict_insert_zc(module->ctx, buf);
1472 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001473}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001474
1475void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001476yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001477{
Pavol Vican6b072512016-04-04 10:50:21 +02001478 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001479 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001480 goto error;
1481 }
Pavol Vican6b072512016-04-04 10:50:21 +02001482 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001483 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001484 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001485 goto error;
1486 }
1487 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1488 if (!typ->type->info.dec64.range) {
1489 LOGMEM;
1490 goto error;
1491 }
1492 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1493 return typ->type->info.dec64.range;
1494
1495error:
1496 free(value);
1497 return NULL;
1498}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001499
1500int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001501yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001502{
Pavol Vican6b072512016-04-04 10:50:21 +02001503 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1504 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001505 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001506 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001507 goto error;
1508 }
1509 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001510 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001511 goto error;
1512 }
1513 /* range check */
1514 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001515 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001516 goto error;
1517 }
1518 typ->type->info.dec64.dig = value;
1519 return EXIT_SUCCESS;
1520
1521error:
1522 return EXIT_FAILURE;
1523}
Pavol Vican79a763d2016-02-25 15:41:27 +01001524
1525void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001526yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001527{
1528 struct lys_type_enum *enm;
1529 int i;
1530
Pavol Vicanc6662412016-08-30 08:06:28 +02001531 if (!value[0]) {
1532 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1533 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1534 free(value);
1535 goto error;
1536 }
1537
Pavol Vican79a763d2016-02-25 15:41:27 +01001538 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1539 enm->name = lydict_insert_zc(module->ctx, value);
1540
1541 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1542 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001543 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001544 goto error;
1545 }
1546
1547 /* check the name uniqueness */
1548 for (i = 0; i < typ->type->info.enums.count; i++) {
1549 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001550 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001551 goto error;
1552 }
1553 }
1554
1555 typ->type->info.enums.count++;
1556 return enm;
1557
1558error:
1559 typ->type->info.enums.count++;
1560 return NULL;
1561}
1562
1563int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001564yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001565{
1566 int i, j;
1567
1568 if (!assign) {
1569 /* assign value automatically */
1570 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001571 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001572 goto error;
1573 }
1574 enm->value = *value;
1575 enm->flags |= LYS_AUTOASSIGNED;
1576 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001577 } else if (typ->type->info.enums.enm == enm) {
1578 /* change value, which is assigned automatically, if first enum has value. */
1579 *value = typ->type->info.enums.enm[0].value;
1580 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001581 }
1582
1583 /* check that the value is unique */
1584 j = typ->type->info.enums.count-1;
1585 for (i = 0; i < j; i++) {
1586 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001587 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001588 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1589 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001590 goto error;
1591 }
1592 }
1593
1594 return EXIT_SUCCESS;
1595
1596error:
1597 return EXIT_FAILURE;
1598}
Pavol Vican9887c682016-02-29 11:32:01 +01001599
1600void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001601yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001602{
1603 int i;
1604 struct lys_type_bit *bit;
1605
1606 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001607 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001608 free(value);
1609 goto error;
1610 }
1611 bit->name = lydict_insert_zc(module->ctx, value);
1612
1613 /* check the name uniqueness */
1614 for (i = 0; i < typ->type->info.bits.count; i++) {
1615 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001616 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001617 typ->type->info.bits.count++;
1618 goto error;
1619 }
1620 }
1621 typ->type->info.bits.count++;
1622 return bit;
1623
1624error:
1625 return NULL;
1626}
1627
1628int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001629yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001630{
1631 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001632
1633 if (!assign) {
1634 /* assign value automatically */
1635 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001636 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001637 goto error;
1638 }
1639 bit->pos = (uint32_t)*value;
1640 bit->flags |= LYS_AUTOASSIGNED;
1641 (*value)++;
1642 }
1643
1644 j = typ->type->info.bits.count - 1;
1645 /* check that the value is unique */
1646 for (i = 0; i < j; i++) {
1647 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001648 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name, typ->type->info.bits.bit[i].name);
Pavol Vican9887c682016-02-29 11:32:01 +01001649 goto error;
1650 }
1651 }
1652
Pavol Vican9887c682016-02-29 11:32:01 +01001653 return EXIT_SUCCESS;
1654
1655error:
1656 return EXIT_FAILURE;
1657}
Pavol Vican0df02b02016-03-01 10:28:50 +01001658
1659void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001660yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001661{
1662 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001663 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001664
Pavol Vican810892e2016-07-12 16:55:34 +02001665 root = (parent) ? NULL : lys_main_module(module)->data;
1666 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001667 free(value);
1668 return NULL;
1669 }
Pavol Vican810892e2016-07-12 16:55:34 +02001670
Pavol Vican0df02b02016-03-01 10:28:50 +01001671 if (!parent) {
1672 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001673 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001674 } else {
1675 switch (parent->nodetype) {
1676 case LYS_GROUPING:
1677 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001678 ((struct lys_node_grp *)parent)->tpdf_size++;
1679 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001680 case LYS_CONTAINER:
1681 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1682 ((struct lys_node_container *)parent)->tpdf_size++;
1683 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001684 case LYS_LIST:
1685 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1686 ((struct lys_node_list *)parent)->tpdf_size++;
1687 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001688 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001689 case LYS_ACTION:
1690 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1691 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001692 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001693 case LYS_INPUT:
1694 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001695 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1696 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001697 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001698 case LYS_NOTIF:
1699 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1700 ((struct lys_node_notif *)parent)->tpdf_size++;
1701 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001702 default:
1703 /* another type of nodetype is error*/
1704 LOGINT;
1705 free(value);
1706 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001707 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001708 }
1709
Pavol Vican79436472016-04-04 11:22:02 +02001710 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001711 ret->name = lydict_insert_zc(module->ctx, value);
1712 ret->module = module;
1713 return ret;
1714}
Pavol Vican1003ead2016-03-02 12:24:52 +01001715
1716void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001717yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001718{
1719 struct lys_refine *rfn;
1720
1721 rfn = &uses->refine[uses->refine_size];
1722 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001723 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001724 free(value);
1725 if (!rfn->target_name) {
1726 return NULL;
1727 }
1728 return rfn;
1729}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001730
1731void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001732yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001733{
1734 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001735
1736 if (parent) {
1737 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1738 } else {
1739 aug = &module->augment[module->augment_size];
1740 }
1741 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001742 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001743 free(value);
1744 if (!aug->target_name) {
1745 return NULL;
1746 }
1747 aug->parent = parent;
1748 aug->module = module;
1749 if (parent) {
1750 ((struct lys_node_uses *)parent)->augment_size++;
1751 } else {
1752 module->augment_size++;
1753 }
1754 return aug;
1755}
Pavol Vican220e5a12016-03-03 14:19:43 +01001756
1757void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001758yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001759{
1760 struct lys_node *dev_target = NULL;
1761 struct lys_deviation *dev;
1762 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001763 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001764
Pavol Vican220e5a12016-03-03 14:19:43 +01001765 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001766 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001767 free(value);
1768 if (!dev->target_name) {
1769 goto error;
1770 }
1771
Pavol Vican974377b2016-03-23 00:38:53 +01001772 deviation = calloc(1, sizeof *deviation);
1773 if (!deviation) {
1774 LOGMEM;
1775 goto error;
1776 }
1777
Pavol Vican220e5a12016-03-03 14:19:43 +01001778 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001779 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Pavol Vican220e5a12016-03-03 14:19:43 +01001780 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001781 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001782 goto error;
1783 }
Radek Krejcic4283442016-04-22 09:19:27 +02001784 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001785 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1786 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001787 goto error;
1788 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001789
Pavol Vican220e5a12016-03-03 14:19:43 +01001790 /*save pointer to the deviation and deviated target*/
1791 deviation->deviation = dev;
1792 deviation->target = dev_target;
1793
Pavol Vican38321d02016-08-16 14:56:02 +02001794 deviation->dflt_check = ly_set_new();
1795 if (!deviation->dflt_check) {
1796 LOGMEM;
1797 goto error;
1798 }
1799
Pavol Vican220e5a12016-03-03 14:19:43 +01001800 return deviation;
1801
1802error:
1803 free(deviation);
1804 lydict_remove(module->ctx, dev->target_name);
1805 return NULL;
1806}
Pavol Vican4c90c642016-03-03 15:06:47 +01001807
1808int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001809yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001810{
1811 int i;
1812
1813 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001814 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001815 return EXIT_FAILURE;
1816 }
1817 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1818
1819 /* you cannot remove a key leaf */
1820 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1821 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1822 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001823 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1824 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001825 return EXIT_FAILURE;
1826 }
1827 }
1828 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001829
Pavol Vican4c90c642016-03-03 15:06:47 +01001830 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001831 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001832 dev->deviation->orig_node = dev->target;
1833
1834 dev->deviation->deviate_size = 1;
1835 return EXIT_SUCCESS;
1836}
Pavol Vican85f12022016-03-05 16:30:35 +01001837
1838int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001839yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001840{
1841 struct unres_schema tmp_unres;
1842
1843 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1844 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1845 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001846 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001847 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001848 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1849 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001850 return EXIT_FAILURE;
1851 }
1852
1853 /* store a shallow copy of the original node */
1854 if (!dev->deviation->orig_node) {
1855 memset(&tmp_unres, 0, sizeof tmp_unres);
Radek Krejci6ff885d2017-01-03 14:06:22 +01001856 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001857 /* just to be safe */
1858 if (tmp_unres.count) {
1859 LOGINT;
1860 return EXIT_FAILURE;
1861 }
1862 }
1863
1864 return EXIT_SUCCESS;
1865}
1866
1867int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001868yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001869{
1870 const char **stritem;
1871
1872 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001873 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001874 free(value);
1875 goto error;
1876 }
1877
1878 /* check target node type */
1879 if (dev->target->nodetype == LYS_LEAFLIST) {
1880 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1881 } else if (dev->target->nodetype == LYS_LEAF) {
1882 stritem = &((struct lys_node_leaf *)dev->target)->units;
1883 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001884 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1885 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001886 free(value);
1887 goto error;
1888 }
1889
1890 dev->deviate->units = lydict_insert_zc(ctx, value);
1891
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001892 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1893 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001894 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001895 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1896 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001897 goto error;
1898 }
1899 /* remove current units value of the target */
1900 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001901 } else {
1902 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1903 /* check that there is no current value */
1904 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001905 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1906 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001907 goto error;
1908 }
1909 } else { /* replace */
1910 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001911 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1912 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001913 goto error;
1914 }
1915 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001916 /* remove current units value of the target ... */
1917 lydict_remove(ctx, *stritem);
1918
1919 /* ... and replace it with the value specified in deviation */
1920 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1921 }
1922
Pavol Vican85f12022016-03-05 16:30:35 +01001923 return EXIT_SUCCESS;
1924
1925error:
1926 return EXIT_FAILURE;
1927}
1928
1929int
Pavol Vican974377b2016-03-23 00:38:53 +01001930yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001931{
Pavol Vican85f12022016-03-05 16:30:35 +01001932 /* check target node type */
1933 switch (dev->target->nodetype) {
1934 case LYS_LEAF:
1935 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1936 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1937 break;
1938 case LYS_CONTAINER:
1939 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1940 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1941 break;
1942 case LYS_LEAFLIST:
1943 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1944 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1945 break;
1946 case LYS_LIST:
1947 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1948 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1949 break;
1950 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001951 case LYS_ANYDATA:
1952 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1953 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001954 break;
1955 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001956 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1957 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001958 goto error;
1959 }
1960
Michal Vasko508a50d2016-09-07 14:50:33 +02001961 /* flag will be checked again, clear it for now */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001962 dev->target->flags &= ~LYS_XPATH_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001963
Pavol Vican85f12022016-03-05 16:30:35 +01001964 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1965 /* reallocate the must array of the target */
1966 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1967 if (!dev->deviate->must) {
1968 LOGMEM;
1969 goto error;
1970 }
1971 *dev->trg_must = dev->deviate->must;
1972 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1973 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001974 } else {
1975 /* LY_DEVIATE_DEL */
1976 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1977 if (!dev->deviate->must) {
1978 LOGMEM;
1979 goto error;
1980 }
Pavol Vican85f12022016-03-05 16:30:35 +01001981 }
1982
1983 return EXIT_SUCCESS;
1984
1985error:
1986 return EXIT_FAILURE;
1987}
1988
1989int
Pavol Vican974377b2016-03-23 00:38:53 +01001990yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001991{
Pavol Vican85f12022016-03-05 16:30:35 +01001992 struct lys_node_list *list;
1993
1994 /* check target node type */
1995 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001996 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1997 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001998 goto error;
1999 }
2000
2001 list = (struct lys_node_list *)dev->target;
2002 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2003 /* reallocate the unique array of the target */
2004 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
2005 if (!dev->deviate->unique) {
2006 LOGMEM;
2007 goto error;
2008 }
2009 list->unique = dev->deviate->unique;
2010 dev->deviate->unique = &list->unique[list->unique_size];
2011 dev->deviate->unique_size = c_uniq;
2012 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002013 } else {
2014 /* LY_DEVIATE_DEL */
2015 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
2016 if (!dev->deviate->unique) {
2017 LOGMEM;
2018 goto error;
2019 }
Pavol Vican85f12022016-03-05 16:30:35 +01002020 }
2021
2022 return EXIT_SUCCESS;
2023
2024error:
2025 return EXIT_FAILURE;
2026}
2027
2028int
Pavol Vican38321d02016-08-16 14:56:02 +02002029yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01002030{
Pavol Vican38321d02016-08-16 14:56:02 +02002031 int i;
2032 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01002033
Pavol Vican38321d02016-08-16 14:56:02 +02002034 /* check target node type */
2035 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
2036 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2037 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2038 goto error;
2039 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2040 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2041 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2042 goto error;
2043 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
2044 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2045 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002046 goto error;
2047 }
2048
Pavol Vican38321d02016-08-16 14:56:02 +02002049 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2050 /* check that there is no current value */
2051 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
2052 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
2053 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2054 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002055 goto error;
2056 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002057
Pavol Vican38321d02016-08-16 14:56:02 +02002058 /* check collision with mandatory/min-elements */
2059 if ((dev->target->flags & LYS_MAND_TRUE) ||
2060 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
2061 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
2062 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2063 "Adding the \"default\" statement is forbidden on %s statement.",
2064 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2065 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01002066 }
Pavol Vican38321d02016-08-16 14:56:02 +02002067 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2068 /* check that there was a value before */
2069 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
2070 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
2071 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2072 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2073 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002074 }
Pavol Vican38321d02016-08-16 14:56:02 +02002075 }
2076
2077 if (dev->target->nodetype == LYS_LEAFLIST) {
2078 /* reallocate default list in the target */
2079 llist = (struct lys_node_leaflist *)dev->target;
2080 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2081 /* reallocate (enlarge) the unique array of the target */
2082 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
2083 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2084 /* reallocate (replace) the unique array of the target */
2085 for (i = 0; i < llist->dflt_size; i++) {
2086 lydict_remove(llist->module->ctx, llist->dflt[i]);
2087 }
2088 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
2089 llist->dflt_size = 0;
2090 }
2091 }
2092
2093 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
2094 if (!dev->deviate->dflt) {
2095 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01002096 goto error;
2097 }
2098
2099 return EXIT_SUCCESS;
2100
2101error:
2102 return EXIT_FAILURE;
2103}
2104
2105int
Pavol Vican38321d02016-08-16 14:56:02 +02002106yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
2107{
2108 struct lys_node *node;
2109 struct lys_node_choice *choice;
2110 struct lys_node_leaf *leaf;
2111 struct lys_node_leaflist *llist;
2112 int rc, i;
2113 unsigned int u;
2114 const char *value;
2115
2116 value = lydict_insert_zc(ctx, exp);
2117 u = strlen(value);
2118 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
2119
2120 if (dev->target->nodetype == LYS_CHOICE) {
2121 choice = (struct lys_node_choice *)dev->target;
2122 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2123 if (rc || !node) {
2124 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2125 goto error;
2126 }
2127 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2128 if (!choice->dflt || (choice->dflt != node)) {
2129 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2131 goto error;
2132 }
2133 } else { /* add or replace */
2134 choice->dflt = node;
2135 if (!choice->dflt) {
2136 /* default branch not found */
2137 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2138 goto error;
2139 }
2140 }
2141 } else if (dev->target->nodetype == LYS_LEAF) {
2142 leaf = (struct lys_node_leaf *)dev->target;
2143 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2144 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2145 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2146 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2147 goto error;
2148 }
2149 /* remove value */
2150 lydict_remove(ctx, leaf->dflt);
2151 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01002152 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02002153 } else { /* add (already checked) and replace */
2154 /* remove value */
2155 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01002156 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02002157
2158 /* set new value */
2159 leaf->dflt = lydict_insert(ctx, value, u);
2160
2161 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2162 ly_set_add(dev->dflt_check, dev->target, 0);
2163 }
2164 } else { /* LYS_LEAFLIST */
2165 llist = (struct lys_node_leaflist *)dev->target;
2166 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2167 /* find and remove the value in target list */
2168 for (i = 0; i < llist->dflt_size; i++) {
2169 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2170 /* match, remove the value */
2171 lydict_remove(llist->module->ctx, llist->dflt[i]);
2172 llist->dflt[i] = NULL;
2173 break;
2174 }
2175 }
2176 if (i == llist->dflt_size) {
2177 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2178 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2179 goto error;
2180 }
2181 } else {
2182 /* add or replace, anyway we place items into the deviate's list
2183 which propagates to the target */
2184 /* we just want to check that the value isn't already in the list */
2185 for (i = 0; i < llist->dflt_size; i++) {
2186 if (ly_strequal(llist->dflt[i], value, 1)) {
2187 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2188 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2189 goto error;
2190 }
2191 }
2192 /* store it in target node */
2193 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
2194
2195 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2196 ly_set_add(dev->dflt_check, dev->target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002197 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02002198 }
2199 }
2200
2201 return EXIT_SUCCESS;
2202error:
2203 return EXIT_FAILURE;
2204}
2205
2206
2207int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002208yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002209{
2210 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002211 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002212 goto error;
2213 }
2214
2215 /* for we deviate from RFC 6020 and allow config property even it is/is not
2216 * specified in the target explicitly since config property inherits. So we expect
2217 * that config is specified in every node. But for delete, we check that the value
2218 * is the same as here in deviation
2219 */
2220 dev->deviate->flags |= value;
2221
2222 /* add and replace are the same in this case */
2223 /* remove current config value of the target ... */
2224 dev->target->flags &= ~LYS_CONFIG_MASK;
2225
2226 /* ... and replace it with the value specified in deviation */
2227 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2228
2229 return EXIT_SUCCESS;
2230
2231error:
2232 return EXIT_FAILURE;
2233}
2234
2235int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002236yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002237{
Radek Krejcie00d2312016-08-12 15:27:49 +02002238 struct lys_node *parent;
2239
Pavol Vican85f12022016-03-05 16:30:35 +01002240 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002241 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002242 goto error;
2243 }
2244
2245 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002246 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002247 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2248 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002249 goto error;
2250 }
2251
2252 dev->deviate->flags |= value;
2253
2254 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2255 /* check that there is no current value */
2256 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002257 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2258 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002259 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002260 } else {
2261 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2262 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2263 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2264 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2265 goto error;
2266 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2267 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2268 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2269 goto error;
2270 }
Pavol Vican85f12022016-03-05 16:30:35 +01002271 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002272 } else { /* replace */
2273 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002274 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2275 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002276 goto error;
2277 }
Pavol Vican85f12022016-03-05 16:30:35 +01002278 }
2279
Pavol Vican85f12022016-03-05 16:30:35 +01002280 /* remove current mandatory value of the target ... */
2281 dev->target->flags &= ~LYS_MAND_MASK;
2282
2283 /* ... and replace it with the value specified in deviation */
2284 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2285
Radek Krejcie00d2312016-08-12 15:27:49 +02002286 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2287 for (parent = dev->target->parent;
2288 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2289 parent = parent->parent) {
2290 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2291 /* stop also on presence containers */
2292 break;
2293 }
2294 }
2295 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2296 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2297 if (lyp_check_mandatory_choice(parent)) {
2298 goto error;
2299 }
2300 }
2301
Pavol Vican85f12022016-03-05 16:30:35 +01002302 return EXIT_SUCCESS;
2303
2304error:
2305 return EXIT_FAILURE;
2306}
2307
2308int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002309yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002310{
Pavol Vican09adcc32016-08-25 10:51:36 +02002311 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002312
2313 /* check target node type */
2314 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002315 max = &((struct lys_node_leaflist *)dev->target)->max;
2316 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002317 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002318 max = &((struct lys_node_list *)dev->target)->max;
2319 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002320 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002321 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2322 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
Pavol Vican85f12022016-03-05 16:30:35 +01002323 goto error;
2324 }
2325
2326 if (type) {
2327 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002328 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002329 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002330 } else {
2331 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002332 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002333 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002334 }
2335
2336 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2337 /* check that there is no current value */
2338 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002339 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2340 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002341 goto error;
2342 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002343 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2344 /* unfortunately, there is no way to check reliably that there
2345 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002346 }
2347
2348 /* add (already checked) and replace */
2349 /* set new value specified in deviation */
2350 *ui32val = value;
2351
Pavol Vican09adcc32016-08-25 10:51:36 +02002352 /* check min-elements is smaller than max-elements */
2353 if (*max && *min > *max) {
2354 if (type) {
2355 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2356 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2357 } else {
2358 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2359 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2360 }
2361 goto error;
2362 }
2363
Pavol Vican85f12022016-03-05 16:30:35 +01002364 return EXIT_SUCCESS;
2365
2366error:
2367 return EXIT_FAILURE;
2368}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002369
2370int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002371yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002372{
2373 int i;
2374
2375 /* find must to delete, we are ok with just matching conditions */
2376 for (i = 0; i < *dev->trg_must_size; i++) {
2377 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2378 /* we have a match, free the must structure ... */
2379 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2380 /* ... and maintain the array */
2381 (*dev->trg_must_size)--;
2382 if (i != *dev->trg_must_size) {
2383 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2384 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2385 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2386 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2387 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2388 }
2389 if (!(*dev->trg_must_size)) {
2390 free(*dev->trg_must);
2391 *dev->trg_must = NULL;
2392 } else {
2393 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2394 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2395 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2396 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2397 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2398 }
2399
2400 i = -1; /* set match flag */
2401 break;
2402 }
2403 }
2404 if (i != -1) {
2405 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002406 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2407 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002408 return EXIT_FAILURE;
2409 }
2410
2411 return EXIT_SUCCESS;
2412}
2413
2414int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002415yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002416{
2417 struct lys_node_list *list;
2418 int i, j;
2419
2420 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002421 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002422 dev->deviate->unique_size++;
2423 goto error;
2424 }
2425
2426 /* find unique structures to delete */
2427 for (i = 0; i < list->unique_size; i++) {
2428 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2429 continue;
2430 }
2431
2432 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2433 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2434 break;
2435 }
2436 }
2437
2438 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2439 /* we have a match, free the unique structure ... */
2440 for (j = 0; j < list->unique[i].expr_size; j++) {
2441 lydict_remove(module->ctx, list->unique[i].expr[j]);
2442 }
2443 free(list->unique[i].expr);
2444 /* ... and maintain the array */
2445 list->unique_size--;
2446 if (i != list->unique_size) {
2447 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2448 list->unique[i].expr = list->unique[list->unique_size].expr;
2449 }
2450
2451 if (!list->unique_size) {
2452 free(list->unique);
2453 list->unique = NULL;
2454 } else {
2455 list->unique[list->unique_size].expr_size = 0;
2456 list->unique[list->unique_size].expr = NULL;
2457 }
2458
2459 i = -1; /* set match flag */
2460 break;
2461 }
2462 }
2463 dev->deviate->unique_size++;
2464
2465 if (i != -1) {
2466 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002467 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2468 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002469 goto error;
2470 }
2471
2472 free(value);
2473 return EXIT_SUCCESS;
2474
2475error:
2476 free(value);
2477 return EXIT_FAILURE;
2478}
Pavol Vicane92421d2016-03-08 10:12:33 +01002479
2480int
Pavol Vican38321d02016-08-16 14:56:02 +02002481yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002482{
2483 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002484 unsigned int u;
2485 const char *value, *target_name;
2486 struct lys_node_leaflist *llist;
2487 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002488
Pavol Vican38321d02016-08-16 14:56:02 +02002489 /* now check whether default value, if any, matches the type */
2490 for (u = 0; u < dflt_check->number; ++u) {
2491 value = NULL;
2492 rc = EXIT_SUCCESS;
2493 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2494 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2495 target_name = leaf->name;
Radek Krejci51673202016-11-01 17:00:32 +01002496 value = leaf->dflt;
2497 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Pavol Vican38321d02016-08-16 14:56:02 +02002498 } else { /* LYS_LEAFLIST */
2499 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2500 target_name = llist->name;
2501 for (i = 0; i < llist->dflt_size; i++) {
Radek Krejci51673202016-11-01 17:00:32 +01002502 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2503 (struct lys_node *)(&llist->dflt[i]));
Pavol Vican38321d02016-08-16 14:56:02 +02002504 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002505 value = llist->dflt[i];
Pavol Vicane92421d2016-03-08 10:12:33 +01002506 break;
2507 }
2508 }
2509 }
Pavol Vican38321d02016-08-16 14:56:02 +02002510 if (rc == -1) {
2511 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2512 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2513 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2514 target_name);
2515 return EXIT_FAILURE;
2516 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002517 }
Pavol Vican38321d02016-08-16 14:56:02 +02002518
Pavol Vicane92421d2016-03-08 10:12:33 +01002519 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002520
Pavol Vican9b89dda2016-03-09 15:36:55 +01002521}
2522
2523int
2524yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vicane024ab72016-07-27 14:27:43 +02002525 struct lys_include *inc, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002526{
Pavol Vican9b89dda2016-03-09 15:36:55 +01002527 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002528 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002529 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002530 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002531
Pavol Vican55870412016-03-10 12:36:21 +01002532 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002533 trg = (submodule) ? (struct lys_module *)submodule : module;
Pavol Vicane024ab72016-07-27 14:27:43 +02002534 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002535 if (!rc) {
2536 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002537 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002538 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002539 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002540 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002541 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002542
Pavol Vican55870412016-03-10 12:36:21 +01002543 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002544 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002545}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002546
2547int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002548yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002549{
2550 char *prefix;
2551 char *identif;
2552 const char *ns = NULL;
2553 int i;
2554
Pavol Vicanf4717e62016-03-16 11:30:01 +01002555 /* check to the same pointer */
2556 if (data_node != actual) {
2557 return EXIT_SUCCESS;
2558 }
2559
Pavol Vicana302aa62016-03-17 10:45:35 +01002560 prefix = strdup(value);
2561 if (!prefix) {
2562 LOGMEM;
2563 goto error;
2564 }
2565 /* find prefix anf identificator*/
2566 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002567 if (!identif) {
2568 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2569 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2570 goto error;
2571 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002572 *identif = '\0';
2573 identif++;
2574
Pavol Vicanf4717e62016-03-16 11:30:01 +01002575 for(i = 0; i < module->imp_size; ++i) {
2576 if (!strcmp(module->imp[i].prefix, prefix)) {
2577 ns = module->imp[i].module->ns;
2578 break;
2579 }
2580 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002581 if (!ns && !strcmp(module->prefix, prefix)) {
2582 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2583 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002584 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002585 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002586
2587error:
2588 free(prefix);
2589 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002590}
2591
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002592int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002593store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002594{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002595 struct lys_node *elem;
2596
Pavol Vican1dac40c2016-09-28 11:39:26 +02002597 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2598 if (config_opt == CONFIG_INHERIT_ENABLE) {
2599 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002600 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002601 if (node->parent) {
2602 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002603 } else {
2604 /* default config is true */
2605 node->flags |= LYS_CONFIG_W;
2606 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002607 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002608 /* do we even care about config flags? */
2609 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002610
Pavol Vican1dac40c2016-09-28 11:39:26 +02002611 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2612 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2613 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2614 return EXIT_FAILURE;
2615 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002616 }
2617 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002618
2619 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002620}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002621
Pavol Vican1938d882016-04-10 13:36:31 +02002622static int
2623yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2624 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002625{
2626 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002627 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002628 int ret = EXIT_SUCCESS;
2629
2630 yylex_init(&scanner);
2631 bp = yy_scan_buffer((char *)data, size, scanner);
2632 yy_switch_to_buffer(bp, scanner);
2633 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2634 ret = EXIT_FAILURE;
2635 }
2636 yy_delete_buffer(bp, scanner);
2637 yylex_destroy(scanner);
2638 return ret;
2639}
2640
2641int
2642yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2643{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002644 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002645 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002646 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002647
2648 size_arrays = calloc(1, sizeof *size_arrays);
2649 if (!size_arrays) {
2650 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002651 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002652 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002653 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002654 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2655 if (!ret) {
2656 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002657 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002658 free(size_arrays->node);
2659 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002660 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002661}
2662
2663struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002664yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002665{
2666
Radek Krejci6ff885d2017-01-03 14:06:22 +01002667 struct lys_module *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002668 struct unres_schema *unres = NULL;
2669
2670 unres = calloc(1, sizeof *unres);
2671 if (!unres) {
2672 LOGMEM;
2673 goto error;
2674 }
2675
2676 module = calloc(1, sizeof *module);
2677 if (!module) {
2678 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002679 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002680 }
2681
2682 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002683 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002684 module->type = 0;
2685 module->implemented = (implement ? 1 : 0);
2686
2687 if (yang_parse_mem(module, NULL, unres, data, size)) {
2688 goto error;
2689 }
2690
2691 if (module && unres->count && resolve_unres_schema(module, unres)) {
2692 goto error;
2693 }
2694
2695 if (revision) {
2696 /* check revision of the parsed model */
2697 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2698 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2699 module->name, module->rev[0].date, revision);
2700 goto error;
2701 }
2702 }
2703
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002704 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002705 goto error;
2706 }
2707
Radek Krejci27fe55e2016-09-13 17:13:35 +02002708 if (module->deviation_size && !module->implemented) {
2709 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2710 /* deviations always causes target to be made implemented,
2711 * but augents and leafrefs not, so we have to apply them now */
2712 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002713 goto error;
2714 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002715 }
2716
Pavol Vican8e7110b2016-03-22 17:00:26 +01002717 unres_schema_free(NULL, &unres);
2718 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2719 return module;
2720
2721error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002722 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002723 unres_schema_free(module, &unres);
2724 if (!module || !module->name) {
2725 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002726 if (ly_vecode != LYVE_SUBMODULE) {
2727 LOGERR(ly_errno, "Module parsing failed.");
2728 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002729 return NULL;
2730 }
2731
2732 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002733
2734 lys_sub_module_remove_devs_augs(module);
2735 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002736 return NULL;
2737}
2738
2739struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002740yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002741{
2742 struct lys_submodule *submodule;
2743
2744 submodule = calloc(1, sizeof *submodule);
2745 if (!submodule) {
2746 LOGMEM;
2747 goto error;
2748 }
2749
2750 submodule->ctx = module->ctx;
2751 submodule->type = 1;
2752 submodule->belongsto = module;
2753
2754 if (yang_parse_mem(module, submodule, unres, data, size)) {
2755 goto error;
2756 }
2757
Pavol Vican8e7110b2016-03-22 17:00:26 +01002758 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002759 return submodule;
2760
2761error:
2762 /* cleanup */
2763 unres_schema_free((struct lys_module *)submodule, &unres);
2764
2765 if (!submodule || !submodule->name) {
2766 free(submodule);
2767 LOGERR(ly_errno, "Submodule parsing failed.");
2768 return NULL;
2769 }
2770
2771 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2772
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002773 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2774 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002775 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002776 return NULL;
2777}
Pavol Vican8760bb72016-04-07 09:44:01 +02002778
2779static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002780read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2781{
2782 int k = 0, j;
2783
2784 while (in_index < size) {
2785 if (input[in_index] == ' ') {
2786 k++;
2787 } else if (input[in_index] == '\t') {
2788 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2789 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002790 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2791 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2792 k += 8;
2793 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002794 } else {
2795 break;
2796 }
2797 ++in_index;
2798 if (k >= indent) {
2799 for (j = k - indent; j > 0; --j) {
2800 output[*out_index] = ' ';
Pavol Vicana7bf3372016-12-01 15:58:18 +01002801 if (j > 1) {
2802 ++(*out_index);
2803 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002804 }
2805 break;
2806 }
2807 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002808 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002809}
2810
2811char *
Pavol Vican3f598892016-09-28 15:41:07 +02002812yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2813 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002814
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002815 while (i < size) {
2816 switch (input[i]) {
2817 case '\n':
2818 out_index -= space;
2819 output[out_index] = '\n';
2820 space = 0;
2821 i = read_indent(input, indent, size, i + 1, &out_index, output);
2822 break;
2823 case ' ':
2824 case '\t':
2825 output[out_index] = input[i];
2826 ++space;
2827 break;
2828 case '\\':
2829 if (input[i + 1] == 'n') {
2830 out_index -= space;
2831 output[out_index] = '\n';
2832 space = 0;
2833 i = read_indent(input, indent, size, i + 2, &out_index, output);
2834 } else if (input[i + 1] == 't') {
2835 output[out_index] = '\t';
2836 ++i;
2837 ++space;
2838 } else if (input[i + 1] == '\\') {
2839 output[out_index] = '\\';
2840 ++i;
2841 } else if ((i + 1) != size && input[i + 1] == '"') {
2842 output[out_index] = '"';
2843 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002844 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002845 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002846 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002847 } else {
2848 /* YANG 1.1 backslash must not be followed by any other character */
2849 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002850 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002851 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002852 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002853 break;
2854 default:
2855 output[out_index] = input[i];
2856 space = 0;
2857 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002858 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002859 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002860 ++out_index;
2861 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002862 output[out_index] = '\0';
2863 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002864 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002865 if (!output) {
2866 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002867 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002868 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002869 }
Pavol Vican3f598892016-09-28 15:41:07 +02002870 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002871}