blob: 31b668eb226c132b604bcd3e52ba45963ab29059 [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 Vican7313fc02016-11-14 01:10:31 +010016#include <assert.h>
Pavol Vican021488a2016-01-25 23:56:12 +010017#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010018#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010019#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010020#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010021
Pavol Vican082afd02016-10-25 12:39:15 +020022static void yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size);
23static void yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size);
Pavol Vican7313fc02016-11-14 01:10:31 +010024static int yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node);
25static void free_yang_common(struct lys_module *module);
Pavol Vican082afd02016-10-25 12:39:15 +020026
Michal Vaskofe7e5a72016-05-02 14:49:23 +020027static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010028yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010029{
Pavol Vicanbf805472016-01-26 14:24:56 +010030 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010031 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010032 free(value);
33 return 1;
34 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010035 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010036 return 0;
37 }
38}
39
Michal Vaskofe7e5a72016-05-02 14:49:23 +020040int
Pavol Vican5f0316a2016-04-05 21:21:11 +020041yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010042{
Pavol Vican6eb14e82016-02-03 12:27:13 +010043 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010044
45 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010046 case MODULE_KEYWORD:
47 module->name = lydict_insert_zc(module->ctx, value);
48 break;
49 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010050 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010051 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010052 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010053 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010054 break;
55 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010056 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010057 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020058 default:
59 free(value);
60 LOGINT;
61 ret = EXIT_FAILURE;
62 break;
Pavol Vican2a064652016-02-02 22:54:34 +010063 }
64
Pavol Vican021488a2016-01-25 23:56:12 +010065 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010066}
67
Michal Vaskofe7e5a72016-05-02 14:49:23 +020068int
Pavol Vicand0b64c12016-07-15 09:56:19 +020069yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
70{
71 int ret = EXIT_SUCCESS;
72
73 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +020074 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
75 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +020076 } else {
77 if (!strcmp(value, "1")) {
78 if (submodule) {
79 if (module->version > 1) {
80 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
81 ret = EXIT_FAILURE;
82 }
83 } else {
84 module->version = 1;
85 }
86 } else if (!strcmp(value, "1.1")) {
87 if (submodule) {
88 if (module->version != 2) {
89 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
90 ret = EXIT_FAILURE;
91 }
92 } else {
93 module->version = 2;
94 }
95 } else {
96 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
97 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +020098 }
Pavol Vicand0b64c12016-07-15 09:56:19 +020099 }
100 free(value);
101 return ret;
102}
103
104int
Pavol Vicane024ab72016-07-27 14:27:43 +0200105yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100106{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100107 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100108
Pavol Vican1cc4e192016-10-24 16:38:31 +0200109 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100110 free(value);
111 return EXIT_FAILURE;
112 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200113
114 if (imp) {
115 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
116 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100117 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100118 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100119
Pavol Vicanbf805472016-01-26 14:24:56 +0100120 return ret;
121}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100122
Pavol Vican1cc4e192016-10-24 16:38:31 +0200123static int
124yang_fill_import(struct lys_module *module, struct lys_import *imp_old, struct lys_import *imp_new, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100125{
Pavol Vican0da132e2016-03-21 12:03:03 +0100126 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200127 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100128
Pavol Vican1cc4e192016-10-24 16:38:31 +0200129 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200130 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200131 goto error;
132 } else {
133 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
134 goto error;
135 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200136 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200137 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100138 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200139 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100140 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200141 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100142 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200143 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100144 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100145
Pavol Vican6eb14e82016-02-03 12:27:13 +0100146 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200147
148error:
149 free(value);
150 lydict_remove(module->ctx, imp_old->dsc);
151 lydict_remove(module->ctx, imp_old->ref);
152 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100153}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100154
155int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100156yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100157{
158 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100159 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100160
161 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100162 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100163 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100164 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200166 } else if (!strcmp("import", where)){
167 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
168 } else if (!strcmp("include", where)){
169 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100170 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100171 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100172 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100173 }
174 return ret;
175}
176
177int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100178yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100179{
180 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100181 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100182
183 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100184 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100185 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100186 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100187 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200188 } else if (!strcmp("import", where)){
189 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
190 } else if (!strcmp("include", where)){
191 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100192 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100193 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100194 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100195 }
196 return ret;
197}
Pavol Vicanbedff692016-02-03 14:29:17 +0100198
Pavol Vican866d9912016-10-25 09:13:30 +0200199void
200yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval)
Pavol Vicanbedff692016-02-03 14:29:17 +0100201{
Pavol Vicanbedff692016-02-03 14:29:17 +0100202 /* first member of array is last revision */
Pavol Vican866d9912016-10-25 09:13:30 +0200203 if ((module->rev_size - 1) && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100204 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
205 memcpy(module->rev[0].date, value, LY_REV_SIZE);
206 retval->dsc = module->rev[0].dsc;
207 retval->ref = module->rev[0].ref;
208 retval = module->rev;
209 retval->dsc = NULL;
210 retval->ref = NULL;
211 } else {
212 memcpy(retval->date, value, LY_REV_SIZE);
213 }
Pavol Vicanbedff692016-02-03 14:29:17 +0100214 free(value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100215}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100216
217int
Pavol Vicana1827962016-02-29 15:39:42 +0100218yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100219{
Pavol Vican45ccc592016-03-09 18:53:48 +0100220 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100221 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
222 LOGMEM;
223 return EXIT_FAILURE;
224 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100225 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100226 }
227 }
228 (*size)++;
229 return EXIT_SUCCESS;
230}
Pavol Vicane1354e92016-02-09 14:02:09 +0100231
Pavol Vicane1354e92016-02-09 14:02:09 +0100232int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200233yang_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 +0100234{
235 const char *exp;
236 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100237 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200238 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100239 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200240 struct lys_type_enum *e;
241 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200242 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100243
Michal Vasko97b32be2016-07-25 10:59:53 +0200244 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
245 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
246 free(value);
247 return EXIT_FAILURE;
248 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100249
Michal Vasko56d082c2016-10-25 14:00:42 +0200250 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100251 free(value);
252 return EXIT_FAILURE;
253 }
254 free(value);
255
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200256 switch (type) {
257 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100258 f = (struct lys_feature *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200259 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, 1, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200260 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200261 break;
262 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200263 i = (struct lys_ident *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200264 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, 0, unres);
Pavol Vican4df80542016-08-08 09:37:55 +0200265 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200266 break;
267 case ENUM_KEYWORD:
268 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 +0200269 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp,
270 (struct lys_node *)((struct yang_type *)ptr)->type->parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200271 e->iffeature_size++;
272 break;
273 case BIT_KEYWORD:
274 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 +0200275 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp,
276 (struct lys_node *)((struct yang_type *)ptr)->type->parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200277 b->iffeature_size++;
278 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200279 case REFINE_KEYWORD:
280 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200281 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, 0, unres);
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200282 r->iffeature_size++;
283 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200284 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100285 n = (struct lys_node *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200286 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, 0, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200287 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200288 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100289 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100290 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100291
Radek Krejci9ff0a922016-07-14 13:08:05 +0200292 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100293 return EXIT_FAILURE;
294 }
295 return EXIT_SUCCESS;
296}
297
Pavol Vican4fb66c92016-03-17 10:32:27 +0100298int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200299yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100300{
301 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100302 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100303 return EXIT_FAILURE;
304 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200305 if (shortint) {
306 *((uint8_t *)flags) |= (uint8_t)value;
307 } else {
308 *flags |= value;
309 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100310 return EXIT_SUCCESS;
311 }
312}
313
Pavol Vicanbbdef532016-02-09 14:52:12 +0100314void *
315yang_read_identity(struct lys_module *module, char *value)
316{
317 struct lys_ident *ret;
318
319 ret = &module->ident[module->ident_size];
320 ret->name = lydict_insert_zc(module->ctx, value);
321 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200322 if (dup_identities_check(ret->name, module)) {
323 lydict_remove(module->ctx, ret->name);
324 return NULL;
325 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100326 module->ident_size++;
327 return ret;
328}
329
330int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100331yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100332{
333 const char *exp;
334
Pavol Vican0adf01d2016-03-22 12:29:33 +0100335 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100336 free(value);
337 if (!exp) {
338 return EXIT_FAILURE;
339 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200340
341 /* temporarily decrement identity_size due to resolve base */
342 module->ident_size--;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100343 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100344 lydict_remove(module->ctx, exp);
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200345 /* undo change identity_size */
346 module->ident_size++;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100347 return EXIT_FAILURE;
348 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200349 /* undo change identity_size */
350 module->ident_size++;
Pavol Vican44dde2c2016-02-10 11:18:14 +0100351
Pavol Vicanbbdef532016-02-09 14:52:12 +0100352 lydict_remove(module->ctx, exp);
353 return EXIT_SUCCESS;
354}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100355
356void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200357yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100358{
359 struct lys_restr *retval;
360
361 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100362 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100363 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100364 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200365 case ANYDATA_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100366 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200367 retval = &((struct lys_node_anydata *)node)->must[((struct lys_node_anydata *)node)->must_size++];
Pavol Vican096c6db2016-02-11 15:08:10 +0100368 break;
369 case LEAF_KEYWORD:
370 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100371 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100372 case LEAF_LIST_KEYWORD:
373 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
374 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100375 case LIST_KEYWORD:
376 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
377 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100378 case REFINE_KEYWORD:
379 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
380 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100381 case ADD_KEYWORD:
382 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
383 memset(retval, 0, sizeof *retval);
384 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100385 case DELETE_KEYWORD:
386 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
387 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200388 case NOTIFICATION_KEYWORD:
389 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
390 break;
391 case INPUT_KEYWORD:
392 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
393 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200394 default:
395 goto error;
396 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100397 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100398 retval->expr = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200399 if (!retval->expr) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100400 goto error;
401 }
402 free(value);
403 return retval;
404
405error:
406 free(value);
407 return NULL;
408}
409
410int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100411yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100412{
413 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100414
Pavol Vicandde090a2016-08-30 15:12:14 +0200415 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100416 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100417 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200418 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100419 }
420 return ret;
421}
Pavol Vicanb5687112016-02-09 22:35:59 +0100422
423int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100424yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100425{
426 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100427 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100428 free(value);
429 return EXIT_FAILURE;
430 } else {
431 cont->presence = lydict_insert_zc(module->ctx, value);
432 return EXIT_SUCCESS;
433 }
434}
435
Pavol Vican235dbd42016-02-10 10:34:19 +0100436void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200437yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100438{
439 struct lys_when *retval;
440
441 retval = calloc(1, sizeof *retval);
442 if (!retval) {
443 LOGMEM;
444 free(value);
445 return NULL;
446 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100447 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200448 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100449 goto error;
450 }
451 switch (type) {
452 case CONTAINER_KEYWORD:
453 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100454 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100455 goto error;
456 }
457 ((struct lys_node_container *)node)->when = retval;
458 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200459 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100460 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200461 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200462 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100463 goto error;
464 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200465 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100466 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100467 case CHOICE_KEYWORD:
468 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100469 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100470 goto error;
471 }
472 ((struct lys_node_choice *)node)->when = retval;
473 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100474 case CASE_KEYWORD:
475 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100476 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100477 goto error;
478 }
479 ((struct lys_node_case *)node)->when = retval;
480 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100481 case LEAF_KEYWORD:
482 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100483 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100484 goto error;
485 }
486 ((struct lys_node_leaf *)node)->when = retval;
487 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100488 case LEAF_LIST_KEYWORD:
489 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100490 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100491 goto error;
492 }
493 ((struct lys_node_leaflist *)node)->when = retval;
494 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100495 case LIST_KEYWORD:
496 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100497 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100498 goto error;
499 }
500 ((struct lys_node_list *)node)->when = retval;
501 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100502 case USES_KEYWORD:
503 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100504 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100505 goto error;
506 }
507 ((struct lys_node_uses *)node)->when = retval;
508 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100509 case AUGMENT_KEYWORD:
510 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100511 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100512 goto error;
513 }
514 ((struct lys_node_augment *)node)->when = retval;
515 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200516 default:
517 goto error;
518 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100519 }
520 free(value);
521 return retval;
522
523error:
524 free(value);
525 lys_when_free(module->ctx, retval);
526 return NULL;
527}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100528
529void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100530yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100531{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100532 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100533
Pavol Vican7cadfe72016-02-11 12:33:34 +0100534 node = calloc(1, sizeof_struct);
535 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100536 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100537 LOGMEM;
538 return NULL;
539 }
Pavol Vican531a9132016-03-03 10:10:09 +0100540 if (value) {
541 node->name = lydict_insert_zc(module->ctx, value);
542 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100543 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100544 node->nodetype = nodetype;
545 node->prev = node;
546
547 /* insert the node into the schema tree */
548 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100549 if (value) {
550 lydict_remove(module->ctx, node->name);
551 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100552 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100553 return NULL;
554 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100555 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100556}
557
Pavol Vican8c793992016-07-15 10:44:57 +0200558void *
559yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
560{
561 struct lys_node *node;
562
Michal Vaskobb174852016-07-25 11:00:21 +0200563 if (module->version != 2) {
564 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
565 return NULL;
566 }
567
Pavol Vican8c793992016-07-15 10:44:57 +0200568 for (node = parent; node; node = lys_parent(node)) {
Radek Krejci24681f12016-10-06 10:42:21 +0200569 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vicanbbe77822016-07-15 12:53:07 +0200570 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200571 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
572 return NULL;
573 }
574 }
575 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
576}
577
Pavol Vican8c82fa82016-02-10 13:13:24 +0100578int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200579yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100580{
581 int ret;
582
583 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100584 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100585 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100586 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100587 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100588 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100589 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200590 default:
591 free(value);
592 LOGINT;
593 ret = EXIT_FAILURE;
594 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100595 }
596 return ret;
597}
598
599int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200600yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100601{
602 int ret;
603
604 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100605 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100606 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100607 break;
608 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100609 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100610 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100611 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100612 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100613 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200614 default:
615 free(value);
616 LOGINT;
617 ret = EXIT_FAILURE;
618 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100619 }
620 return ret;
621}
Pavol Vican5de33492016-02-22 14:03:24 +0100622
623int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100624yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100625{
626 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100627 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100628
629 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200630 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100631 while ((value = strpbrk(value, " \t\n"))) {
632 list->keys_size++;
633 while (isspace(*value)) {
634 value++;
635 }
636 }
637 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100638
639 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100640 list->keys = calloc(list->keys_size, sizeof *list->keys);
641 if (!list->keys) {
642 LOGMEM;
Radek Krejci5c08a992016-11-02 13:30:04 +0100643 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100644 }
Radek Krejci5c08a992016-11-02 13:30:04 +0100645 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
646 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
647 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100648 }
Pavol Vican5de33492016-02-22 14:03:24 +0100649 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100650}
651
652int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100653yang_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 +0100654{
655 int i, j;
656 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200657 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100658
659 /* count the number of unique leafs in the value */
660 vaux = value;
661 while ((vaux = strpbrk(vaux, " \t\n"))) {
662 unique->expr_size++;
663 while (isspace(*vaux)) {
664 vaux++;
665 }
666 }
667 unique->expr_size++;
668 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
669 if (!unique->expr) {
670 LOGMEM;
671 goto error;
672 }
673
674 for (i = 0; i < unique->expr_size; i++) {
675 vaux = strpbrk(value, " \t\n");
676 if (!vaux) {
677 /* the last token, lydict_insert() will count its size on its own */
678 vaux = value;
679 }
680
681 /* store token into unique structure */
682 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
683
684 /* check that the expression does not repeat */
685 for (j = 0; j < i; j++) {
686 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100687 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
688 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100689 goto error;
690 }
691 }
692 /* try to resolve leaf */
693 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200694 unique_info = malloc(sizeof *unique_info);
695 unique_info->list = (struct lys_node *)list;
696 unique_info->expr = unique->expr[i];
697 unique_info->trg_type = &unique->trg_type;
698 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200699 goto error;
700 }
Pavol Vican85f12022016-03-05 16:30:35 +0100701 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200702 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100703 goto error;
704 }
705 }
706
707 /* move to next token */
708 value = vaux;
709 while(isspace(*value)) {
710 value++;
711 }
712 }
713
714 return EXIT_SUCCESS;
715
716error:
717 return EXIT_FAILURE;
718}
719
720int
Pavol Vican5de33492016-02-22 14:03:24 +0100721yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
722{
723 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100724 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100725
726 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100727 str = (char *)list->unique[k].expr;
728 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100729 goto error;
730 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100731 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100732 }
733 return EXIT_SUCCESS;
734
735error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100736 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100737 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100738}
739
Pavol Vican07f220f2016-09-02 13:04:37 +0200740int
Pavol Vican81344ac2016-09-02 14:23:06 +0200741yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100742{
Pavol Vican81344ac2016-09-02 14:23:06 +0200743 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
744 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
745 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100746 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200747 if (stype->type->info.lref.path) {
748 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
749 goto error;
750 }
751 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
752 stype->base = LY_TYPE_LEAFREF;
753 return EXIT_SUCCESS;
754
755error:
756 free(value);
757 return EXIT_FAILURE;
758}
759
760int
761yang_read_require_instance(struct yang_type *stype, int req)
762{
763 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
764 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
765 return EXIT_FAILURE;
766 }
767 if (stype->type->info.lref.req) {
768 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
769 return EXIT_FAILURE;
770 }
771 stype->type->info.lref.req = req;
772 stype->base = LY_TYPE_LEAFREF;
773 return EXIT_SUCCESS;
774}
775
776int
Pavol Vican07f220f2016-09-02 13:04:37 +0200777yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100778{
Pavol Vican07f220f2016-09-02 13:04:37 +0200779 const char *value;
780 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100781
Pavol Vican07f220f2016-09-02 13:04:37 +0200782 if (stype->base && stype->base != LY_TYPE_IDENT) {
783 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
784 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100785 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200786
787 stype->base = LY_TYPE_IDENT;
788 /* store in the JSON format */
789 value = transform_schema2json(module, expr);
790 free(expr);
791
792 if (!value) {
793 return EXIT_FAILURE;
794 }
795 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100796 lydict_remove(module->ctx, value);
797
798 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200799 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100800 }
801
Pavol Vican07f220f2016-09-02 13:04:37 +0200802 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100803}
804
Pavol Vican73e7c992016-02-24 12:18:05 +0100805int
Pavol Vican7313fc02016-11-14 01:10:31 +0100806yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct lys_type *type, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100807{
Pavol Vican81344ac2016-09-02 14:23:06 +0200808 int i, j, rc, ret = -1;
809 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100810 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200811 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200812 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200813 struct lys_type *dertype;
814 struct lys_type_enum *enms_sc = NULL;
815 struct lys_type_bit *bits_sc = NULL;
816 struct lys_type_bit bit_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100817
Pavol Vican0adf01d2016-03-22 12:29:33 +0100818 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100819 if (!value) {
820 goto error;
821 }
822
823 i = parse_identifier(value);
824 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100825 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100826 lydict_remove(module->ctx, value);
827 goto error;
828 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200829 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100830 name = value;
831 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100832 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100833 name += i;
834 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100835 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100836 lydict_remove(module->ctx, value);
837 goto error;
838 }
839 ++name;
840 }
841
Pavol Vican7313fc02016-11-14 01:10:31 +0100842 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100843 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100844 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200845 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100846 goto error;
847
Michal Vasko01c6fd22016-05-20 11:43:05 +0200848 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100849 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200850 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200851 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100852 ret = EXIT_FAILURE;
853 goto error;
854 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200855 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200856
Pavol Vican7313fc02016-11-14 01:10:31 +0100857 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200858 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200859 * 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 +0200860 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
861 if (siter) {
862 if (!((struct lys_node_grp *)siter)->nacm) {
863 LOGINT;
864 goto error;
865 }
866 ((struct lys_node_grp *)siter)->nacm--;
867 } else {
868 LOGINT;
869 goto error;
870 }
871 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200872
873 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100874 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
875 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200876 goto error;
877 }
878
Pavol Vican8bd72e42016-08-29 09:53:05 +0200879 base = typ->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100880 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100881 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100882 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100883 }
884 switch (base) {
885 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100886 if (type->base == LY_TYPE_BINARY) {
887 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100888 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100889 goto error;
890 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100891 type->info.binary.length = type->info.str.length;
892 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
893 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100894 goto error;
895 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100896 } else if (type->base == LY_TYPE_STRING) {
897 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
898 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100899 goto error;
900 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100901 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100902 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100903 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100904 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100905 break;
906 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100907 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100908 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100909 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100910 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100911 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100912 goto error;
913 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100914 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100915 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100916 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100917 goto error;
918 }
Radek Krejci4800f652016-09-08 14:02:52 +0200919
920 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100921 if (type->der->type.der) {
922 type->info.dec64.dig = type->der->type.info.dec64.dig;
923 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200924 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100925 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
926 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200927 goto error;
928 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100929 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
930 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100931 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100932 goto error;
933 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100934 type->info.num.range = type->info.dec64.range;
935 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
936 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100937 goto error;
938 }
939 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100940 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100941 goto error;
942 }
943 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100944 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100945 if (type->base != LY_TYPE_ENUM) {
946 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100947 goto error;
948 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100949 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200950
951 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100952 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200953 /* type is derived directly from buit-in enumeartion type and enum statement is required */
954 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
955 goto error;
956 }
957 } else {
958 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100959 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200960 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
961 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
962 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
963 goto error;
964 }
965
966 /* restricted enumeration type - the name MUST be used in the base type */
967 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100968 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200969 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100970 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200971 break;
972 }
973 }
974 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100975 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200976 goto error;
977 }
978
Pavol Vican7313fc02016-11-14 01:10:31 +0100979 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200980 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100981 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200982 } else {
983 /* check that the assigned value corresponds to the original
984 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100985 if (type->info.enums.enm[i].value != enms_sc[j].value) {
986 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200987 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100988 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
989 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200990 goto error;
991 }
992 }
993 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100994 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100995 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100996 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100997 if (type->base != LY_TYPE_BITS) {
998 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100999 goto error;
1000 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001001 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001002
1003 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001004 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001005 /* type is derived directly from buit-in bits type and bit statement is required */
1006 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1007 goto error;
1008 }
1009 } else {
1010 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +01001011 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001012 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1013 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1014 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1015 goto error;
1016 }
1017
1018 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +01001019 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001020 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001021 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001022 break;
1023 }
1024 }
1025 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001026 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001027 goto error;
1028 }
1029
1030 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001031 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001032 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001033 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001034 } else {
1035 /* check that the assigned position corresponds to the original
1036 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001037 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
1038 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001039 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001040 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
1041 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001042 goto error;
1043 }
1044 }
1045 }
Pavol Vican03a59442016-03-21 15:23:45 +01001046 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001047
Pavol Vican7313fc02016-11-14 01:10:31 +01001048 for (i = type->info.bits.count - 1; i > 0; i--) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001049 j = i;
1050
1051 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +01001052 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001053 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +01001054 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
1055 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
1056 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001057 j--;
1058 }
Pavol Vican03a59442016-03-21 15:23:45 +01001059 }
1060 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001061 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +01001062 if (type->base == LY_TYPE_INST) {
1063 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +02001064 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +01001065 goto error;
1066 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001067 if ((req = type->info.lref.req)) {
1068 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +02001069 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001070 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +02001071 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +01001072 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +02001073 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
1074 goto error;
1075 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001076 /* flag resolving for later use */
1077 if (!tpdftype) {
1078 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1079 if (siter) {
1080 /* just a flag - do not resolve */
1081 tpdftype = 1;
1082 }
1083 }
1084
Pavol Vican7313fc02016-11-14 01:10:31 +01001085 if (type->info.lref.path) {
1086 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001087 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1088 goto error;
1089 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001090 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +01001091 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +01001092 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001093 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +01001094 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +01001095 goto error;
1096 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001097 /* try to resolve leafref path only when this is instantiated
1098 * leaf, so it is not:
1099 * - typedef's type,
1100 * - in grouping definition,
1101 * - just instantiated in a grouping definition,
1102 * because in those cases the nodes referenced in path might not be present
1103 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +01001104 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001105 goto error;
1106 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001107 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001108 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001109 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001110 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001111 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001112 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001113 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001114 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001115 goto error;
1116 }
Radek Krejci742be352016-07-17 12:18:54 +02001117
Radek Krejci3a5501d2016-07-18 22:03:34 +02001118 /* add pointer to leafref target, only on leaves (not in typedefs) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001119 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001120 goto error;
Radek Krejci742be352016-07-17 12:18:54 +02001121 }
Pavol Vican191613a2016-02-26 16:21:32 +01001122 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001123 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001124 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001125 goto error;
1126 }
1127 break;
1128 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +01001129 if (type->base != LY_TYPE_IDENT) {
1130 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001131 goto error;
1132 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001133 if (type->der->type.der) {
1134 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001135 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1136 goto error;
1137 }
1138 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001139 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001140 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1141 goto error;
1142 }
1143 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001144 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001145 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +01001146 if (type->base != LY_TYPE_UNION) {
1147 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001148 goto error;
1149 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001150 if (!type->info.uni.types) {
1151 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001152 /* this is just a derived type with no additional type specified/required */
1153 break;
1154 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001155 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001156 goto error;
1157 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001158 for (i = 0; i < type->info.uni.count; i++) {
1159 type->info.uni.types[i].parent = type->parent;
1160 if (unres_schema_add_node(module, unres, &type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001161 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001162 goto error;
1163 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001164 if (module->version < 2) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001165 if (type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001166 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1167 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01001168 } else if (type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001169 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1170 goto error;
1171 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001172 }
1173 }
1174 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001175
1176 default:
1177 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001178 if (type->base != base) {
1179 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001180 goto error;
1181 }
1182 } else {
1183 LOGINT;
1184 goto error;
1185 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001186 }
1187 return EXIT_SUCCESS;
1188
1189error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001190 if (type->module_name) {
1191 lydict_remove(module->ctx, type->module_name);
1192 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001193 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001194 if (base) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001195 type->base = base;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001196 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001197 return ret;
1198}
1199
1200void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001201yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001202{
1203 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001204 struct type_deviation *dev;
1205 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001206
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001207 typ = calloc(1, sizeof *typ);
1208 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001209 LOGMEM;
1210 return NULL;
1211 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001212
1213 typ->flags = LY_YANG_STRUCTURE_FLAG;
1214 switch (type) {
1215 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001216 if (((struct lys_node_leaf *)parent)->type.der) {
1217 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1218 goto error;
1219 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001220 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1221 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1222 typ->type = &((struct lys_node_leaf *)parent)->type;
1223 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001224 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001225 if (((struct lys_node_leaflist *)parent)->type.der) {
1226 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1227 goto error;
1228 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001229 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1230 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1231 typ->type = &((struct lys_node_leaflist *)parent)->type;
1232 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001233 case UNION_KEYWORD:
1234 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1235 typ->type = (struct lys_type *)parent;
1236 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001237 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001238 if (((struct lys_tpdf *)parent)->type.der) {
1239 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1240 goto error;
1241 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001242 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1243 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001244 break;
1245 case REPLACE_KEYWORD:
1246 /* deviation replace type*/
1247 dev = (struct type_deviation *)parent;
1248 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001249 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001250 goto error;
1251 }
1252 /* check target node type */
1253 if (dev->target->nodetype == LYS_LEAF) {
1254 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1255 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1256 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1257 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001258 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1259 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001260 goto error;
1261 }
1262
1263 /* remove type and initialize it */
1264 lys_type_free(module->ctx, typ->type);
1265 tmp_parent = typ->type->parent;
1266 memset(typ->type, 0, sizeof *typ->type);
1267 typ->type->parent = tmp_parent;
1268
1269 /* replace it with the value specified in deviation */
1270 /* HACK for unres */
1271 typ->type->der = (struct lys_tpdf *)typ;
1272 dev->deviate->type = typ->type;
1273 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001274 default:
1275 goto error;
1276 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001277 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001278 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001279 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001280
1281error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001282 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001283 free(typ);
1284 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001285}
1286
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001287void
1288yang_delete_type(struct lys_module *module, struct yang_type *stype)
1289{
1290 int i;
1291
Pavol Vican77a95e52016-08-15 09:49:26 +02001292 if (!stype) {
1293 return;
1294 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001295 stype->type->base = stype->base;
1296 stype->type->der = NULL;
1297 lydict_remove(module->ctx, stype->name);
1298 if (stype->base == LY_TYPE_UNION) {
1299 for (i = 0; i < stype->type->info.uni.count; i++) {
1300 if (stype->type->info.uni.types[i].der) {
1301 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1302 }
1303 }
1304 }
1305 free(stype);
1306}
1307
Pavol Vican73e7c992016-02-24 12:18:05 +01001308void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001309yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001310{
1311 struct lys_restr **length;
1312
Pavol Vican6b072512016-04-04 10:50:21 +02001313 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001314 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001315 typ->base = LY_TYPE_STRING;
1316 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001317 length = &typ->type->info.binary.length;
1318 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001319 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001320 goto error;
1321 }
1322
1323 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001324 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001325 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001326 }
1327 *length = calloc(1, sizeof **length);
1328 if (!*length) {
1329 LOGMEM;
1330 goto error;
1331 }
1332 (*length)->expr = lydict_insert_zc(module->ctx, value);
1333 return *length;
1334
1335error:
1336 free(value);
1337 return NULL;
1338
1339}
Pavol Vican1c203db2016-02-24 14:05:23 +01001340
Pavol Vican6eecf302016-08-10 11:09:05 +02001341int
1342yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001343{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001344 char *buf;
1345 size_t len;
1346
Michal Vasko0aee5c12016-06-17 14:27:26 +02001347 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001348 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001349 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001350 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001351
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001352 len = strlen(value);
1353 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001354
1355 if (!buf) {
1356 LOGMEM;
1357 free(value);
1358 return EXIT_FAILURE;
1359 }
1360
1361 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001362 strcpy(&buf[1], value);
1363 free(value);
1364
Pavol Vican6eecf302016-08-10 11:09:05 +02001365 pattern->expr = lydict_insert_zc(module->ctx, buf);
1366 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001367}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001368
1369void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001370yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001371{
Pavol Vican6b072512016-04-04 10:50:21 +02001372 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001373 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001374 goto error;
1375 }
Pavol Vican6b072512016-04-04 10:50:21 +02001376 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001377 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001378 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001379 goto error;
1380 }
1381 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1382 if (!typ->type->info.dec64.range) {
1383 LOGMEM;
1384 goto error;
1385 }
1386 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1387 return typ->type->info.dec64.range;
1388
1389error:
1390 free(value);
1391 return NULL;
1392}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001393
1394int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001395yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001396{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001397 unsigned int i;
1398
Pavol Vican6b072512016-04-04 10:50:21 +02001399 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1400 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001401 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001402 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001403 goto error;
1404 }
1405 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001406 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001407 goto error;
1408 }
1409 /* range check */
1410 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001411 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001412 goto error;
1413 }
1414 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001415 typ->type->info.dec64.div = 10;
1416 for (i = 1; i < value; i++) {
1417 typ->type->info.dec64.div *= 10;
1418 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001419 return EXIT_SUCCESS;
1420
1421error:
1422 return EXIT_FAILURE;
1423}
Pavol Vican79a763d2016-02-25 15:41:27 +01001424
Pavol Vican874715f2016-10-25 14:52:08 +02001425int
1426yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001427{
Pavol Vican874715f2016-10-25 14:52:08 +02001428 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001429
Pavol Vicanc6662412016-08-30 08:06:28 +02001430 if (!value[0]) {
1431 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1432 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1433 free(value);
1434 goto error;
1435 }
1436
Pavol Vican79a763d2016-02-25 15:41:27 +01001437 enm->name = lydict_insert_zc(module->ctx, value);
1438
1439 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1440 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001441 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001442 goto error;
1443 }
1444
Pavol Vican874715f2016-10-25 14:52:08 +02001445 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001446 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001447 for (i = 0; i < j; i++) {
1448 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[j].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001449 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001450 goto error;
1451 }
1452 }
1453
Pavol Vican874715f2016-10-25 14:52:08 +02001454 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001455
1456error:
Pavol Vican874715f2016-10-25 14:52:08 +02001457 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001458}
1459
1460int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001461yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001462{
1463 int i, j;
1464
1465 if (!assign) {
1466 /* assign value automatically */
1467 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001468 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001469 goto error;
1470 }
1471 enm->value = *value;
1472 enm->flags |= LYS_AUTOASSIGNED;
1473 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001474 } else if (typ->type->info.enums.enm == enm) {
1475 /* change value, which is assigned automatically, if first enum has value. */
1476 *value = typ->type->info.enums.enm[0].value;
1477 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001478 }
1479
1480 /* check that the value is unique */
1481 j = typ->type->info.enums.count-1;
1482 for (i = 0; i < j; i++) {
1483 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001484 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001485 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1486 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001487 goto error;
1488 }
1489 }
1490
1491 return EXIT_SUCCESS;
1492
1493error:
1494 return EXIT_FAILURE;
1495}
Pavol Vican9887c682016-02-29 11:32:01 +01001496
Pavol Vican59e8dee2016-10-25 15:29:38 +02001497int
1498yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001499{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001500 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001501
Pavol Vican59e8dee2016-10-25 15:29:38 +02001502 bit->name = lydict_insert_zc(module->ctx, value);
1503 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001504 free(value);
1505 goto error;
1506 }
Pavol Vican9887c682016-02-29 11:32:01 +01001507
Pavol Vican59e8dee2016-10-25 15:29:38 +02001508 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001509 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001510 for (i = 0; i < j; i++) {
Pavol Vican9887c682016-02-29 11:32:01 +01001511 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001512 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001513 goto error;
1514 }
1515 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001516 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001517
1518error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001519 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001520}
1521
1522int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001523yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001524{
1525 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001526
1527 if (!assign) {
1528 /* assign value automatically */
1529 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001530 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001531 goto error;
1532 }
1533 bit->pos = (uint32_t)*value;
1534 bit->flags |= LYS_AUTOASSIGNED;
1535 (*value)++;
1536 }
1537
1538 j = typ->type->info.bits.count - 1;
1539 /* check that the value is unique */
1540 for (i = 0; i < j; i++) {
1541 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001542 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 +01001543 goto error;
1544 }
1545 }
1546
Pavol Vican9887c682016-02-29 11:32:01 +01001547 return EXIT_SUCCESS;
1548
1549error:
1550 return EXIT_FAILURE;
1551}
Pavol Vican0df02b02016-03-01 10:28:50 +01001552
1553void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001554yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001555{
1556 struct lys_refine *rfn;
1557
1558 rfn = &uses->refine[uses->refine_size];
1559 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001560 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001561 free(value);
1562 if (!rfn->target_name) {
1563 return NULL;
1564 }
1565 return rfn;
1566}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001567
1568void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001569yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001570{
1571 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001572
1573 if (parent) {
1574 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1575 } else {
1576 aug = &module->augment[module->augment_size];
1577 }
1578 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001579 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001580 free(value);
1581 if (!aug->target_name) {
1582 return NULL;
1583 }
1584 aug->parent = parent;
1585 aug->module = module;
1586 if (parent) {
1587 ((struct lys_node_uses *)parent)->augment_size++;
1588 } else {
1589 module->augment_size++;
1590 }
1591 return aug;
1592}
Pavol Vican220e5a12016-03-03 14:19:43 +01001593
1594void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001595yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001596{
1597 struct lys_node *dev_target = NULL;
1598 struct lys_deviation *dev;
1599 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001600 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001601
Pavol Vican220e5a12016-03-03 14:19:43 +01001602 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001603 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001604 free(value);
1605 if (!dev->target_name) {
1606 goto error;
1607 }
1608
Pavol Vican974377b2016-03-23 00:38:53 +01001609 deviation = calloc(1, sizeof *deviation);
1610 if (!deviation) {
1611 LOGMEM;
1612 goto error;
1613 }
1614
Pavol Vican220e5a12016-03-03 14:19:43 +01001615 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001616 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Pavol Vican220e5a12016-03-03 14:19:43 +01001617 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001618 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001619 goto error;
1620 }
Radek Krejcic4283442016-04-22 09:19:27 +02001621 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001622 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1623 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001624 goto error;
1625 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001626
Pavol Vican220e5a12016-03-03 14:19:43 +01001627 /*save pointer to the deviation and deviated target*/
1628 deviation->deviation = dev;
1629 deviation->target = dev_target;
1630
Pavol Vican38321d02016-08-16 14:56:02 +02001631 deviation->dflt_check = ly_set_new();
1632 if (!deviation->dflt_check) {
1633 LOGMEM;
1634 goto error;
1635 }
1636
Pavol Vican220e5a12016-03-03 14:19:43 +01001637 return deviation;
1638
1639error:
1640 free(deviation);
1641 lydict_remove(module->ctx, dev->target_name);
1642 return NULL;
1643}
Pavol Vican4c90c642016-03-03 15:06:47 +01001644
1645int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001646yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001647{
1648 int i;
1649
1650 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001651 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001652 return EXIT_FAILURE;
1653 }
1654 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1655
1656 /* you cannot remove a key leaf */
1657 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1658 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1659 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001660 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1661 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001662 return EXIT_FAILURE;
1663 }
1664 }
1665 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001666
Pavol Vican4c90c642016-03-03 15:06:47 +01001667 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001668 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001669 dev->deviation->orig_node = dev->target;
1670
1671 dev->deviation->deviate_size = 1;
1672 return EXIT_SUCCESS;
1673}
Pavol Vican85f12022016-03-05 16:30:35 +01001674
1675int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001676yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001677{
1678 struct unres_schema tmp_unres;
1679
1680 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1681 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1682 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001683 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001684 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001685 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001687 return EXIT_FAILURE;
1688 }
1689
1690 /* store a shallow copy of the original node */
1691 if (!dev->deviation->orig_node) {
1692 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001693 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001694 /* just to be safe */
1695 if (tmp_unres.count) {
1696 LOGINT;
1697 return EXIT_FAILURE;
1698 }
1699 }
1700
1701 return EXIT_SUCCESS;
1702}
1703
1704int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001705yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001706{
1707 const char **stritem;
1708
1709 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001710 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001711 free(value);
1712 goto error;
1713 }
1714
1715 /* check target node type */
1716 if (dev->target->nodetype == LYS_LEAFLIST) {
1717 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1718 } else if (dev->target->nodetype == LYS_LEAF) {
1719 stritem = &((struct lys_node_leaf *)dev->target)->units;
1720 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001723 free(value);
1724 goto error;
1725 }
1726
1727 dev->deviate->units = lydict_insert_zc(ctx, value);
1728
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001729 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1730 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001731 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001732 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1733 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001734 goto error;
1735 }
1736 /* remove current units value of the target */
1737 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001738 } else {
1739 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1740 /* check that there is no current value */
1741 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001742 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1743 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001744 goto error;
1745 }
1746 } else { /* replace */
1747 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001748 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1749 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001750 goto error;
1751 }
1752 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001753 /* remove current units value of the target ... */
1754 lydict_remove(ctx, *stritem);
1755
1756 /* ... and replace it with the value specified in deviation */
1757 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1758 }
1759
Pavol Vican85f12022016-03-05 16:30:35 +01001760 return EXIT_SUCCESS;
1761
1762error:
1763 return EXIT_FAILURE;
1764}
1765
1766int
Pavol Vican974377b2016-03-23 00:38:53 +01001767yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001768{
Pavol Vican85f12022016-03-05 16:30:35 +01001769 /* check target node type */
1770 switch (dev->target->nodetype) {
1771 case LYS_LEAF:
1772 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1773 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1774 break;
1775 case LYS_CONTAINER:
1776 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1777 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1778 break;
1779 case LYS_LEAFLIST:
1780 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1781 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1782 break;
1783 case LYS_LIST:
1784 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1785 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1786 break;
1787 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001788 case LYS_ANYDATA:
1789 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1790 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001791 break;
1792 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001793 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1794 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001795 goto error;
1796 }
1797
Michal Vasko508a50d2016-09-07 14:50:33 +02001798 /* flag will be checked again, clear it for now */
Michal Vaskoe9914d12016-10-07 14:32:37 +02001799 dev->target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001800
Pavol Vican85f12022016-03-05 16:30:35 +01001801 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1802 /* reallocate the must array of the target */
1803 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1804 if (!dev->deviate->must) {
1805 LOGMEM;
1806 goto error;
1807 }
1808 *dev->trg_must = dev->deviate->must;
1809 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1810 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001811 } else {
1812 /* LY_DEVIATE_DEL */
1813 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1814 if (!dev->deviate->must) {
1815 LOGMEM;
1816 goto error;
1817 }
Pavol Vican85f12022016-03-05 16:30:35 +01001818 }
1819
1820 return EXIT_SUCCESS;
1821
1822error:
1823 return EXIT_FAILURE;
1824}
1825
1826int
Pavol Vican974377b2016-03-23 00:38:53 +01001827yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001828{
Pavol Vican85f12022016-03-05 16:30:35 +01001829 struct lys_node_list *list;
1830
1831 /* check target node type */
1832 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001833 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1834 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001835 goto error;
1836 }
1837
1838 list = (struct lys_node_list *)dev->target;
1839 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1840 /* reallocate the unique array of the target */
1841 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1842 if (!dev->deviate->unique) {
1843 LOGMEM;
1844 goto error;
1845 }
1846 list->unique = dev->deviate->unique;
1847 dev->deviate->unique = &list->unique[list->unique_size];
1848 dev->deviate->unique_size = c_uniq;
1849 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001850 } else {
1851 /* LY_DEVIATE_DEL */
1852 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1853 if (!dev->deviate->unique) {
1854 LOGMEM;
1855 goto error;
1856 }
Pavol Vican85f12022016-03-05 16:30:35 +01001857 }
1858
1859 return EXIT_SUCCESS;
1860
1861error:
1862 return EXIT_FAILURE;
1863}
1864
1865int
Pavol Vican38321d02016-08-16 14:56:02 +02001866yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001867{
Pavol Vican38321d02016-08-16 14:56:02 +02001868 int i;
1869 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001870
Pavol Vican38321d02016-08-16 14:56:02 +02001871 /* check target node type */
1872 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1873 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1874 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1875 goto error;
1876 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1877 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1878 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1879 goto error;
1880 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1881 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1882 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001883 goto error;
1884 }
1885
Pavol Vican38321d02016-08-16 14:56:02 +02001886 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1887 /* check that there is no current value */
1888 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
1889 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
1890 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1891 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001892 goto error;
1893 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001894
Pavol Vican38321d02016-08-16 14:56:02 +02001895 /* check collision with mandatory/min-elements */
1896 if ((dev->target->flags & LYS_MAND_TRUE) ||
1897 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
1898 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1899 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1900 "Adding the \"default\" statement is forbidden on %s statement.",
1901 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1902 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01001903 }
Pavol Vican38321d02016-08-16 14:56:02 +02001904 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1905 /* check that there was a value before */
1906 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
1907 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
1908 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1909 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1910 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001911 }
Pavol Vican38321d02016-08-16 14:56:02 +02001912 }
1913
1914 if (dev->target->nodetype == LYS_LEAFLIST) {
1915 /* reallocate default list in the target */
1916 llist = (struct lys_node_leaflist *)dev->target;
1917 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1918 /* reallocate (enlarge) the unique array of the target */
1919 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
1920 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1921 /* reallocate (replace) the unique array of the target */
1922 for (i = 0; i < llist->dflt_size; i++) {
1923 lydict_remove(llist->module->ctx, llist->dflt[i]);
1924 }
1925 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
1926 llist->dflt_size = 0;
1927 }
1928 }
1929
1930 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
1931 if (!dev->deviate->dflt) {
1932 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01001933 goto error;
1934 }
1935
1936 return EXIT_SUCCESS;
1937
1938error:
1939 return EXIT_FAILURE;
1940}
1941
1942int
Pavol Vican38321d02016-08-16 14:56:02 +02001943yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
1944{
1945 struct lys_node *node;
1946 struct lys_node_choice *choice;
1947 struct lys_node_leaf *leaf;
1948 struct lys_node_leaflist *llist;
1949 int rc, i;
1950 unsigned int u;
1951 const char *value;
1952
1953 value = lydict_insert_zc(ctx, exp);
1954 u = strlen(value);
1955 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
1956
1957 if (dev->target->nodetype == LYS_CHOICE) {
1958 choice = (struct lys_node_choice *)dev->target;
1959 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1960 if (rc || !node) {
1961 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1962 goto error;
1963 }
1964 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1965 if (!choice->dflt || (choice->dflt != node)) {
1966 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1967 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1968 goto error;
1969 }
1970 } else { /* add or replace */
1971 choice->dflt = node;
1972 if (!choice->dflt) {
1973 /* default branch not found */
1974 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1975 goto error;
1976 }
1977 }
1978 } else if (dev->target->nodetype == LYS_LEAF) {
1979 leaf = (struct lys_node_leaf *)dev->target;
1980 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1981 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1982 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1984 goto error;
1985 }
1986 /* remove value */
1987 lydict_remove(ctx, leaf->dflt);
1988 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001989 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001990 } else { /* add (already checked) and replace */
1991 /* remove value */
1992 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001993 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001994
1995 /* set new value */
1996 leaf->dflt = lydict_insert(ctx, value, u);
1997
1998 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1999 ly_set_add(dev->dflt_check, dev->target, 0);
2000 }
2001 } else { /* LYS_LEAFLIST */
2002 llist = (struct lys_node_leaflist *)dev->target;
2003 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2004 /* find and remove the value in target list */
2005 for (i = 0; i < llist->dflt_size; i++) {
2006 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2007 /* match, remove the value */
2008 lydict_remove(llist->module->ctx, llist->dflt[i]);
2009 llist->dflt[i] = NULL;
2010 break;
2011 }
2012 }
2013 if (i == llist->dflt_size) {
2014 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2015 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2016 goto error;
2017 }
2018 } else {
2019 /* add or replace, anyway we place items into the deviate's list
2020 which propagates to the target */
2021 /* we just want to check that the value isn't already in the list */
2022 for (i = 0; i < llist->dflt_size; i++) {
2023 if (ly_strequal(llist->dflt[i], value, 1)) {
2024 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2025 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2026 goto error;
2027 }
2028 }
2029 /* store it in target node */
2030 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
2031
2032 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2033 ly_set_add(dev->dflt_check, dev->target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01002034 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02002035 }
2036 }
2037
2038 return EXIT_SUCCESS;
2039error:
2040 return EXIT_FAILURE;
2041}
2042
2043
2044int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002045yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002046{
2047 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002048 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002049 goto error;
2050 }
2051
2052 /* for we deviate from RFC 6020 and allow config property even it is/is not
2053 * specified in the target explicitly since config property inherits. So we expect
2054 * that config is specified in every node. But for delete, we check that the value
2055 * is the same as here in deviation
2056 */
2057 dev->deviate->flags |= value;
2058
2059 /* add and replace are the same in this case */
2060 /* remove current config value of the target ... */
2061 dev->target->flags &= ~LYS_CONFIG_MASK;
2062
2063 /* ... and replace it with the value specified in deviation */
2064 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2065
2066 return EXIT_SUCCESS;
2067
2068error:
2069 return EXIT_FAILURE;
2070}
2071
2072int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002073yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002074{
Radek Krejcie00d2312016-08-12 15:27:49 +02002075 struct lys_node *parent;
2076
Pavol Vican85f12022016-03-05 16:30:35 +01002077 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002078 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002079 goto error;
2080 }
2081
2082 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002083 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002084 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2085 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002086 goto error;
2087 }
2088
2089 dev->deviate->flags |= value;
2090
2091 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2092 /* check that there is no current value */
2093 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002094 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2095 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002096 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002097 } else {
2098 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2099 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2100 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2101 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2102 goto error;
2103 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2104 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2105 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2106 goto error;
2107 }
Pavol Vican85f12022016-03-05 16:30:35 +01002108 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002109 } else { /* replace */
2110 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002111 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2112 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002113 goto error;
2114 }
Pavol Vican85f12022016-03-05 16:30:35 +01002115 }
2116
Pavol Vican85f12022016-03-05 16:30:35 +01002117 /* remove current mandatory value of the target ... */
2118 dev->target->flags &= ~LYS_MAND_MASK;
2119
2120 /* ... and replace it with the value specified in deviation */
2121 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2122
Radek Krejcie00d2312016-08-12 15:27:49 +02002123 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2124 for (parent = dev->target->parent;
2125 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2126 parent = parent->parent) {
2127 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2128 /* stop also on presence containers */
2129 break;
2130 }
2131 }
2132 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2133 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2134 if (lyp_check_mandatory_choice(parent)) {
2135 goto error;
2136 }
2137 }
2138
Pavol Vican85f12022016-03-05 16:30:35 +01002139 return EXIT_SUCCESS;
2140
2141error:
2142 return EXIT_FAILURE;
2143}
2144
2145int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002146yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002147{
Pavol Vican09adcc32016-08-25 10:51:36 +02002148 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002149
2150 /* check target node type */
2151 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002152 max = &((struct lys_node_leaflist *)dev->target)->max;
2153 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002154 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002155 max = &((struct lys_node_list *)dev->target)->max;
2156 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002157 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002158 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2159 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 +01002160 goto error;
2161 }
2162
2163 if (type) {
2164 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002165 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002166 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002167 } else {
2168 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002169 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002170 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002171 }
2172
2173 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2174 /* check that there is no current value */
2175 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002176 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2177 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002178 goto error;
2179 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002180 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2181 /* unfortunately, there is no way to check reliably that there
2182 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002183 }
2184
2185 /* add (already checked) and replace */
2186 /* set new value specified in deviation */
2187 *ui32val = value;
2188
Pavol Vican09adcc32016-08-25 10:51:36 +02002189 /* check min-elements is smaller than max-elements */
2190 if (*max && *min > *max) {
2191 if (type) {
2192 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2193 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2194 } else {
2195 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2196 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2197 }
2198 goto error;
2199 }
2200
Pavol Vican85f12022016-03-05 16:30:35 +01002201 return EXIT_SUCCESS;
2202
2203error:
2204 return EXIT_FAILURE;
2205}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002206
2207int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002208yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002209{
2210 int i;
2211
2212 /* find must to delete, we are ok with just matching conditions */
2213 for (i = 0; i < *dev->trg_must_size; i++) {
2214 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2215 /* we have a match, free the must structure ... */
2216 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2217 /* ... and maintain the array */
2218 (*dev->trg_must_size)--;
2219 if (i != *dev->trg_must_size) {
2220 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2221 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2222 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2223 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2224 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2225 }
2226 if (!(*dev->trg_must_size)) {
2227 free(*dev->trg_must);
2228 *dev->trg_must = NULL;
2229 } else {
2230 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2231 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2232 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2233 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2234 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2235 }
2236
2237 i = -1; /* set match flag */
2238 break;
2239 }
2240 }
2241 if (i != -1) {
2242 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002243 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2244 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002245 return EXIT_FAILURE;
2246 }
2247
2248 return EXIT_SUCCESS;
2249}
2250
2251int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002252yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002253{
2254 struct lys_node_list *list;
2255 int i, j;
2256
2257 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002258 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002259 dev->deviate->unique_size++;
2260 goto error;
2261 }
2262
2263 /* find unique structures to delete */
2264 for (i = 0; i < list->unique_size; i++) {
2265 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2266 continue;
2267 }
2268
2269 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2270 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2271 break;
2272 }
2273 }
2274
2275 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2276 /* we have a match, free the unique structure ... */
2277 for (j = 0; j < list->unique[i].expr_size; j++) {
2278 lydict_remove(module->ctx, list->unique[i].expr[j]);
2279 }
2280 free(list->unique[i].expr);
2281 /* ... and maintain the array */
2282 list->unique_size--;
2283 if (i != list->unique_size) {
2284 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2285 list->unique[i].expr = list->unique[list->unique_size].expr;
2286 }
2287
2288 if (!list->unique_size) {
2289 free(list->unique);
2290 list->unique = NULL;
2291 } else {
2292 list->unique[list->unique_size].expr_size = 0;
2293 list->unique[list->unique_size].expr = NULL;
2294 }
2295
2296 i = -1; /* set match flag */
2297 break;
2298 }
2299 }
2300 dev->deviate->unique_size++;
2301
2302 if (i != -1) {
2303 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002304 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2305 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002306 goto error;
2307 }
2308
2309 free(value);
2310 return EXIT_SUCCESS;
2311
2312error:
2313 free(value);
2314 return EXIT_FAILURE;
2315}
Pavol Vicane92421d2016-03-08 10:12:33 +01002316
2317int
Pavol Vican38321d02016-08-16 14:56:02 +02002318yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002319{
2320 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002321 unsigned int u;
2322 const char *value, *target_name;
2323 struct lys_node_leaflist *llist;
2324 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002325
Pavol Vican38321d02016-08-16 14:56:02 +02002326 /* now check whether default value, if any, matches the type */
2327 for (u = 0; u < dflt_check->number; ++u) {
2328 value = NULL;
2329 rc = EXIT_SUCCESS;
2330 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2331 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2332 target_name = leaf->name;
Radek Krejci51673202016-11-01 17:00:32 +01002333 value = leaf->dflt;
2334 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Pavol Vican38321d02016-08-16 14:56:02 +02002335 } else { /* LYS_LEAFLIST */
2336 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2337 target_name = llist->name;
2338 for (i = 0; i < llist->dflt_size; i++) {
Radek Krejci51673202016-11-01 17:00:32 +01002339 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2340 (struct lys_node *)(&llist->dflt[i]));
Pavol Vican38321d02016-08-16 14:56:02 +02002341 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002342 value = llist->dflt[i];
Pavol Vicane92421d2016-03-08 10:12:33 +01002343 break;
2344 }
2345 }
2346 }
Pavol Vican38321d02016-08-16 14:56:02 +02002347 if (rc == -1) {
2348 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2349 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2350 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2351 target_name);
2352 return EXIT_FAILURE;
2353 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002354 }
Pavol Vican38321d02016-08-16 14:56:02 +02002355
Pavol Vicane92421d2016-03-08 10:12:33 +01002356 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002357
Pavol Vican9b89dda2016-03-09 15:36:55 +01002358}
2359
Pavol Vicanec423c92016-10-24 21:33:43 +02002360static int
2361yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2362 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002363{
Pavol Vicanec423c92016-10-24 21:33:43 +02002364 struct lys_submodule *submodule;
2365 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002366 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002367 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002368 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002369
Pavol Vicanec423c92016-10-24 21:33:43 +02002370 str = lydict_insert_zc(trg->ctx, value);
2371 if (trg->version) {
2372 submodule = (struct lys_submodule *)trg;
2373 module = ((struct lys_submodule *)trg)->belongsto;
2374 } else {
2375 submodule = NULL;
2376 module = trg;
2377 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002378 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002379 if (!rc) {
2380 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002381 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002382 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002383 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002384 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002385 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002386
Pavol Vicanec423c92016-10-24 21:33:43 +02002387 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002388 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002389}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002390
2391int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002392yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002393{
2394 char *prefix;
2395 char *identif;
2396 const char *ns = NULL;
2397 int i;
2398
Pavol Vicanf4717e62016-03-16 11:30:01 +01002399 /* check to the same pointer */
2400 if (data_node != actual) {
2401 return EXIT_SUCCESS;
2402 }
2403
Pavol Vicana302aa62016-03-17 10:45:35 +01002404 prefix = strdup(value);
2405 if (!prefix) {
2406 LOGMEM;
2407 goto error;
2408 }
2409 /* find prefix anf identificator*/
2410 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002411 if (!identif) {
2412 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2413 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2414 goto error;
2415 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002416 *identif = '\0';
2417 identif++;
2418
Pavol Vicanf4717e62016-03-16 11:30:01 +01002419 for(i = 0; i < module->imp_size; ++i) {
2420 if (!strcmp(module->imp[i].prefix, prefix)) {
2421 ns = module->imp[i].module->ns;
2422 break;
2423 }
2424 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002425 if (!ns && !strcmp(module->prefix, prefix)) {
2426 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2427 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002428 if (ns && !strcmp(ns, LY_NSNACM)) {
2429 if (!strcmp(identif, "default-deny-write")) {
2430 data_node->nacm |= LYS_NACM_DENYW;
2431 } else if (!strcmp(identif, "default-deny-all")) {
2432 data_node->nacm |= LYS_NACM_DENYA;
2433 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002434 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002435 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002436 }
2437 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002438 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002439 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002440
2441error:
2442 free(prefix);
2443 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002444}
2445
2446void
2447nacm_inherit(struct lys_module *module)
2448{
Pavol Vican10ffba52016-04-04 12:21:22 +02002449 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002450
2451 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002452 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002453 if (elem->parent) {
2454 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002455 case LYS_GROUPING:
2456 /* extension nacm not inherited*/
2457 break;
2458 case LYS_CHOICE:
2459 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002460 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002461 case LYS_USES:
2462 if (elem->parent->nodetype != LYS_GROUPING) {
2463 elem->nacm |= elem->parent->nacm;
2464 }
2465 break;
2466 case LYS_CONTAINER:
2467 case LYS_LIST:
2468 case LYS_CASE:
2469 case LYS_NOTIF:
2470 case LYS_RPC:
2471 case LYS_INPUT:
2472 case LYS_OUTPUT:
2473 case LYS_AUGMENT:
2474 elem->nacm |= elem->parent->nacm;
2475 break;
2476 case LYS_LEAF:
2477 case LYS_LEAFLIST:
2478 tmp_node = elem;
2479 tmp_child = elem->child;
2480 elem->child = NULL;
2481 default:
2482 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002483 }
2484 }
2485 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002486 if (tmp_node) {
2487 tmp_node->child = tmp_child;
2488 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002489 }
2490}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002491
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002492int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002493store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002494{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002495 struct lys_node *elem;
2496
Pavol Vican1dac40c2016-09-28 11:39:26 +02002497 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2498 if (config_opt == CONFIG_INHERIT_ENABLE) {
2499 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002500 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002501 if (node->parent) {
2502 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002503 } else {
2504 /* default config is true */
2505 node->flags |= LYS_CONFIG_W;
2506 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002507 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002508 /* do we even care about config flags? */
2509 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002510
Pavol Vican1dac40c2016-09-28 11:39:26 +02002511 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2512 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2513 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2514 return EXIT_FAILURE;
2515 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002516 }
2517 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002518
2519 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002520}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002521
Pavol Vican9d50a772016-10-14 22:23:36 +02002522int
2523yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2524 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002525{
Pavol Vican9d50a772016-10-14 22:23:36 +02002526 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002527 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002528 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002529 int ret = EXIT_SUCCESS, remove_import = 1;
2530 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002531
Pavol Vican9d50a772016-10-14 22:23:36 +02002532 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002533 yylex_init(&scanner);
2534 bp = yy_scan_buffer((char *)data, size, scanner);
2535 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002536 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2537 if (remove_import) {
2538 trg = (submodule) ? (struct lys_module *)submodule : module;
2539 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2540 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2541 trg->inc_size = 0;
2542 trg->imp_size = 0;
2543 }
Pavol Vican1938d882016-04-10 13:36:31 +02002544 ret = EXIT_FAILURE;
2545 }
2546 yy_delete_buffer(bp, scanner);
2547 yylex_destroy(scanner);
2548 return ret;
2549}
2550
Pavol Vican8e7110b2016-03-22 17:00:26 +01002551struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002552yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002553{
2554
Pavol Vican10ffba52016-04-04 12:21:22 +02002555 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002556 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002557 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002558
2559 unres = calloc(1, sizeof *unres);
2560 if (!unres) {
2561 LOGMEM;
2562 goto error;
2563 }
2564
2565 module = calloc(1, sizeof *module);
2566 if (!module) {
2567 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002568 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002569 }
2570
2571 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002572 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002573 module->type = 0;
2574 module->implemented = (implement ? 1 : 0);
2575
Pavol Vican9d50a772016-10-14 22:23:36 +02002576 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican7313fc02016-11-14 01:10:31 +01002577 free_yang_common(module);
2578 goto error;
2579 }
2580
2581 if (yang_check_sub_module(module, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002582 goto error;
2583 }
2584
2585 if (module && unres->count && resolve_unres_schema(module, unres)) {
2586 goto error;
2587 }
2588
2589 if (revision) {
2590 /* check revision of the parsed model */
2591 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2592 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2593 module->name, module->rev[0].date, revision);
2594 goto error;
2595 }
2596 }
2597
Pavol Vican10ffba52016-04-04 12:21:22 +02002598 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002599 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002600 goto error;
2601 }
2602
Pavol Vican10ffba52016-04-04 12:21:22 +02002603 if (module == tmp_module) {
2604 nacm_inherit(module);
2605 }
2606
Radek Krejci27fe55e2016-09-13 17:13:35 +02002607 if (module->deviation_size && !module->implemented) {
2608 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2609 /* deviations always causes target to be made implemented,
2610 * but augents and leafrefs not, so we have to apply them now */
2611 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002612 goto error;
2613 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002614 }
2615
Pavol Vican8e7110b2016-03-22 17:00:26 +01002616 unres_schema_free(NULL, &unres);
2617 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2618 return module;
2619
2620error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002621 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002622 unres_schema_free(module, &unres);
2623 if (!module || !module->name) {
2624 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002625 if (ly_vecode != LYVE_SUBMODULE) {
2626 LOGERR(ly_errno, "Module parsing failed.");
2627 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002628 return NULL;
2629 }
2630
2631 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002632
2633 lys_sub_module_remove_devs_augs(module);
2634 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002635 return NULL;
2636}
2637
2638struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002639yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002640{
2641 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002642 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002643
2644 submodule = calloc(1, sizeof *submodule);
2645 if (!submodule) {
2646 LOGMEM;
2647 goto error;
2648 }
2649
2650 submodule->ctx = module->ctx;
2651 submodule->type = 1;
2652 submodule->belongsto = module;
2653
Pavol Vican9d50a772016-10-14 22:23:36 +02002654 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican7313fc02016-11-14 01:10:31 +01002655 free_yang_common((struct lys_module *)submodule);
2656 goto error;
2657 }
2658
2659 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002660 goto error;
2661 }
2662
Pavol Vican8e7110b2016-03-22 17:00:26 +01002663 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002664 return submodule;
2665
2666error:
2667 /* cleanup */
2668 unres_schema_free((struct lys_module *)submodule, &unres);
2669
2670 if (!submodule || !submodule->name) {
2671 free(submodule);
2672 LOGERR(ly_errno, "Submodule parsing failed.");
2673 return NULL;
2674 }
2675
2676 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2677
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002678 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2679 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002680 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002681 return NULL;
2682}
Pavol Vican8760bb72016-04-07 09:44:01 +02002683
2684static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002685read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2686{
2687 int k = 0, j;
2688
2689 while (in_index < size) {
2690 if (input[in_index] == ' ') {
2691 k++;
2692 } else if (input[in_index] == '\t') {
2693 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2694 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002695 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2696 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2697 k += 8;
2698 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002699 } else {
2700 break;
2701 }
2702 ++in_index;
2703 if (k >= indent) {
2704 for (j = k - indent; j > 0; --j) {
2705 output[*out_index] = ' ';
2706 ++(*out_index);
2707 }
2708 break;
2709 }
2710 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002711 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002712}
2713
2714char *
Pavol Vican3f598892016-09-28 15:41:07 +02002715yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2716 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002717
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002718 while (i < size) {
2719 switch (input[i]) {
2720 case '\n':
2721 out_index -= space;
2722 output[out_index] = '\n';
2723 space = 0;
2724 i = read_indent(input, indent, size, i + 1, &out_index, output);
2725 break;
2726 case ' ':
2727 case '\t':
2728 output[out_index] = input[i];
2729 ++space;
2730 break;
2731 case '\\':
2732 if (input[i + 1] == 'n') {
2733 out_index -= space;
2734 output[out_index] = '\n';
2735 space = 0;
2736 i = read_indent(input, indent, size, i + 2, &out_index, output);
2737 } else if (input[i + 1] == 't') {
2738 output[out_index] = '\t';
2739 ++i;
2740 ++space;
2741 } else if (input[i + 1] == '\\') {
2742 output[out_index] = '\\';
2743 ++i;
2744 } else if ((i + 1) != size && input[i + 1] == '"') {
2745 output[out_index] = '"';
2746 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002747 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002748 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002749 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002750 } else {
2751 /* YANG 1.1 backslash must not be followed by any other character */
2752 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002753 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002754 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002755 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002756 break;
2757 default:
2758 output[out_index] = input[i];
2759 space = 0;
2760 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002761 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002762 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002763 ++out_index;
2764 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002765 output[out_index] = '\0';
2766 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002767 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002768 if (!output) {
2769 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002770 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002771 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002772 }
Pavol Vican3f598892016-09-28 15:41:07 +02002773 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002774}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002775
2776/* free function */
2777
Pavol Vican7313fc02016-11-14 01:10:31 +01002778static void yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
2779{
2780 struct yang_type *stype = (struct yang_type *)type->der;
2781 int i;
2782
2783 if (!stype) {
2784 return ;
2785 }
2786 lydict_remove(ctx, stype->name);
2787 type->base = stype->base;
2788 if (type->base == LY_TYPE_IDENT) {
2789 for (i = 0; i < type->info.ident.count; ++i) {
2790 free(type->info.ident.ref[i]);
2791 }
2792 }
2793 lys_type_free(ctx, type);
2794 free(stype);
2795}
2796
2797static void
2798yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2799{
2800 uint8_t i;
2801
2802 assert(ctx);
2803 if (!tpdf) {
2804 return;
2805 }
2806
2807 for (i = start; i < size; ++i) {
2808 lydict_remove(ctx, tpdf->name);
2809 lydict_remove(ctx, tpdf->dsc);
2810 lydict_remove(ctx, tpdf->ref);
2811
2812 yang_type_free(ctx, &tpdf->type);
2813
2814 lydict_remove(ctx, tpdf->units);
2815 lydict_remove(ctx, tpdf->dflt);
2816 }
2817}
2818
Pavol Vican1cc4e192016-10-24 16:38:31 +02002819static void
2820yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2821{
2822 uint8_t i;
2823
2824 for (i = start; i < size; ++i){
2825 free((char *)imp[i].module);
2826 lydict_remove(ctx, imp[i].prefix);
2827 lydict_remove(ctx, imp[i].dsc);
2828 lydict_remove(ctx, imp[i].ref);
2829 }
2830}
2831
Pavol Vicanec423c92016-10-24 21:33:43 +02002832static void
2833yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2834{
2835 uint8_t i;
2836
2837 for (i = start; i < size; ++i){
2838 free((char *)inc[i].submodule);
2839 lydict_remove(ctx, inc[i].dsc);
2840 lydict_remove(ctx, inc[i].ref);
2841 }
2842}
2843
Pavol Vican7313fc02016-11-14 01:10:31 +01002844/* free common item from module and submodule */
2845static void
2846free_yang_common(struct lys_module *module)
2847{
2848 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
2849 module->tpdf_size = 0;
2850}
2851
Pavol Vican1cc4e192016-10-24 16:38:31 +02002852/* check function*/
2853
2854int
Pavol Vicanec423c92016-10-24 21:33:43 +02002855yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02002856{
2857 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02002858 struct lys_include *inc;
2859 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002860 size_t size;
2861 char *s;
2862
2863 imp = module->imp;
2864 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02002865 inc = module->inc;
2866 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002867
2868 if (imp_size) {
2869 size = (imp_size * sizeof *module->imp) + sizeof(void*);
2870 module->imp_size = 0;
2871 module->imp = calloc(1, size);
2872 if (!module->imp) {
2873 LOGMEM;
2874 goto error;
2875 }
2876 /* set stop block for possible realloc */
2877 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02002878 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02002879
Pavol Vicanec423c92016-10-24 21:33:43 +02002880 if (inc_size) {
2881 size = (inc_size * sizeof *module->inc) + sizeof(void*);
2882 module->inc_size = 0;
2883 module->inc = calloc(1, size);
2884 if (!module->inc) {
2885 LOGMEM;
2886 goto error;
2887 }
2888 /* set stop block for possible realloc */
2889 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002890 }
2891
2892 for (i = 0; i < imp_size; ++i) {
2893 s = (char *) imp[i].module;
2894 imp[i].module = NULL;
2895 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
2896 ++i;
2897 goto error;
2898 }
2899 }
Pavol Vicanec423c92016-10-24 21:33:43 +02002900 for (j = 0; j < inc_size; ++j) {
2901 s = (char *) inc[i].submodule;
2902 inc[i].submodule = NULL;
2903 if (yang_fill_include(module, s, &inc[i], unres)) {
2904 ++i;
2905 goto error;
2906 }
2907 }
2908 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002909 free(imp);
2910
2911 return EXIT_SUCCESS;
2912
2913error:
2914 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02002915 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002916 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02002917 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002918 return EXIT_FAILURE;
2919}
Pavol Vican7313fc02016-11-14 01:10:31 +01002920
2921int
2922yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
2923{
2924 struct lys_tpdf *tpdf;
2925 uint8_t i, tpdf_size, *ptr_tpdf_size;
2926 int ret = EXIT_SUCCESS;
2927
2928 if (!parent) {
2929 tpdf = module->tpdf;
2930 ptr_tpdf_size = &module->tpdf_size;
2931 }
2932
2933 tpdf_size = *ptr_tpdf_size;
2934 *ptr_tpdf_size = 0;
2935
2936 for (i = 0; i < tpdf_size; ++i) {
2937 tpdf[i].type.parent = &tpdf[i];
2938 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
2939 ret = EXIT_FAILURE;
2940 break;
2941 }
2942
2943 /* check default value*/
2944 if (tpdf[i].dflt && unres_schema_add_str(module, unres, &tpdf[i].type, UNRES_TYPE_DFLT, tpdf[i].dflt) == -1) {
2945 ++i;
2946 ret = EXIT_FAILURE;
2947 break;
2948 }
2949 (*ptr_tpdf_size)++;
2950 }
2951 if (i < tpdf_size) {
2952 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
2953 }
2954
2955 return ret;
2956}
2957
2958static int
2959yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
2960{
Pavol Vican7a7916f2016-11-21 23:38:30 +01002961 uint8_t i, j, size;
2962 struct lys_feature *feature; /* shortcut */
2963 char *s;
2964
Pavol Vican7313fc02016-11-14 01:10:31 +01002965 if (yang_check_typedef(module, NULL, unres)) {
2966 goto error;
2967 }
2968
Pavol Vican7a7916f2016-11-21 23:38:30 +01002969 /* check features */
2970 for (i = 0; i < module->features_size; ++i) {
2971 feature = &module->features[i];
2972 size = feature->iffeature_size;
2973 feature->iffeature_size = 0;
2974 for (j = 0; j < size; ++j) {
2975 s = (char *)feature->iffeature[j].features;
2976 if (yang_read_if_feature(module, feature, s, unres, FEATURE_KEYWORD)) {
2977 goto error;
2978 }
2979 if (unres_schema_add_node(module, unres, feature, UNRES_FEATURE, NULL) == -1) {
2980 goto error;
2981 }
2982 }
2983 }
2984
Pavol Vican7313fc02016-11-14 01:10:31 +01002985 return EXIT_SUCCESS;
2986error:
2987 return EXIT_FAILURE;
2988}