blob: 917107e621e780f87c27b8390e1763a5a9f5891e [file] [log] [blame]
Pavol Vican021488a2016-01-25 23:56:12 +01001/**
2 * @file parser_yang.c
3 * @author Pavol Vican
4 * @brief YANG parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Pavol Vican9a3a7212016-03-23 10:04:00 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Pavol Vican021488a2016-01-25 23:56:12 +010013 */
14
Pavol Vican5de33492016-02-22 14:03:24 +010015#include <ctype.h>
Pavol Vican021488a2016-01-25 23:56:12 +010016#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010017#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010018#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010019#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010020
Pavol Vican082afd02016-10-25 12:39:15 +020021static void yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size);
22static void yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size);
23
Michal Vaskofe7e5a72016-05-02 14:49:23 +020024static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010025yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010026{
Pavol Vicanbf805472016-01-26 14:24:56 +010027 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010028 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010029 free(value);
30 return 1;
31 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010032 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010033 return 0;
34 }
35}
36
Pavol Vican810892e2016-07-12 16:55:34 +020037static int
38yang_check_typedef_identif(struct lys_node *root, struct lys_node *node, char *id)
39{
40 struct lys_node *child, *next;
41 int size;
42 struct lys_tpdf *tpdf;
43
Pavol Vican810892e2016-07-12 16:55:34 +020044 if (root) {
45 node = root;
46 }
47
48 do {
49 LY_TREE_DFS_BEGIN(node, next, child) {
50 if (child->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_GROUPING | LYS_RPC | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
51 switch (child->nodetype) {
52 case LYS_CONTAINER:
53 tpdf = ((struct lys_node_container *)child)->tpdf;
54 size = ((struct lys_node_container *)child)->tpdf_size;
55 break;
56 case LYS_LIST:
57 tpdf = ((struct lys_node_list *)child)->tpdf;
58 size = ((struct lys_node_list *)child)->tpdf_size;
59 break;
60 case LYS_GROUPING:
61 tpdf = ((struct lys_node_grp *)child)->tpdf;
62 size = ((struct lys_node_grp *)child)->tpdf_size;
63 break;
64 case LYS_RPC:
Radek Krejci71d51832016-07-14 15:59:06 +020065 tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
66 size = ((struct lys_node_rpc_action *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020067 break;
68 case LYS_INPUT:
69 case LYS_OUTPUT:
Radek Krejci71d51832016-07-14 15:59:06 +020070 tpdf = ((struct lys_node_inout *)child)->tpdf;
71 size = ((struct lys_node_inout *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020072 break;
73 case LYS_NOTIF:
74 tpdf = ((struct lys_node_notif *)child)->tpdf;
75 size = ((struct lys_node_notif *)child)->tpdf_size;
76 break;
77 default:
78 size = 0;
79 break;
80 }
Radek Krejcifc824a42016-07-14 15:48:38 +020081 if (size && dup_typedef_check(id, tpdf, size)) {
Pavol Vican810892e2016-07-12 16:55:34 +020082 LOGVAL(LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
83 return EXIT_FAILURE;
84 }
Michal Vasko3767fb22016-07-21 12:10:57 +020085 }
Pavol Vican810892e2016-07-12 16:55:34 +020086 LY_TREE_DFS_END(node, next, child)}
87 } while (root && (node = node->next));
88 return EXIT_SUCCESS;
89}
90
Michal Vaskofe7e5a72016-05-02 14:49:23 +020091int
Pavol Vican5f0316a2016-04-05 21:21:11 +020092yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010093{
Pavol Vican6eb14e82016-02-03 12:27:13 +010094 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010095
96 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010097 case MODULE_KEYWORD:
98 module->name = lydict_insert_zc(module->ctx, value);
99 break;
100 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100101 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100102 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100103 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100104 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100105 break;
106 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100107 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100108 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200109 default:
110 free(value);
111 LOGINT;
112 ret = EXIT_FAILURE;
113 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100114 }
115
Pavol Vican021488a2016-01-25 23:56:12 +0100116 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +0100117}
118
Michal Vaskofe7e5a72016-05-02 14:49:23 +0200119int
Pavol Vicand0b64c12016-07-15 09:56:19 +0200120yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
121{
122 int ret = EXIT_SUCCESS;
123
124 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +0200125 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
126 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +0200127 } else {
128 if (!strcmp(value, "1")) {
129 if (submodule) {
130 if (module->version > 1) {
131 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
132 ret = EXIT_FAILURE;
133 }
134 } else {
135 module->version = 1;
136 }
137 } else if (!strcmp(value, "1.1")) {
138 if (submodule) {
139 if (module->version != 2) {
140 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
141 ret = EXIT_FAILURE;
142 }
143 } else {
144 module->version = 2;
145 }
146 } else {
147 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
148 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200149 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200150 }
151 free(value);
152 return ret;
153}
154
155int
Pavol Vicane024ab72016-07-27 14:27:43 +0200156yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100157{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100158 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100159
Pavol Vican1cc4e192016-10-24 16:38:31 +0200160 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100161 free(value);
162 return EXIT_FAILURE;
163 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200164
165 if (imp) {
166 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
167 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100168 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100169 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100170
Pavol Vicanbf805472016-01-26 14:24:56 +0100171 return ret;
172}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100173
Pavol Vican1cc4e192016-10-24 16:38:31 +0200174static int
175yang_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 +0100176{
Pavol Vican0da132e2016-03-21 12:03:03 +0100177 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200178 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100179
Pavol Vican1cc4e192016-10-24 16:38:31 +0200180 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200181 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200182 goto error;
183 } else {
184 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
185 goto error;
186 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200187 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200188 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100189 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200190 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100191 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200192 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100193 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200194 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100195 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100196
Pavol Vican6eb14e82016-02-03 12:27:13 +0100197 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200198
199error:
200 free(value);
201 lydict_remove(module->ctx, imp_old->dsc);
202 lydict_remove(module->ctx, imp_old->ref);
203 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100204}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100205
206int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100207yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100208{
209 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100210 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100211
212 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100213 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100214 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100215 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100216 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200217 } else if (!strcmp("import", where)){
218 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
219 } else if (!strcmp("include", where)){
220 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100221 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100222 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100223 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100224 }
225 return ret;
226}
227
228int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100229yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100230{
231 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100232 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100233
234 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100235 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100236 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100237 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100238 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200239 } else if (!strcmp("import", where)){
240 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
241 } else if (!strcmp("include", where)){
242 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100243 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100244 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100245 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100246 }
247 return ret;
248}
Pavol Vicanbedff692016-02-03 14:29:17 +0100249
Pavol Vican866d9912016-10-25 09:13:30 +0200250void
251yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval)
Pavol Vicanbedff692016-02-03 14:29:17 +0100252{
Pavol Vicanbedff692016-02-03 14:29:17 +0100253 /* first member of array is last revision */
Pavol Vican866d9912016-10-25 09:13:30 +0200254 if ((module->rev_size - 1) && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100255 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
256 memcpy(module->rev[0].date, value, LY_REV_SIZE);
257 retval->dsc = module->rev[0].dsc;
258 retval->ref = module->rev[0].ref;
259 retval = module->rev;
260 retval->dsc = NULL;
261 retval->ref = NULL;
262 } else {
263 memcpy(retval->date, value, LY_REV_SIZE);
264 }
Pavol Vicanbedff692016-02-03 14:29:17 +0100265 free(value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100266}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100267
268int
Pavol Vicana1827962016-02-29 15:39:42 +0100269yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100270{
Pavol Vican45ccc592016-03-09 18:53:48 +0100271 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100272 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
273 LOGMEM;
274 return EXIT_FAILURE;
275 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100276 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100277 }
278 }
279 (*size)++;
280 return EXIT_SUCCESS;
281}
Pavol Vicane1354e92016-02-09 14:02:09 +0100282
283void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100284yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100285{
286 struct lys_feature *retval;
287
288 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100289 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100290 goto error;
291 }
292 retval = &module->features[module->features_size];
293 retval->name = lydict_insert_zc(module->ctx, value);
294 retval->module = module;
295 module->features_size++;
296 return retval;
297
298error:
299 free(value);
300 return NULL;
301}
302
303int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200304yang_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 +0100305{
306 const char *exp;
307 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100308 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200309 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100310 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200311 struct lys_type_enum *e;
312 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200313 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100314
Michal Vasko97b32be2016-07-25 10:59:53 +0200315 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
316 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
317 free(value);
318 return EXIT_FAILURE;
319 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100320
Pavol Vican0adf01d2016-03-22 12:29:33 +0100321 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100322 free(value);
323 return EXIT_FAILURE;
324 }
325 free(value);
326
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200327 switch (type) {
328 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100329 f = (struct lys_feature *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200330 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200331 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200332 break;
333 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200334 i = (struct lys_ident *) ptr;
335 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, unres);
336 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200337 break;
338 case ENUM_KEYWORD:
339 e = &((struct yang_type *)ptr)->type->info.enums.enm[((struct yang_type *)ptr)->type->info.enums.count - 1];
340 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
341 e->iffeature_size++;
342 break;
343 case BIT_KEYWORD:
344 b = &((struct yang_type *)ptr)->type->info.bits.bit[((struct yang_type *)ptr)->type->info.bits.count - 1];
345 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
346 b->iffeature_size++;
347 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200348 case REFINE_KEYWORD:
349 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
350 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, unres);
351 r->iffeature_size++;
352 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200353 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100354 n = (struct lys_node *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200355 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200356 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200357 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100358 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100359 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100360
Radek Krejci9ff0a922016-07-14 13:08:05 +0200361 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100362 return EXIT_FAILURE;
363 }
364 return EXIT_SUCCESS;
365}
366
Pavol Vican4fb66c92016-03-17 10:32:27 +0100367int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200368yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100369{
370 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100371 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100372 return EXIT_FAILURE;
373 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200374 if (shortint) {
375 *((uint8_t *)flags) |= (uint8_t)value;
376 } else {
377 *flags |= value;
378 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100379 return EXIT_SUCCESS;
380 }
381}
382
Pavol Vicanbbdef532016-02-09 14:52:12 +0100383void *
384yang_read_identity(struct lys_module *module, char *value)
385{
386 struct lys_ident *ret;
387
388 ret = &module->ident[module->ident_size];
389 ret->name = lydict_insert_zc(module->ctx, value);
390 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200391 if (dup_identities_check(ret->name, module)) {
392 lydict_remove(module->ctx, ret->name);
393 return NULL;
394 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100395 module->ident_size++;
396 return ret;
397}
398
399int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100400yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100401{
402 const char *exp;
403
Pavol Vican0adf01d2016-03-22 12:29:33 +0100404 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100405 free(value);
406 if (!exp) {
407 return EXIT_FAILURE;
408 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200409
410 /* temporarily decrement identity_size due to resolve base */
411 module->ident_size--;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100412 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100413 lydict_remove(module->ctx, exp);
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200414 /* undo change identity_size */
415 module->ident_size++;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100416 return EXIT_FAILURE;
417 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200418 /* undo change identity_size */
419 module->ident_size++;
Pavol Vican44dde2c2016-02-10 11:18:14 +0100420
Pavol Vicanbbdef532016-02-09 14:52:12 +0100421 lydict_remove(module->ctx, exp);
422 return EXIT_SUCCESS;
423}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100424
425void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200426yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100427{
428 struct lys_restr *retval;
429
430 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100431 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100432 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100433 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200434 case ANYDATA_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100435 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200436 retval = &((struct lys_node_anydata *)node)->must[((struct lys_node_anydata *)node)->must_size++];
Pavol Vican096c6db2016-02-11 15:08:10 +0100437 break;
438 case LEAF_KEYWORD:
439 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100440 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100441 case LEAF_LIST_KEYWORD:
442 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
443 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100444 case LIST_KEYWORD:
445 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
446 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100447 case REFINE_KEYWORD:
448 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
449 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100450 case ADD_KEYWORD:
451 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
452 memset(retval, 0, sizeof *retval);
453 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100454 case DELETE_KEYWORD:
455 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
456 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200457 case NOTIFICATION_KEYWORD:
458 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
459 break;
460 case INPUT_KEYWORD:
461 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
462 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200463 default:
464 goto error;
465 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100466 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100467 retval->expr = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200468 if (!retval->expr) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100469 goto error;
470 }
471 free(value);
472 return retval;
473
474error:
475 free(value);
476 return NULL;
477}
478
479int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100480yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100481{
482 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100483
Pavol Vicandde090a2016-08-30 15:12:14 +0200484 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100485 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100486 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200487 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100488 }
489 return ret;
490}
Pavol Vicanb5687112016-02-09 22:35:59 +0100491
492int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100493yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100494{
495 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100496 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100497 free(value);
498 return EXIT_FAILURE;
499 } else {
500 cont->presence = lydict_insert_zc(module->ctx, value);
501 return EXIT_SUCCESS;
502 }
503}
504
Pavol Vican235dbd42016-02-10 10:34:19 +0100505void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200506yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100507{
508 struct lys_when *retval;
509
510 retval = calloc(1, sizeof *retval);
511 if (!retval) {
512 LOGMEM;
513 free(value);
514 return NULL;
515 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100516 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200517 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100518 goto error;
519 }
520 switch (type) {
521 case CONTAINER_KEYWORD:
522 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100523 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100524 goto error;
525 }
526 ((struct lys_node_container *)node)->when = retval;
527 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200528 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100529 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200530 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200531 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100532 goto error;
533 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200534 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100535 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100536 case CHOICE_KEYWORD:
537 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100538 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100539 goto error;
540 }
541 ((struct lys_node_choice *)node)->when = retval;
542 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100543 case CASE_KEYWORD:
544 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100545 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100546 goto error;
547 }
548 ((struct lys_node_case *)node)->when = retval;
549 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100550 case LEAF_KEYWORD:
551 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100552 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100553 goto error;
554 }
555 ((struct lys_node_leaf *)node)->when = retval;
556 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100557 case LEAF_LIST_KEYWORD:
558 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100559 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100560 goto error;
561 }
562 ((struct lys_node_leaflist *)node)->when = retval;
563 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100564 case LIST_KEYWORD:
565 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100566 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100567 goto error;
568 }
569 ((struct lys_node_list *)node)->when = retval;
570 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100571 case USES_KEYWORD:
572 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100573 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100574 goto error;
575 }
576 ((struct lys_node_uses *)node)->when = retval;
577 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100578 case AUGMENT_KEYWORD:
579 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100580 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100581 goto error;
582 }
583 ((struct lys_node_augment *)node)->when = retval;
584 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200585 default:
586 goto error;
587 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100588 }
589 free(value);
590 return retval;
591
592error:
593 free(value);
594 lys_when_free(module->ctx, retval);
595 return NULL;
596}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100597
598void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100599yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100600{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100601 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100602
Pavol Vican7cadfe72016-02-11 12:33:34 +0100603 node = calloc(1, sizeof_struct);
604 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100605 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100606 LOGMEM;
607 return NULL;
608 }
Pavol Vican531a9132016-03-03 10:10:09 +0100609 if (value) {
610 node->name = lydict_insert_zc(module->ctx, value);
611 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100612 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100613 node->nodetype = nodetype;
614 node->prev = node;
615
616 /* insert the node into the schema tree */
617 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100618 if (value) {
619 lydict_remove(module->ctx, node->name);
620 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100621 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100622 return NULL;
623 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100624 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100625}
626
Pavol Vican8c793992016-07-15 10:44:57 +0200627void *
628yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
629{
630 struct lys_node *node;
631
Michal Vaskobb174852016-07-25 11:00:21 +0200632 if (module->version != 2) {
633 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
634 return NULL;
635 }
636
Pavol Vican8c793992016-07-15 10:44:57 +0200637 for (node = parent; node; node = lys_parent(node)) {
Radek Krejci24681f12016-10-06 10:42:21 +0200638 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vicanbbe77822016-07-15 12:53:07 +0200639 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200640 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
641 return NULL;
642 }
643 }
644 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
645}
646
Pavol Vican8c82fa82016-02-10 13:13:24 +0100647int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200648yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100649{
650 int ret;
651
652 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100653 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100654 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100655 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100656 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100657 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100658 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200659 default:
660 free(value);
661 LOGINT;
662 ret = EXIT_FAILURE;
663 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100664 }
665 return ret;
666}
667
668int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200669yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100670{
671 int ret;
672
673 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100674 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100675 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100676 break;
677 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100678 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100679 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100680 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100681 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100682 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200683 default:
684 free(value);
685 LOGINT;
686 ret = EXIT_FAILURE;
687 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100688 }
689 return ret;
690}
Pavol Vican5de33492016-02-22 14:03:24 +0100691
692int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100693yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100694{
695 char *exp, *value;
696
697 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200698 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100699 while ((value = strpbrk(value, " \t\n"))) {
700 list->keys_size++;
701 while (isspace(*value)) {
702 value++;
703 }
704 }
705 list->keys_size++;
706 list->keys = calloc(list->keys_size, sizeof *list->keys);
707 if (!list->keys) {
708 LOGMEM;
709 goto error;
710 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100711 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100712 goto error;
713 }
714 free(exp);
715 return EXIT_SUCCESS;
716
717error:
718 free(exp);
719 return EXIT_FAILURE;
720}
721
722int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100723yang_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 +0100724{
725 int i, j;
726 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200727 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100728
729 /* count the number of unique leafs in the value */
730 vaux = value;
731 while ((vaux = strpbrk(vaux, " \t\n"))) {
732 unique->expr_size++;
733 while (isspace(*vaux)) {
734 vaux++;
735 }
736 }
737 unique->expr_size++;
738 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
739 if (!unique->expr) {
740 LOGMEM;
741 goto error;
742 }
743
744 for (i = 0; i < unique->expr_size; i++) {
745 vaux = strpbrk(value, " \t\n");
746 if (!vaux) {
747 /* the last token, lydict_insert() will count its size on its own */
748 vaux = value;
749 }
750
751 /* store token into unique structure */
752 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
753
754 /* check that the expression does not repeat */
755 for (j = 0; j < i; j++) {
756 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100757 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
758 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100759 goto error;
760 }
761 }
762 /* try to resolve leaf */
763 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200764 unique_info = malloc(sizeof *unique_info);
765 unique_info->list = (struct lys_node *)list;
766 unique_info->expr = unique->expr[i];
767 unique_info->trg_type = &unique->trg_type;
768 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200769 goto error;
770 }
Pavol Vican85f12022016-03-05 16:30:35 +0100771 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200772 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100773 goto error;
774 }
775 }
776
777 /* move to next token */
778 value = vaux;
779 while(isspace(*value)) {
780 value++;
781 }
782 }
783
784 return EXIT_SUCCESS;
785
786error:
787 return EXIT_FAILURE;
788}
789
790int
Pavol Vican5de33492016-02-22 14:03:24 +0100791yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
792{
793 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100794 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100795
796 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100797 str = (char *)list->unique[k].expr;
798 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100799 goto error;
800 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100801 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100802 }
803 return EXIT_SUCCESS;
804
805error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100806 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100807 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100808}
809
Pavol Vican07f220f2016-09-02 13:04:37 +0200810int
Pavol Vican81344ac2016-09-02 14:23:06 +0200811yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100812{
Pavol Vican81344ac2016-09-02 14:23:06 +0200813 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
814 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
815 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100816 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200817 if (stype->type->info.lref.path) {
818 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
819 goto error;
820 }
821 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
822 stype->base = LY_TYPE_LEAFREF;
823 return EXIT_SUCCESS;
824
825error:
826 free(value);
827 return EXIT_FAILURE;
828}
829
830int
831yang_read_require_instance(struct yang_type *stype, int req)
832{
833 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
834 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
835 return EXIT_FAILURE;
836 }
837 if (stype->type->info.lref.req) {
838 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
839 return EXIT_FAILURE;
840 }
841 stype->type->info.lref.req = req;
842 stype->base = LY_TYPE_LEAFREF;
843 return EXIT_SUCCESS;
844}
845
846int
Pavol Vican07f220f2016-09-02 13:04:37 +0200847yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100848{
Pavol Vican07f220f2016-09-02 13:04:37 +0200849 const char *value;
850 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100851
Pavol Vican07f220f2016-09-02 13:04:37 +0200852 if (stype->base && stype->base != LY_TYPE_IDENT) {
853 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
854 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100855 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200856
857 stype->base = LY_TYPE_IDENT;
858 /* store in the JSON format */
859 value = transform_schema2json(module, expr);
860 free(expr);
861
862 if (!value) {
863 return EXIT_FAILURE;
864 }
865 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100866 lydict_remove(module->ctx, value);
867
868 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200869 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100870 }
871
Pavol Vican07f220f2016-09-02 13:04:37 +0200872 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100873}
874
Pavol Vican73e7c992016-02-24 12:18:05 +0100875int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200876yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100877{
Pavol Vican81344ac2016-09-02 14:23:06 +0200878 int i, j, rc, ret = -1;
879 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100880 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200881 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200882 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200883 struct lys_type *dertype;
884 struct lys_type_enum *enms_sc = NULL;
885 struct lys_type_bit *bits_sc = NULL;
886 struct lys_type_bit bit_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100887
Pavol Vican0adf01d2016-03-22 12:29:33 +0100888 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100889 if (!value) {
890 goto error;
891 }
892
893 i = parse_identifier(value);
894 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100895 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100896 lydict_remove(module->ctx, value);
897 goto error;
898 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200899 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100900 name = value;
901 if (value[i]) {
902 typ->type->module_name = lydict_insert(module->ctx, value, i);
903 name += i;
904 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100905 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100906 lydict_remove(module->ctx, value);
907 goto error;
908 }
909 ++name;
910 }
911
912 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100913 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100914 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200915 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100916 goto error;
917
Michal Vasko01c6fd22016-05-20 11:43:05 +0200918 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100919 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200920 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200921 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100922 ret = EXIT_FAILURE;
923 goto error;
924 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200925 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200926
Radek Krejci9b6aad22016-09-20 15:55:51 +0200927 if (typ->type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200928 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200929 * 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 +0200930 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
931 if (siter) {
932 if (!((struct lys_node_grp *)siter)->nacm) {
933 LOGINT;
934 goto error;
935 }
936 ((struct lys_node_grp *)siter)->nacm--;
937 } else {
938 LOGINT;
939 goto error;
940 }
941 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200942
943 /* check status */
944 if (lyp_check_status(typ->type->parent->flags, typ->type->parent->module, typ->type->parent->name,
945 typ->type->der->flags, typ->type->der->module, typ->type->der->name, parent)) {
946 goto error;
947 }
948
Pavol Vican8bd72e42016-08-29 09:53:05 +0200949 base = typ->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100950 typ->type->base = typ->type->der->type.base;
951 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100952 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100953 }
954 switch (base) {
955 case LY_TYPE_STRING:
956 if (typ->type->base == LY_TYPE_BINARY) {
957 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100958 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100959 goto error;
960 }
961 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100962 if (typ->type->info.binary.length && lyp_check_length_range(typ->type->info.binary.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100963 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100964 goto error;
965 }
966 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100967 if (typ->type->info.str.length && lyp_check_length_range(typ->type->info.str.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100968 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100969 goto error;
970 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100971 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200972 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100973 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100974 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100975 break;
976 case LY_TYPE_DEC64:
977 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100978 /* mandatory sub-statement(s) check */
979 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
980 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100981 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100982 goto error;
983 }
984 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
985 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100986 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100987 goto error;
988 }
Radek Krejci4800f652016-09-08 14:02:52 +0200989
990 /* copy fraction-digits specification from parent type for easier internal use */
991 if (typ->type->der->type.der) {
992 typ->type->info.dec64.dig = typ->type->der->type.info.dec64.dig;
993 typ->type->info.dec64.div = typ->type->der->type.info.dec64.div;
994 }
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200995 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
996 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
997 goto error;
998 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100999 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
1000 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001001 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001002 goto error;
1003 }
1004 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001005 if (typ->type->info.num.range && lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001006 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001007 goto error;
1008 }
1009 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001010 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +01001011 goto error;
1012 }
1013 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001014 case LY_TYPE_ENUM:
1015 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001016 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001017 goto error;
1018 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001019 dertype = &typ->type->der->type;
1020
1021 if (!dertype->der) {
1022 if (!typ->type->info.enums.count) {
1023 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1024 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
1025 goto error;
1026 }
1027 } else {
1028 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1029 if (module->version < 2 && typ->type->info.enums.count) {
1030 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
1031 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
1032 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
1033 goto error;
1034 }
1035
1036 /* restricted enumeration type - the name MUST be used in the base type */
1037 enms_sc = dertype->info.enums.enm;
1038 for(i = 0; i < typ->type->info.enums.count; i++) {
1039 for (j = 0; j < dertype->info.enums.count; j++) {
1040 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
1041 break;
1042 }
1043 }
1044 if (j == dertype->info.enums.count) {
1045 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1046 goto error;
1047 }
1048
1049 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
1050 /* automatically assign value from base type */
1051 typ->type->info.enums.enm[i].value = enms_sc[j].value;
1052 } else {
1053 /* check that the assigned value corresponds to the original
1054 * value of the enum in the base type */
1055 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
1056 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
1057 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1058 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
1059 typ->type->info.enums.enm[i].name, enms_sc[j].value);
1060 goto error;
1061 }
1062 }
1063 }
Pavol Vican79a763d2016-02-25 15:41:27 +01001064 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001065 break;
Pavol Vican03a59442016-03-21 15:23:45 +01001066 case LY_TYPE_BITS:
1067 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001068 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +01001069 goto error;
1070 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001071 dertype = &typ->type->der->type;
1072
1073 if (!dertype->der) {
1074 if (!typ->type->info.bits.count) {
1075 /* type is derived directly from buit-in bits type and bit statement is required */
1076 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1077 goto error;
1078 }
1079 } else {
1080 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1081 if (module->version < 2 && typ->type->info.bits.count) {
1082 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1083 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1084 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1085 goto error;
1086 }
1087
1088 bits_sc = dertype->info.bits.bit;
1089 for (i = 0; i < typ->type->info.bits.count; i++) {
1090 for (j = 0; j < dertype->info.bits.count; j++) {
1091 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
1092 break;
1093 }
1094 }
1095 if (j == dertype->info.bits.count) {
1096 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1097 goto error;
1098 }
1099
1100 /* restricted bits type */
1101 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1102 /* automatically assign position from base type */
1103 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1104 } else {
1105 /* check that the assigned position corresponds to the original
1106 * position of the bit in the base type */
1107 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1108 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1109 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1110 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1111 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1112 goto error;
1113 }
1114 }
1115 }
Pavol Vican03a59442016-03-21 15:23:45 +01001116 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001117
1118 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1119 j = i;
1120
1121 /* keep them ordered by position */
1122 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1123 /* switch them */
1124 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1125 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1126 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1127 j--;
1128 }
Pavol Vican03a59442016-03-21 15:23:45 +01001129 }
1130 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001131 case LY_TYPE_LEAFREF:
Pavol Vican81344ac2016-09-02 14:23:06 +02001132 if (typ->type->base == LY_TYPE_INST) {
1133 if (typ->type->info.lref.path) {
1134 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +01001135 goto error;
1136 }
Pavol Vican81344ac2016-09-02 14:23:06 +02001137 if ((req = typ->type->info.lref.req)) {
1138 typ->type->info.inst.req = req;
1139 }
Pavol Vican191613a2016-02-26 16:21:32 +01001140 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +02001141 /* require-instance only YANG 1.1 */
1142 if (typ->type->info.lref.req && (module->version < 2)) {
1143 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
1144 goto error;
1145 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001146 /* flag resolving for later use */
1147 if (!tpdftype) {
1148 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1149 if (siter) {
1150 /* just a flag - do not resolve */
1151 tpdftype = 1;
1152 }
1153 }
1154
Pavol Vican6b072512016-04-04 10:50:21 +02001155 if (typ->type->info.lref.path) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001156 if (typ->type->der->type.der) {
1157 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1158 goto error;
1159 }
Pavol Vican191613a2016-02-26 16:21:32 +01001160 value = typ->type->info.lref.path;
1161 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001162 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001163 lydict_remove(module->ctx, value);
1164 if (!typ->type->info.lref.path) {
1165 goto error;
1166 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001167 /* try to resolve leafref path only when this is instantiated
1168 * leaf, so it is not:
1169 * - typedef's type,
1170 * - in grouping definition,
1171 * - just instantiated in a grouping definition,
1172 * because in those cases the nodes referenced in path might not be present
1173 * and it is not a bug. */
1174 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001175 goto error;
1176 }
Pavol Vican6b072512016-04-04 10:50:21 +02001177 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001178 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001179 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001180 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001181 /* copy leafref definition into the derived type */
1182 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1183 /* and resolve the path at the place we are (if not in grouping/typedef) */
1184 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001185 goto error;
1186 }
Radek Krejci742be352016-07-17 12:18:54 +02001187
Radek Krejci3a5501d2016-07-18 22:03:34 +02001188 /* add pointer to leafref target, only on leaves (not in typedefs) */
1189 if (typ->type->info.lref.target && lys_leaf_add_leafref_target(typ->type->info.lref.target, (struct lys_node *)typ->type->parent)) {
1190 goto error;
Radek Krejci742be352016-07-17 12:18:54 +02001191 }
Pavol Vican191613a2016-02-26 16:21:32 +01001192 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001193 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001194 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001195 goto error;
1196 }
1197 break;
1198 case LY_TYPE_IDENT:
Pavol Vican07f220f2016-09-02 13:04:37 +02001199 if (typ->type->base != LY_TYPE_IDENT) {
1200 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001201 goto error;
1202 }
Pavol Vican07f220f2016-09-02 13:04:37 +02001203 if (typ->type->der->type.der) {
1204 if (typ->type->info.ident.ref) {
1205 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1206 goto error;
1207 }
1208 } else {
1209 if (!typ->type->info.ident.ref) {
1210 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1211 goto error;
1212 }
1213 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001214 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001215 case LY_TYPE_UNION:
1216 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001217 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001218 goto error;
1219 }
1220 if (!typ->type->info.uni.types) {
1221 if (typ->type->der->type.der) {
1222 /* this is just a derived type with no additional type specified/required */
1223 break;
1224 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001225 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001226 goto error;
1227 }
1228 for (i = 0; i < typ->type->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001229 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001230 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001231 goto error;
1232 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001233 if (module->version < 2) {
1234 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
1235 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1236 goto error;
1237 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
1238 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1239 goto error;
1240 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001241 }
1242 }
1243 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001244
1245 default:
1246 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1247 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001248 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001249 goto error;
1250 }
1251 } else {
1252 LOGINT;
1253 goto error;
1254 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001255 }
1256 return EXIT_SUCCESS;
1257
1258error:
1259 if (typ->type->module_name) {
1260 lydict_remove(module->ctx, typ->type->module_name);
1261 typ->type->module_name = NULL;
1262 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001263 if (base) {
1264 typ->type->base = base;
1265 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001266 return ret;
1267}
1268
1269void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001270yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001271{
1272 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001273 struct type_deviation *dev;
1274 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001275
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001276 typ = calloc(1, sizeof *typ);
1277 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001278 LOGMEM;
1279 return NULL;
1280 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001281
1282 typ->flags = LY_YANG_STRUCTURE_FLAG;
1283 switch (type) {
1284 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001285 if (((struct lys_node_leaf *)parent)->type.der) {
1286 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1287 goto error;
1288 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001289 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1290 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1291 typ->type = &((struct lys_node_leaf *)parent)->type;
1292 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001293 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001294 if (((struct lys_node_leaflist *)parent)->type.der) {
1295 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1296 goto error;
1297 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001298 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1299 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1300 typ->type = &((struct lys_node_leaflist *)parent)->type;
1301 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001302 case UNION_KEYWORD:
1303 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1304 typ->type = (struct lys_type *)parent;
1305 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001306 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001307 if (((struct lys_tpdf *)parent)->type.der) {
1308 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1309 goto error;
1310 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001311 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1312 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001313 break;
1314 case REPLACE_KEYWORD:
1315 /* deviation replace type*/
1316 dev = (struct type_deviation *)parent;
1317 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001318 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001319 goto error;
1320 }
1321 /* check target node type */
1322 if (dev->target->nodetype == LYS_LEAF) {
1323 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1324 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1325 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1326 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001327 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1328 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001329 goto error;
1330 }
1331
1332 /* remove type and initialize it */
1333 lys_type_free(module->ctx, typ->type);
1334 tmp_parent = typ->type->parent;
1335 memset(typ->type, 0, sizeof *typ->type);
1336 typ->type->parent = tmp_parent;
1337
1338 /* replace it with the value specified in deviation */
1339 /* HACK for unres */
1340 typ->type->der = (struct lys_tpdf *)typ;
1341 dev->deviate->type = typ->type;
1342 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001343 default:
1344 goto error;
1345 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001346 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001347 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001348 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001349
1350error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001351 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001352 free(typ);
1353 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001354}
1355
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001356void
1357yang_delete_type(struct lys_module *module, struct yang_type *stype)
1358{
1359 int i;
1360
Pavol Vican77a95e52016-08-15 09:49:26 +02001361 if (!stype) {
1362 return;
1363 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001364 stype->type->base = stype->base;
1365 stype->type->der = NULL;
1366 lydict_remove(module->ctx, stype->name);
1367 if (stype->base == LY_TYPE_UNION) {
1368 for (i = 0; i < stype->type->info.uni.count; i++) {
1369 if (stype->type->info.uni.types[i].der) {
1370 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1371 }
1372 }
1373 }
1374 free(stype);
1375}
1376
Pavol Vican73e7c992016-02-24 12:18:05 +01001377void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001378yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001379{
1380 struct lys_restr **length;
1381
Pavol Vican6b072512016-04-04 10:50:21 +02001382 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001383 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001384 typ->base = LY_TYPE_STRING;
1385 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001386 length = &typ->type->info.binary.length;
1387 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001388 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001389 goto error;
1390 }
1391
1392 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001393 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001394 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001395 }
1396 *length = calloc(1, sizeof **length);
1397 if (!*length) {
1398 LOGMEM;
1399 goto error;
1400 }
1401 (*length)->expr = lydict_insert_zc(module->ctx, value);
1402 return *length;
1403
1404error:
1405 free(value);
1406 return NULL;
1407
1408}
Pavol Vican1c203db2016-02-24 14:05:23 +01001409
Pavol Vican6eecf302016-08-10 11:09:05 +02001410int
1411yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001412{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001413 char *buf;
1414 size_t len;
1415
Michal Vasko0aee5c12016-06-17 14:27:26 +02001416 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001417 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001418 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001419 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001420
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001421 len = strlen(value);
1422 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001423
1424 if (!buf) {
1425 LOGMEM;
1426 free(value);
1427 return EXIT_FAILURE;
1428 }
1429
1430 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001431 strcpy(&buf[1], value);
1432 free(value);
1433
Pavol Vican6eecf302016-08-10 11:09:05 +02001434 pattern->expr = lydict_insert_zc(module->ctx, buf);
1435 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001436}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001437
1438void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001439yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001440{
Pavol Vican6b072512016-04-04 10:50:21 +02001441 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001442 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001443 goto error;
1444 }
Pavol Vican6b072512016-04-04 10:50:21 +02001445 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001446 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001447 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001448 goto error;
1449 }
1450 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1451 if (!typ->type->info.dec64.range) {
1452 LOGMEM;
1453 goto error;
1454 }
1455 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1456 return typ->type->info.dec64.range;
1457
1458error:
1459 free(value);
1460 return NULL;
1461}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001462
1463int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001464yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001465{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001466 unsigned int i;
1467
Pavol Vican6b072512016-04-04 10:50:21 +02001468 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1469 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001470 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001471 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001472 goto error;
1473 }
1474 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001475 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001476 goto error;
1477 }
1478 /* range check */
1479 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001480 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001481 goto error;
1482 }
1483 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001484 typ->type->info.dec64.div = 10;
1485 for (i = 1; i < value; i++) {
1486 typ->type->info.dec64.div *= 10;
1487 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001488 return EXIT_SUCCESS;
1489
1490error:
1491 return EXIT_FAILURE;
1492}
Pavol Vican79a763d2016-02-25 15:41:27 +01001493
Pavol Vican874715f2016-10-25 14:52:08 +02001494int
1495yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001496{
Pavol Vican874715f2016-10-25 14:52:08 +02001497 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001498
Pavol Vicanc6662412016-08-30 08:06:28 +02001499 if (!value[0]) {
1500 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1501 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1502 free(value);
1503 goto error;
1504 }
1505
Pavol Vican79a763d2016-02-25 15:41:27 +01001506 enm->name = lydict_insert_zc(module->ctx, value);
1507
1508 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1509 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001510 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001511 goto error;
1512 }
1513
Pavol Vican874715f2016-10-25 14:52:08 +02001514 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001515 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001516 for (i = 0; i < j; i++) {
1517 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[j].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001518 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001519 goto error;
1520 }
1521 }
1522
Pavol Vican874715f2016-10-25 14:52:08 +02001523 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001524
1525error:
Pavol Vican874715f2016-10-25 14:52:08 +02001526 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001527}
1528
1529int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001530yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001531{
1532 int i, j;
1533
1534 if (!assign) {
1535 /* assign value automatically */
1536 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001537 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001538 goto error;
1539 }
1540 enm->value = *value;
1541 enm->flags |= LYS_AUTOASSIGNED;
1542 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001543 } else if (typ->type->info.enums.enm == enm) {
1544 /* change value, which is assigned automatically, if first enum has value. */
1545 *value = typ->type->info.enums.enm[0].value;
1546 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001547 }
1548
1549 /* check that the value is unique */
1550 j = typ->type->info.enums.count-1;
1551 for (i = 0; i < j; i++) {
1552 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001553 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001554 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1555 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001556 goto error;
1557 }
1558 }
1559
1560 return EXIT_SUCCESS;
1561
1562error:
1563 return EXIT_FAILURE;
1564}
Pavol Vican9887c682016-02-29 11:32:01 +01001565
1566void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001567yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001568{
1569 int i;
1570 struct lys_type_bit *bit;
1571
1572 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001573 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001574 free(value);
1575 goto error;
1576 }
1577 bit->name = lydict_insert_zc(module->ctx, value);
1578
1579 /* check the name uniqueness */
1580 for (i = 0; i < typ->type->info.bits.count; i++) {
1581 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001582 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001583 typ->type->info.bits.count++;
1584 goto error;
1585 }
1586 }
1587 typ->type->info.bits.count++;
1588 return bit;
1589
1590error:
1591 return NULL;
1592}
1593
1594int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001595yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001596{
1597 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001598
1599 if (!assign) {
1600 /* assign value automatically */
1601 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001602 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001603 goto error;
1604 }
1605 bit->pos = (uint32_t)*value;
1606 bit->flags |= LYS_AUTOASSIGNED;
1607 (*value)++;
1608 }
1609
1610 j = typ->type->info.bits.count - 1;
1611 /* check that the value is unique */
1612 for (i = 0; i < j; i++) {
1613 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001614 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 +01001615 goto error;
1616 }
1617 }
1618
Pavol Vican9887c682016-02-29 11:32:01 +01001619 return EXIT_SUCCESS;
1620
1621error:
1622 return EXIT_FAILURE;
1623}
Pavol Vican0df02b02016-03-01 10:28:50 +01001624
1625void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001626yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001627{
1628 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001629 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001630
Pavol Vican810892e2016-07-12 16:55:34 +02001631 root = (parent) ? NULL : lys_main_module(module)->data;
1632 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001633 free(value);
1634 return NULL;
1635 }
Pavol Vican810892e2016-07-12 16:55:34 +02001636
Pavol Vican0df02b02016-03-01 10:28:50 +01001637 if (!parent) {
1638 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001639 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001640 } else {
1641 switch (parent->nodetype) {
1642 case LYS_GROUPING:
1643 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001644 ((struct lys_node_grp *)parent)->tpdf_size++;
1645 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001646 case LYS_CONTAINER:
1647 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1648 ((struct lys_node_container *)parent)->tpdf_size++;
1649 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001650 case LYS_LIST:
1651 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1652 ((struct lys_node_list *)parent)->tpdf_size++;
1653 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001654 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001655 case LYS_ACTION:
1656 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1657 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001658 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001659 case LYS_INPUT:
1660 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001661 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1662 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001663 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001664 case LYS_NOTIF:
1665 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1666 ((struct lys_node_notif *)parent)->tpdf_size++;
1667 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001668 default:
1669 /* another type of nodetype is error*/
1670 LOGINT;
1671 free(value);
1672 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001673 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001674 }
1675
Pavol Vican79436472016-04-04 11:22:02 +02001676 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001677 ret->name = lydict_insert_zc(module->ctx, value);
1678 ret->module = module;
1679 return ret;
1680}
Pavol Vican1003ead2016-03-02 12:24:52 +01001681
1682void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001683yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001684{
1685 struct lys_refine *rfn;
1686
1687 rfn = &uses->refine[uses->refine_size];
1688 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001689 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001690 free(value);
1691 if (!rfn->target_name) {
1692 return NULL;
1693 }
1694 return rfn;
1695}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001696
1697void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001698yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001699{
1700 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001701
1702 if (parent) {
1703 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1704 } else {
1705 aug = &module->augment[module->augment_size];
1706 }
1707 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001708 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001709 free(value);
1710 if (!aug->target_name) {
1711 return NULL;
1712 }
1713 aug->parent = parent;
1714 aug->module = module;
1715 if (parent) {
1716 ((struct lys_node_uses *)parent)->augment_size++;
1717 } else {
1718 module->augment_size++;
1719 }
1720 return aug;
1721}
Pavol Vican220e5a12016-03-03 14:19:43 +01001722
1723void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001724yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001725{
1726 struct lys_node *dev_target = NULL;
1727 struct lys_deviation *dev;
1728 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001729 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001730
Pavol Vican220e5a12016-03-03 14:19:43 +01001731 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001732 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001733 free(value);
1734 if (!dev->target_name) {
1735 goto error;
1736 }
1737
Pavol Vican974377b2016-03-23 00:38:53 +01001738 deviation = calloc(1, sizeof *deviation);
1739 if (!deviation) {
1740 LOGMEM;
1741 goto error;
1742 }
1743
Pavol Vican220e5a12016-03-03 14:19:43 +01001744 /* resolve target node */
1745 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1746 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001747 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001748 goto error;
1749 }
Radek Krejcic4283442016-04-22 09:19:27 +02001750 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001751 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1752 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001753 goto error;
1754 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001755
Pavol Vican220e5a12016-03-03 14:19:43 +01001756 /*save pointer to the deviation and deviated target*/
1757 deviation->deviation = dev;
1758 deviation->target = dev_target;
1759
Pavol Vican38321d02016-08-16 14:56:02 +02001760 deviation->dflt_check = ly_set_new();
1761 if (!deviation->dflt_check) {
1762 LOGMEM;
1763 goto error;
1764 }
1765
Pavol Vican220e5a12016-03-03 14:19:43 +01001766 return deviation;
1767
1768error:
1769 free(deviation);
1770 lydict_remove(module->ctx, dev->target_name);
1771 return NULL;
1772}
Pavol Vican4c90c642016-03-03 15:06:47 +01001773
1774int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001775yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001776{
1777 int i;
1778
1779 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001780 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001781 return EXIT_FAILURE;
1782 }
1783 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1784
1785 /* you cannot remove a key leaf */
1786 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1787 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1788 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001789 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1790 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001791 return EXIT_FAILURE;
1792 }
1793 }
1794 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001795
Pavol Vican4c90c642016-03-03 15:06:47 +01001796 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001797 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001798 dev->deviation->orig_node = dev->target;
1799
1800 dev->deviation->deviate_size = 1;
1801 return EXIT_SUCCESS;
1802}
Pavol Vican85f12022016-03-05 16:30:35 +01001803
1804int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001805yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001806{
1807 struct unres_schema tmp_unres;
1808
1809 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1810 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1811 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001812 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001813 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001814 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1815 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001816 return EXIT_FAILURE;
1817 }
1818
1819 /* store a shallow copy of the original node */
1820 if (!dev->deviation->orig_node) {
1821 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001822 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001823 /* just to be safe */
1824 if (tmp_unres.count) {
1825 LOGINT;
1826 return EXIT_FAILURE;
1827 }
1828 }
1829
1830 return EXIT_SUCCESS;
1831}
1832
1833int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001834yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001835{
1836 const char **stritem;
1837
1838 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001839 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001840 free(value);
1841 goto error;
1842 }
1843
1844 /* check target node type */
1845 if (dev->target->nodetype == LYS_LEAFLIST) {
1846 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1847 } else if (dev->target->nodetype == LYS_LEAF) {
1848 stritem = &((struct lys_node_leaf *)dev->target)->units;
1849 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001850 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001852 free(value);
1853 goto error;
1854 }
1855
1856 dev->deviate->units = lydict_insert_zc(ctx, value);
1857
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001858 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1859 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001860 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001861 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1862 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001863 goto error;
1864 }
1865 /* remove current units value of the target */
1866 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001867 } else {
1868 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1869 /* check that there is no current value */
1870 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001871 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1872 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001873 goto error;
1874 }
1875 } else { /* replace */
1876 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001877 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1878 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001879 goto error;
1880 }
1881 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001882 /* remove current units value of the target ... */
1883 lydict_remove(ctx, *stritem);
1884
1885 /* ... and replace it with the value specified in deviation */
1886 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1887 }
1888
Pavol Vican85f12022016-03-05 16:30:35 +01001889 return EXIT_SUCCESS;
1890
1891error:
1892 return EXIT_FAILURE;
1893}
1894
1895int
Pavol Vican974377b2016-03-23 00:38:53 +01001896yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001897{
Pavol Vican85f12022016-03-05 16:30:35 +01001898 /* check target node type */
1899 switch (dev->target->nodetype) {
1900 case LYS_LEAF:
1901 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1902 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1903 break;
1904 case LYS_CONTAINER:
1905 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1906 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1907 break;
1908 case LYS_LEAFLIST:
1909 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1910 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1911 break;
1912 case LYS_LIST:
1913 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1914 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1915 break;
1916 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001917 case LYS_ANYDATA:
1918 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1919 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001920 break;
1921 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001922 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1923 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001924 goto error;
1925 }
1926
Michal Vasko508a50d2016-09-07 14:50:33 +02001927 /* flag will be checked again, clear it for now */
Michal Vaskoe9914d12016-10-07 14:32:37 +02001928 dev->target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001929
Pavol Vican85f12022016-03-05 16:30:35 +01001930 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1931 /* reallocate the must array of the target */
1932 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1933 if (!dev->deviate->must) {
1934 LOGMEM;
1935 goto error;
1936 }
1937 *dev->trg_must = dev->deviate->must;
1938 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1939 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001940 } else {
1941 /* LY_DEVIATE_DEL */
1942 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1943 if (!dev->deviate->must) {
1944 LOGMEM;
1945 goto error;
1946 }
Pavol Vican85f12022016-03-05 16:30:35 +01001947 }
1948
1949 return EXIT_SUCCESS;
1950
1951error:
1952 return EXIT_FAILURE;
1953}
1954
1955int
Pavol Vican974377b2016-03-23 00:38:53 +01001956yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001957{
Pavol Vican85f12022016-03-05 16:30:35 +01001958 struct lys_node_list *list;
1959
1960 /* check target node type */
1961 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001962 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1963 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001964 goto error;
1965 }
1966
1967 list = (struct lys_node_list *)dev->target;
1968 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1969 /* reallocate the unique array of the target */
1970 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1971 if (!dev->deviate->unique) {
1972 LOGMEM;
1973 goto error;
1974 }
1975 list->unique = dev->deviate->unique;
1976 dev->deviate->unique = &list->unique[list->unique_size];
1977 dev->deviate->unique_size = c_uniq;
1978 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001979 } else {
1980 /* LY_DEVIATE_DEL */
1981 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1982 if (!dev->deviate->unique) {
1983 LOGMEM;
1984 goto error;
1985 }
Pavol Vican85f12022016-03-05 16:30:35 +01001986 }
1987
1988 return EXIT_SUCCESS;
1989
1990error:
1991 return EXIT_FAILURE;
1992}
1993
1994int
Pavol Vican38321d02016-08-16 14:56:02 +02001995yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001996{
Pavol Vican38321d02016-08-16 14:56:02 +02001997 int i;
1998 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001999
Pavol Vican38321d02016-08-16 14:56:02 +02002000 /* check target node type */
2001 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
2002 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2003 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
2004 goto error;
2005 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2006 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2007 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2008 goto error;
2009 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
2010 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2011 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002012 goto error;
2013 }
2014
Pavol Vican38321d02016-08-16 14:56:02 +02002015 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2016 /* check that there is no current value */
2017 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
2018 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
2019 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2020 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002021 goto error;
2022 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002023
Pavol Vican38321d02016-08-16 14:56:02 +02002024 /* check collision with mandatory/min-elements */
2025 if ((dev->target->flags & LYS_MAND_TRUE) ||
2026 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
2027 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
2028 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2029 "Adding the \"default\" statement is forbidden on %s statement.",
2030 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2031 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01002032 }
Pavol Vican38321d02016-08-16 14:56:02 +02002033 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2034 /* check that there was a value before */
2035 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
2036 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
2037 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2038 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2039 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002040 }
Pavol Vican38321d02016-08-16 14:56:02 +02002041 }
2042
2043 if (dev->target->nodetype == LYS_LEAFLIST) {
2044 /* reallocate default list in the target */
2045 llist = (struct lys_node_leaflist *)dev->target;
2046 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2047 /* reallocate (enlarge) the unique array of the target */
2048 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
2049 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2050 /* reallocate (replace) the unique array of the target */
2051 for (i = 0; i < llist->dflt_size; i++) {
2052 lydict_remove(llist->module->ctx, llist->dflt[i]);
2053 }
2054 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
2055 llist->dflt_size = 0;
2056 }
2057 }
2058
2059 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
2060 if (!dev->deviate->dflt) {
2061 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01002062 goto error;
2063 }
2064
2065 return EXIT_SUCCESS;
2066
2067error:
2068 return EXIT_FAILURE;
2069}
2070
2071int
Pavol Vican38321d02016-08-16 14:56:02 +02002072yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
2073{
2074 struct lys_node *node;
2075 struct lys_node_choice *choice;
2076 struct lys_node_leaf *leaf;
2077 struct lys_node_leaflist *llist;
2078 int rc, i;
2079 unsigned int u;
2080 const char *value;
2081
2082 value = lydict_insert_zc(ctx, exp);
2083 u = strlen(value);
2084 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
2085
2086 if (dev->target->nodetype == LYS_CHOICE) {
2087 choice = (struct lys_node_choice *)dev->target;
2088 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2089 if (rc || !node) {
2090 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2091 goto error;
2092 }
2093 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2094 if (!choice->dflt || (choice->dflt != node)) {
2095 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2096 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2097 goto error;
2098 }
2099 } else { /* add or replace */
2100 choice->dflt = node;
2101 if (!choice->dflt) {
2102 /* default branch not found */
2103 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2104 goto error;
2105 }
2106 }
2107 } else if (dev->target->nodetype == LYS_LEAF) {
2108 leaf = (struct lys_node_leaf *)dev->target;
2109 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2110 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2111 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2112 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2113 goto error;
2114 }
2115 /* remove value */
2116 lydict_remove(ctx, leaf->dflt);
2117 leaf->dflt = NULL;
2118 } else { /* add (already checked) and replace */
2119 /* remove value */
2120 lydict_remove(ctx, leaf->dflt);
2121
2122 /* set new value */
2123 leaf->dflt = lydict_insert(ctx, value, u);
2124
2125 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2126 ly_set_add(dev->dflt_check, dev->target, 0);
2127 }
2128 } else { /* LYS_LEAFLIST */
2129 llist = (struct lys_node_leaflist *)dev->target;
2130 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2131 /* find and remove the value in target list */
2132 for (i = 0; i < llist->dflt_size; i++) {
2133 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2134 /* match, remove the value */
2135 lydict_remove(llist->module->ctx, llist->dflt[i]);
2136 llist->dflt[i] = NULL;
2137 break;
2138 }
2139 }
2140 if (i == llist->dflt_size) {
2141 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2142 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2143 goto error;
2144 }
2145 } else {
2146 /* add or replace, anyway we place items into the deviate's list
2147 which propagates to the target */
2148 /* we just want to check that the value isn't already in the list */
2149 for (i = 0; i < llist->dflt_size; i++) {
2150 if (ly_strequal(llist->dflt[i], value, 1)) {
2151 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2152 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2153 goto error;
2154 }
2155 }
2156 /* store it in target node */
2157 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
2158
2159 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2160 ly_set_add(dev->dflt_check, dev->target, 0);
2161 }
2162 }
2163
2164 return EXIT_SUCCESS;
2165error:
2166 return EXIT_FAILURE;
2167}
2168
2169
2170int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002171yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002172{
2173 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002174 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002175 goto error;
2176 }
2177
2178 /* for we deviate from RFC 6020 and allow config property even it is/is not
2179 * specified in the target explicitly since config property inherits. So we expect
2180 * that config is specified in every node. But for delete, we check that the value
2181 * is the same as here in deviation
2182 */
2183 dev->deviate->flags |= value;
2184
2185 /* add and replace are the same in this case */
2186 /* remove current config value of the target ... */
2187 dev->target->flags &= ~LYS_CONFIG_MASK;
2188
2189 /* ... and replace it with the value specified in deviation */
2190 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2191
2192 return EXIT_SUCCESS;
2193
2194error:
2195 return EXIT_FAILURE;
2196}
2197
2198int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002199yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002200{
Radek Krejcie00d2312016-08-12 15:27:49 +02002201 struct lys_node *parent;
2202
Pavol Vican85f12022016-03-05 16:30:35 +01002203 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002204 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002205 goto error;
2206 }
2207
2208 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002209 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002210 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2211 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002212 goto error;
2213 }
2214
2215 dev->deviate->flags |= value;
2216
2217 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2218 /* check that there is no current value */
2219 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002220 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2221 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002222 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002223 } else {
2224 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2225 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2226 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2227 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2228 goto error;
2229 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2230 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2231 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2232 goto error;
2233 }
Pavol Vican85f12022016-03-05 16:30:35 +01002234 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002235 } else { /* replace */
2236 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002237 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2238 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002239 goto error;
2240 }
Pavol Vican85f12022016-03-05 16:30:35 +01002241 }
2242
Pavol Vican85f12022016-03-05 16:30:35 +01002243 /* remove current mandatory value of the target ... */
2244 dev->target->flags &= ~LYS_MAND_MASK;
2245
2246 /* ... and replace it with the value specified in deviation */
2247 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2248
Radek Krejcie00d2312016-08-12 15:27:49 +02002249 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2250 for (parent = dev->target->parent;
2251 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2252 parent = parent->parent) {
2253 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2254 /* stop also on presence containers */
2255 break;
2256 }
2257 }
2258 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2259 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2260 if (lyp_check_mandatory_choice(parent)) {
2261 goto error;
2262 }
2263 }
2264
Pavol Vican85f12022016-03-05 16:30:35 +01002265 return EXIT_SUCCESS;
2266
2267error:
2268 return EXIT_FAILURE;
2269}
2270
2271int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002272yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002273{
Pavol Vican09adcc32016-08-25 10:51:36 +02002274 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002275
2276 /* check target node type */
2277 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002278 max = &((struct lys_node_leaflist *)dev->target)->max;
2279 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002280 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002281 max = &((struct lys_node_list *)dev->target)->max;
2282 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002283 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002284 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2285 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 +01002286 goto error;
2287 }
2288
2289 if (type) {
2290 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002291 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002292 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002293 } else {
2294 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002295 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002296 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002297 }
2298
2299 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2300 /* check that there is no current value */
2301 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002302 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2303 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002304 goto error;
2305 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002306 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2307 /* unfortunately, there is no way to check reliably that there
2308 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002309 }
2310
2311 /* add (already checked) and replace */
2312 /* set new value specified in deviation */
2313 *ui32val = value;
2314
Pavol Vican09adcc32016-08-25 10:51:36 +02002315 /* check min-elements is smaller than max-elements */
2316 if (*max && *min > *max) {
2317 if (type) {
2318 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2319 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2320 } else {
2321 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2322 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2323 }
2324 goto error;
2325 }
2326
Pavol Vican85f12022016-03-05 16:30:35 +01002327 return EXIT_SUCCESS;
2328
2329error:
2330 return EXIT_FAILURE;
2331}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002332
2333int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002334yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002335{
2336 int i;
2337
2338 /* find must to delete, we are ok with just matching conditions */
2339 for (i = 0; i < *dev->trg_must_size; i++) {
2340 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2341 /* we have a match, free the must structure ... */
2342 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2343 /* ... and maintain the array */
2344 (*dev->trg_must_size)--;
2345 if (i != *dev->trg_must_size) {
2346 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2347 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2348 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2349 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2350 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2351 }
2352 if (!(*dev->trg_must_size)) {
2353 free(*dev->trg_must);
2354 *dev->trg_must = NULL;
2355 } else {
2356 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2357 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2358 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2359 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2360 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2361 }
2362
2363 i = -1; /* set match flag */
2364 break;
2365 }
2366 }
2367 if (i != -1) {
2368 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002369 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2370 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002371 return EXIT_FAILURE;
2372 }
2373
2374 return EXIT_SUCCESS;
2375}
2376
2377int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002378yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002379{
2380 struct lys_node_list *list;
2381 int i, j;
2382
2383 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002384 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002385 dev->deviate->unique_size++;
2386 goto error;
2387 }
2388
2389 /* find unique structures to delete */
2390 for (i = 0; i < list->unique_size; i++) {
2391 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2392 continue;
2393 }
2394
2395 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2396 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2397 break;
2398 }
2399 }
2400
2401 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2402 /* we have a match, free the unique structure ... */
2403 for (j = 0; j < list->unique[i].expr_size; j++) {
2404 lydict_remove(module->ctx, list->unique[i].expr[j]);
2405 }
2406 free(list->unique[i].expr);
2407 /* ... and maintain the array */
2408 list->unique_size--;
2409 if (i != list->unique_size) {
2410 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2411 list->unique[i].expr = list->unique[list->unique_size].expr;
2412 }
2413
2414 if (!list->unique_size) {
2415 free(list->unique);
2416 list->unique = NULL;
2417 } else {
2418 list->unique[list->unique_size].expr_size = 0;
2419 list->unique[list->unique_size].expr = NULL;
2420 }
2421
2422 i = -1; /* set match flag */
2423 break;
2424 }
2425 }
2426 dev->deviate->unique_size++;
2427
2428 if (i != -1) {
2429 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002430 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2431 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002432 goto error;
2433 }
2434
2435 free(value);
2436 return EXIT_SUCCESS;
2437
2438error:
2439 free(value);
2440 return EXIT_FAILURE;
2441}
Pavol Vicane92421d2016-03-08 10:12:33 +01002442
2443int
Pavol Vican38321d02016-08-16 14:56:02 +02002444yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002445{
2446 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002447 unsigned int u;
2448 const char *value, *target_name;
2449 struct lys_node_leaflist *llist;
2450 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002451
Pavol Vican38321d02016-08-16 14:56:02 +02002452 /* now check whether default value, if any, matches the type */
2453 for (u = 0; u < dflt_check->number; ++u) {
2454 value = NULL;
2455 rc = EXIT_SUCCESS;
2456 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2457 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2458 target_name = leaf->name;
2459 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2460 } else { /* LYS_LEAFLIST */
2461 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2462 target_name = llist->name;
2463 for (i = 0; i < llist->dflt_size; i++) {
2464 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[i]);
2465 if (rc == -1) {
Pavol Vicane92421d2016-03-08 10:12:33 +01002466 break;
2467 }
2468 }
2469 }
Pavol Vican38321d02016-08-16 14:56:02 +02002470 if (rc == -1) {
2471 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2472 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2473 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2474 target_name);
2475 return EXIT_FAILURE;
2476 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002477 }
Pavol Vican38321d02016-08-16 14:56:02 +02002478
Pavol Vicane92421d2016-03-08 10:12:33 +01002479 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002480
Pavol Vican9b89dda2016-03-09 15:36:55 +01002481}
2482
Pavol Vicanec423c92016-10-24 21:33:43 +02002483static int
2484yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2485 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002486{
Pavol Vicanec423c92016-10-24 21:33:43 +02002487 struct lys_submodule *submodule;
2488 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002489 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002490 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002491 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002492
Pavol Vicanec423c92016-10-24 21:33:43 +02002493 str = lydict_insert_zc(trg->ctx, value);
2494 if (trg->version) {
2495 submodule = (struct lys_submodule *)trg;
2496 module = ((struct lys_submodule *)trg)->belongsto;
2497 } else {
2498 submodule = NULL;
2499 module = trg;
2500 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002501 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002502 if (!rc) {
2503 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002504 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002505 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002506 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002507 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002508 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002509
Pavol Vicanec423c92016-10-24 21:33:43 +02002510 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002511 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002512}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002513
2514int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002515yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002516{
2517 char *prefix;
2518 char *identif;
2519 const char *ns = NULL;
2520 int i;
2521
Pavol Vicanf4717e62016-03-16 11:30:01 +01002522 /* check to the same pointer */
2523 if (data_node != actual) {
2524 return EXIT_SUCCESS;
2525 }
2526
Pavol Vicana302aa62016-03-17 10:45:35 +01002527 prefix = strdup(value);
2528 if (!prefix) {
2529 LOGMEM;
2530 goto error;
2531 }
2532 /* find prefix anf identificator*/
2533 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002534 if (!identif) {
2535 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2536 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2537 goto error;
2538 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002539 *identif = '\0';
2540 identif++;
2541
Pavol Vicanf4717e62016-03-16 11:30:01 +01002542 for(i = 0; i < module->imp_size; ++i) {
2543 if (!strcmp(module->imp[i].prefix, prefix)) {
2544 ns = module->imp[i].module->ns;
2545 break;
2546 }
2547 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002548 if (!ns && !strcmp(module->prefix, prefix)) {
2549 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2550 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002551 if (ns && !strcmp(ns, LY_NSNACM)) {
2552 if (!strcmp(identif, "default-deny-write")) {
2553 data_node->nacm |= LYS_NACM_DENYW;
2554 } else if (!strcmp(identif, "default-deny-all")) {
2555 data_node->nacm |= LYS_NACM_DENYA;
2556 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002557 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002558 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002559 }
2560 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002561 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002562 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002563
2564error:
2565 free(prefix);
2566 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002567}
2568
2569void
2570nacm_inherit(struct lys_module *module)
2571{
Pavol Vican10ffba52016-04-04 12:21:22 +02002572 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002573
2574 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002575 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002576 if (elem->parent) {
2577 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002578 case LYS_GROUPING:
2579 /* extension nacm not inherited*/
2580 break;
2581 case LYS_CHOICE:
2582 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002583 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002584 case LYS_USES:
2585 if (elem->parent->nodetype != LYS_GROUPING) {
2586 elem->nacm |= elem->parent->nacm;
2587 }
2588 break;
2589 case LYS_CONTAINER:
2590 case LYS_LIST:
2591 case LYS_CASE:
2592 case LYS_NOTIF:
2593 case LYS_RPC:
2594 case LYS_INPUT:
2595 case LYS_OUTPUT:
2596 case LYS_AUGMENT:
2597 elem->nacm |= elem->parent->nacm;
2598 break;
2599 case LYS_LEAF:
2600 case LYS_LEAFLIST:
2601 tmp_node = elem;
2602 tmp_child = elem->child;
2603 elem->child = NULL;
2604 default:
2605 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002606 }
2607 }
2608 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002609 if (tmp_node) {
2610 tmp_node->child = tmp_child;
2611 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002612 }
2613}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002614
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002615int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002616store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002617{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002618 struct lys_node *elem;
2619
Pavol Vican1dac40c2016-09-28 11:39:26 +02002620 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2621 if (config_opt == CONFIG_INHERIT_ENABLE) {
2622 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002623 /* get config flag from parent */
Pavol Vicanb5071382016-09-30 14:54:23 +02002624 if (node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2625 node->flags |= LYS_CONFIG_R;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002626 } else {
2627 /* default config is true */
2628 node->flags |= LYS_CONFIG_W;
2629 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002630 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002631 /* do we even care about config flags? */
2632 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002633
Pavol Vican1dac40c2016-09-28 11:39:26 +02002634 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2635 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2636 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2637 return EXIT_FAILURE;
2638 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002639 }
2640 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002641
2642 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002643}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002644
Pavol Vican9d50a772016-10-14 22:23:36 +02002645int
2646yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2647 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002648{
Pavol Vican9d50a772016-10-14 22:23:36 +02002649 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002650 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002651 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002652 int ret = EXIT_SUCCESS, remove_import = 1;
2653 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002654
Pavol Vican9d50a772016-10-14 22:23:36 +02002655 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002656 yylex_init(&scanner);
2657 bp = yy_scan_buffer((char *)data, size, scanner);
2658 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002659 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2660 if (remove_import) {
2661 trg = (submodule) ? (struct lys_module *)submodule : module;
2662 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2663 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2664 trg->inc_size = 0;
2665 trg->imp_size = 0;
2666 }
Pavol Vican1938d882016-04-10 13:36:31 +02002667 ret = EXIT_FAILURE;
2668 }
2669 yy_delete_buffer(bp, scanner);
2670 yylex_destroy(scanner);
2671 return ret;
2672}
2673
Pavol Vican8e7110b2016-03-22 17:00:26 +01002674struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002675yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002676{
2677
Pavol Vican10ffba52016-04-04 12:21:22 +02002678 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002679 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002680 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002681
2682 unres = calloc(1, sizeof *unres);
2683 if (!unres) {
2684 LOGMEM;
2685 goto error;
2686 }
2687
2688 module = calloc(1, sizeof *module);
2689 if (!module) {
2690 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002691 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002692 }
2693
2694 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002695 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002696 module->type = 0;
2697 module->implemented = (implement ? 1 : 0);
2698
Pavol Vican9d50a772016-10-14 22:23:36 +02002699 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002700 goto error;
2701 }
2702
2703 if (module && unres->count && resolve_unres_schema(module, unres)) {
2704 goto error;
2705 }
2706
2707 if (revision) {
2708 /* check revision of the parsed model */
2709 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2710 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2711 module->name, module->rev[0].date, revision);
2712 goto error;
2713 }
2714 }
2715
Pavol Vican10ffba52016-04-04 12:21:22 +02002716 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002717 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002718 goto error;
2719 }
2720
Pavol Vican10ffba52016-04-04 12:21:22 +02002721 if (module == tmp_module) {
2722 nacm_inherit(module);
2723 }
2724
Radek Krejci27fe55e2016-09-13 17:13:35 +02002725 if (module->deviation_size && !module->implemented) {
2726 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2727 /* deviations always causes target to be made implemented,
2728 * but augents and leafrefs not, so we have to apply them now */
2729 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002730 goto error;
2731 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002732 }
2733
Pavol Vican8e7110b2016-03-22 17:00:26 +01002734 unres_schema_free(NULL, &unres);
2735 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2736 return module;
2737
2738error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002739 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002740 unres_schema_free(module, &unres);
2741 if (!module || !module->name) {
2742 free(module);
2743 LOGERR(ly_errno, "Module parsing failed.");
2744 return NULL;
2745 }
2746
2747 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002748
2749 lys_sub_module_remove_devs_augs(module);
2750 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002751 return NULL;
2752}
2753
2754struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002755yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002756{
2757 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002758 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002759
2760 submodule = calloc(1, sizeof *submodule);
2761 if (!submodule) {
2762 LOGMEM;
2763 goto error;
2764 }
2765
2766 submodule->ctx = module->ctx;
2767 submodule->type = 1;
2768 submodule->belongsto = module;
2769
Pavol Vican9d50a772016-10-14 22:23:36 +02002770 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002771 goto error;
2772 }
2773
Pavol Vican8e7110b2016-03-22 17:00:26 +01002774 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002775 return submodule;
2776
2777error:
2778 /* cleanup */
2779 unres_schema_free((struct lys_module *)submodule, &unres);
2780
2781 if (!submodule || !submodule->name) {
2782 free(submodule);
2783 LOGERR(ly_errno, "Submodule parsing failed.");
2784 return NULL;
2785 }
2786
2787 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2788
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002789 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2790 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002791 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002792 return NULL;
2793}
Pavol Vican8760bb72016-04-07 09:44:01 +02002794
2795static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002796read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2797{
2798 int k = 0, j;
2799
2800 while (in_index < size) {
2801 if (input[in_index] == ' ') {
2802 k++;
2803 } else if (input[in_index] == '\t') {
2804 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2805 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002806 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2807 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2808 k += 8;
2809 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002810 } else {
2811 break;
2812 }
2813 ++in_index;
2814 if (k >= indent) {
2815 for (j = k - indent; j > 0; --j) {
2816 output[*out_index] = ' ';
2817 ++(*out_index);
2818 }
2819 break;
2820 }
2821 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002822 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002823}
2824
2825char *
Pavol Vican3f598892016-09-28 15:41:07 +02002826yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2827 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002828
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002829 while (i < size) {
2830 switch (input[i]) {
2831 case '\n':
2832 out_index -= space;
2833 output[out_index] = '\n';
2834 space = 0;
2835 i = read_indent(input, indent, size, i + 1, &out_index, output);
2836 break;
2837 case ' ':
2838 case '\t':
2839 output[out_index] = input[i];
2840 ++space;
2841 break;
2842 case '\\':
2843 if (input[i + 1] == 'n') {
2844 out_index -= space;
2845 output[out_index] = '\n';
2846 space = 0;
2847 i = read_indent(input, indent, size, i + 2, &out_index, output);
2848 } else if (input[i + 1] == 't') {
2849 output[out_index] = '\t';
2850 ++i;
2851 ++space;
2852 } else if (input[i + 1] == '\\') {
2853 output[out_index] = '\\';
2854 ++i;
2855 } else if ((i + 1) != size && input[i + 1] == '"') {
2856 output[out_index] = '"';
2857 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002858 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002859 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002860 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002861 } else {
2862 /* YANG 1.1 backslash must not be followed by any other character */
2863 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002864 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002865 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002866 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002867 break;
2868 default:
2869 output[out_index] = input[i];
2870 space = 0;
2871 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002872 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002873 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002874 ++out_index;
2875 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002876 output[out_index] = '\0';
2877 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002878 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002879 if (!output) {
2880 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002881 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002882 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002883 }
Pavol Vican3f598892016-09-28 15:41:07 +02002884 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002885}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002886
2887/* free function */
2888
2889static void
2890yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2891{
2892 uint8_t i;
2893
2894 for (i = start; i < size; ++i){
2895 free((char *)imp[i].module);
2896 lydict_remove(ctx, imp[i].prefix);
2897 lydict_remove(ctx, imp[i].dsc);
2898 lydict_remove(ctx, imp[i].ref);
2899 }
2900}
2901
Pavol Vicanec423c92016-10-24 21:33:43 +02002902static void
2903yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2904{
2905 uint8_t i;
2906
2907 for (i = start; i < size; ++i){
2908 free((char *)inc[i].submodule);
2909 lydict_remove(ctx, inc[i].dsc);
2910 lydict_remove(ctx, inc[i].ref);
2911 }
2912}
2913
Pavol Vican1cc4e192016-10-24 16:38:31 +02002914/* check function*/
2915
2916int
Pavol Vicanec423c92016-10-24 21:33:43 +02002917yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02002918{
2919 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02002920 struct lys_include *inc;
2921 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002922 size_t size;
2923 char *s;
2924
2925 imp = module->imp;
2926 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02002927 inc = module->inc;
2928 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002929
2930 if (imp_size) {
2931 size = (imp_size * sizeof *module->imp) + sizeof(void*);
2932 module->imp_size = 0;
2933 module->imp = calloc(1, size);
2934 if (!module->imp) {
2935 LOGMEM;
2936 goto error;
2937 }
2938 /* set stop block for possible realloc */
2939 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02002940 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02002941
Pavol Vicanec423c92016-10-24 21:33:43 +02002942 if (inc_size) {
2943 size = (inc_size * sizeof *module->inc) + sizeof(void*);
2944 module->inc_size = 0;
2945 module->inc = calloc(1, size);
2946 if (!module->inc) {
2947 LOGMEM;
2948 goto error;
2949 }
2950 /* set stop block for possible realloc */
2951 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002952 }
2953
2954 for (i = 0; i < imp_size; ++i) {
2955 s = (char *) imp[i].module;
2956 imp[i].module = NULL;
2957 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
2958 ++i;
2959 goto error;
2960 }
2961 }
Pavol Vicanec423c92016-10-24 21:33:43 +02002962 for (j = 0; j < inc_size; ++j) {
2963 s = (char *) inc[i].submodule;
2964 inc[i].submodule = NULL;
2965 if (yang_fill_include(module, s, &inc[i], unres)) {
2966 ++i;
2967 goto error;
2968 }
2969 }
2970 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002971 free(imp);
2972
2973 return EXIT_SUCCESS;
2974
2975error:
2976 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02002977 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002978 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02002979 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002980 return EXIT_FAILURE;
2981}