blob: 096cbf4a7a0d8614d71b6ee66bfcd8068bde537b [file] [log] [blame]
Pavol Vican021488a2016-01-25 23:56:12 +01001/**
2 * @file parser_yang.c
3 * @author Pavol Vican
4 * @brief YANG parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Pavol Vican9a3a7212016-03-23 10:04:00 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Pavol Vican021488a2016-01-25 23:56:12 +010013 */
14
Pavol Vican5de33492016-02-22 14:03:24 +010015#include <ctype.h>
Pavol Vican021488a2016-01-25 23:56:12 +010016#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010017#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010018#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010019#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010020
Michal Vaskofe7e5a72016-05-02 14:49:23 +020021static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010022yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010023{
Pavol Vicanbf805472016-01-26 14:24:56 +010024 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010025 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010026 free(value);
27 return 1;
28 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010029 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010030 return 0;
31 }
32}
33
Pavol Vican810892e2016-07-12 16:55:34 +020034static int
35yang_check_typedef_identif(struct lys_node *root, struct lys_node *node, char *id)
36{
37 struct lys_node *child, *next;
38 int size;
39 struct lys_tpdf *tpdf;
40
41
42 if (root) {
43 node = root;
44 }
45
46 do {
47 LY_TREE_DFS_BEGIN(node, next, child) {
48 if (child->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_GROUPING | LYS_RPC | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
49 switch (child->nodetype) {
50 case LYS_CONTAINER:
51 tpdf = ((struct lys_node_container *)child)->tpdf;
52 size = ((struct lys_node_container *)child)->tpdf_size;
53 break;
54 case LYS_LIST:
55 tpdf = ((struct lys_node_list *)child)->tpdf;
56 size = ((struct lys_node_list *)child)->tpdf_size;
57 break;
58 case LYS_GROUPING:
59 tpdf = ((struct lys_node_grp *)child)->tpdf;
60 size = ((struct lys_node_grp *)child)->tpdf_size;
61 break;
62 case LYS_RPC:
63 tpdf = ((struct lys_node_rpc *)child)->tpdf;
64 size = ((struct lys_node_rpc *)child)->tpdf_size;
65 break;
66 case LYS_INPUT:
67 case LYS_OUTPUT:
68 tpdf = ((struct lys_node_rpc_inout *)child)->tpdf;
69 size = ((struct lys_node_rpc_inout *)child)->tpdf_size;
70 break;
71 case LYS_NOTIF:
72 tpdf = ((struct lys_node_notif *)child)->tpdf;
73 size = ((struct lys_node_notif *)child)->tpdf_size;
74 break;
75 default:
76 size = 0;
77 break;
78 }
Radek Krejcifc824a42016-07-14 15:48:38 +020079 if (size && dup_typedef_check(id, tpdf, size)) {
Pavol Vican810892e2016-07-12 16:55:34 +020080 LOGVAL(LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
81 return EXIT_FAILURE;
82 }
83 }
84 LY_TREE_DFS_END(node, next, child)}
85 } while (root && (node = node->next));
86 return EXIT_SUCCESS;
87}
88
Michal Vaskofe7e5a72016-05-02 14:49:23 +020089int
Pavol Vican5f0316a2016-04-05 21:21:11 +020090yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010091{
Pavol Vican6eb14e82016-02-03 12:27:13 +010092 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010093
94 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010095 case MODULE_KEYWORD:
96 module->name = lydict_insert_zc(module->ctx, value);
97 break;
98 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010099 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100100 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100101 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100102 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100103 break;
104 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100105 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100106 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200107 default:
108 free(value);
109 LOGINT;
110 ret = EXIT_FAILURE;
111 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100112 }
113
Pavol Vican021488a2016-01-25 23:56:12 +0100114 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +0100115}
116
Michal Vaskofe7e5a72016-05-02 14:49:23 +0200117int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200118yang_read_prefix(struct lys_module *module, void *save, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +0100119{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100121
Pavol Vican0adf01d2016-03-22 12:29:33 +0100122 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100123 free(value);
124 return EXIT_FAILURE;
125 }
Pavol Vicanbf805472016-01-26 14:24:56 +0100126 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +0100127 case MODULE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100128 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100129 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100130 case IMPORT_KEYWORD:
131 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
132 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200133 default:
134 free(value);
135 LOGINT;
136 ret = EXIT_FAILURE;
137 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100138 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100139
Pavol Vicanbf805472016-01-26 14:24:56 +0100140 return ret;
141}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100142
Pavol Vican6eb14e82016-02-03 12:27:13 +0100143int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100144yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100145{
Pavol Vican0da132e2016-03-21 12:03:03 +0100146 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200147 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100148
Pavol Vican0da132e2016-03-21 12:03:03 +0100149 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100150 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +0100151 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200152 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100153 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200154 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100155 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100156
Pavol Vican6eb14e82016-02-03 12:27:13 +0100157 return EXIT_SUCCESS;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100158}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100159
160int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100161yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100162{
163 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100164 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100165
166 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100167 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100168 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100169 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100170 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100171 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100173 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100174 }
175 return ret;
176}
177
178int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100179yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100180{
181 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100182 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100183
184 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100185 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100186 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100187 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100188 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100189 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100190 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100191 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100192 }
193 return ret;
194}
Pavol Vicanbedff692016-02-03 14:29:17 +0100195
196void *
197yang_read_revision(struct lys_module *module, char *value)
198{
199 struct lys_revision *retval;
200
Pavol Vican1eeb1992016-02-09 11:10:45 +0100201 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100202
203 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100204 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100205 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
206 memcpy(module->rev[0].date, value, LY_REV_SIZE);
207 retval->dsc = module->rev[0].dsc;
208 retval->ref = module->rev[0].ref;
209 retval = module->rev;
210 retval->dsc = NULL;
211 retval->ref = NULL;
212 } else {
213 memcpy(retval->date, value, LY_REV_SIZE);
214 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100215 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100216 free(value);
217 return retval;
218}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100219
220int
Pavol Vicana1827962016-02-29 15:39:42 +0100221yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100222{
Pavol Vican45ccc592016-03-09 18:53:48 +0100223 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100224 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
225 LOGMEM;
226 return EXIT_FAILURE;
227 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100228 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100229 }
230 }
231 (*size)++;
232 return EXIT_SUCCESS;
233}
Pavol Vicane1354e92016-02-09 14:02:09 +0100234
235void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100236yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100237{
238 struct lys_feature *retval;
239
240 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100241 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100242 goto error;
243 }
244 retval = &module->features[module->features_size];
245 retval->name = lydict_insert_zc(module->ctx, value);
246 retval->module = module;
247 module->features_size++;
248 return retval;
249
250error:
251 free(value);
252 return NULL;
253}
254
255int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200256yang_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 +0100257{
258 const char *exp;
259 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100260 struct lys_feature *f;
261 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100262
Pavol Vican0adf01d2016-03-22 12:29:33 +0100263 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100264 free(value);
265 return EXIT_FAILURE;
266 }
267 free(value);
268
269 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100270 if (type == FEATURE_KEYWORD) {
271 f = (struct lys_feature *) ptr;
272 f->features[f->features_size] = f;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100273 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100274 f->features_size++;
275 } else {
276 n = (struct lys_node *) ptr;
277 n->features[n->features_size] = (struct lys_feature *) n;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100278 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100279 n->features_size++;
280 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100281
282 lydict_remove(module->ctx, exp);
283 if (ret == -1) {
284
285 return EXIT_FAILURE;
286 }
287 return EXIT_SUCCESS;
288}
289
Pavol Vican4fb66c92016-03-17 10:32:27 +0100290int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200291yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100292{
293 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100294 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100295 return EXIT_FAILURE;
296 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200297 if (shortint) {
298 *((uint8_t *)flags) |= (uint8_t)value;
299 } else {
300 *flags |= value;
301 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100302 return EXIT_SUCCESS;
303 }
304}
305
Pavol Vicanbbdef532016-02-09 14:52:12 +0100306void *
307yang_read_identity(struct lys_module *module, char *value)
308{
309 struct lys_ident *ret;
310
311 ret = &module->ident[module->ident_size];
312 ret->name = lydict_insert_zc(module->ctx, value);
313 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200314 if (dup_identities_check(ret->name, module)) {
315 lydict_remove(module->ctx, ret->name);
316 return NULL;
317 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100318 module->ident_size++;
319 return ret;
320}
321
322int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100323yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100324{
325 const char *exp;
326
Pavol Vicane2368982016-03-19 14:37:56 +0100327 if (!value) {
328 /* base statement not found */
329 return EXIT_SUCCESS;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100330 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100331 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100332 free(value);
333 if (!exp) {
334 return EXIT_FAILURE;
335 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100336 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100337 lydict_remove(module->ctx, exp);
338 return EXIT_FAILURE;
339 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100340
Pavol Vicanbbdef532016-02-09 14:52:12 +0100341 lydict_remove(module->ctx, exp);
342 return EXIT_SUCCESS;
343}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100344
345void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200346yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100347{
348 struct lys_restr *retval;
349
350 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100351 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100352 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100353 break;
354 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100355 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
356 break;
357 case LEAF_KEYWORD:
358 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100359 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100360 case LEAF_LIST_KEYWORD:
361 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
362 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100363 case LIST_KEYWORD:
364 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
365 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100366 case REFINE_KEYWORD:
367 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
368 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100369 case ADD_KEYWORD:
370 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
371 memset(retval, 0, sizeof *retval);
372 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100373 case DELETE_KEYWORD:
374 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
375 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200376 default:
377 goto error;
378 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100379 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100380 retval->expr = transform_schema2json(module, value);
381 if (!retval->expr || lyxp_syntax_check(retval->expr)) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100382 goto error;
383 }
384 free(value);
385 return retval;
386
387error:
388 free(value);
389 return NULL;
390}
391
392int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100393yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100394{
395 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100396
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100397 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100398 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100399 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100400 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100401 }
402 return ret;
403}
Pavol Vicanb5687112016-02-09 22:35:59 +0100404
405int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100406yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100407{
408 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100409 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100410 free(value);
411 return EXIT_FAILURE;
412 } else {
413 cont->presence = lydict_insert_zc(module->ctx, value);
414 return EXIT_SUCCESS;
415 }
416}
417
Pavol Vican235dbd42016-02-10 10:34:19 +0100418void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200419yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100420{
421 struct lys_when *retval;
422
423 retval = calloc(1, sizeof *retval);
424 if (!retval) {
425 LOGMEM;
426 free(value);
427 return NULL;
428 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100429 retval->cond = transform_schema2json(module, value);
430 if (!retval->cond || lyxp_syntax_check(retval->cond)) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100431 goto error;
432 }
433 switch (type) {
434 case CONTAINER_KEYWORD:
435 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100436 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100437 goto error;
438 }
439 ((struct lys_node_container *)node)->when = retval;
440 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100441 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100442 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100443 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100444 goto error;
445 }
446 ((struct lys_node_anyxml *)node)->when = retval;
447 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100448 case CHOICE_KEYWORD:
449 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100450 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100451 goto error;
452 }
453 ((struct lys_node_choice *)node)->when = retval;
454 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100455 case CASE_KEYWORD:
456 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100457 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100458 goto error;
459 }
460 ((struct lys_node_case *)node)->when = retval;
461 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100462 case LEAF_KEYWORD:
463 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100464 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100465 goto error;
466 }
467 ((struct lys_node_leaf *)node)->when = retval;
468 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100469 case LEAF_LIST_KEYWORD:
470 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100471 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100472 goto error;
473 }
474 ((struct lys_node_leaflist *)node)->when = retval;
475 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100476 case LIST_KEYWORD:
477 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100478 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100479 goto error;
480 }
481 ((struct lys_node_list *)node)->when = retval;
482 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100483 case USES_KEYWORD:
484 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100485 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100486 goto error;
487 }
488 ((struct lys_node_uses *)node)->when = retval;
489 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100490 case AUGMENT_KEYWORD:
491 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100492 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100493 goto error;
494 }
495 ((struct lys_node_augment *)node)->when = retval;
496 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200497 default:
498 goto error;
499 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100500 }
501 free(value);
502 return retval;
503
504error:
505 free(value);
506 lys_when_free(module->ctx, retval);
507 return NULL;
508}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100509
510void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100511yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100512{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100513 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100514
Pavol Vican7cadfe72016-02-11 12:33:34 +0100515 node = calloc(1, sizeof_struct);
516 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100517 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100518 LOGMEM;
519 return NULL;
520 }
Pavol Vican531a9132016-03-03 10:10:09 +0100521 if (value) {
522 node->name = lydict_insert_zc(module->ctx, value);
523 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100524 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100525 node->nodetype = nodetype;
526 node->prev = node;
527
528 /* insert the node into the schema tree */
529 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100530 if (value) {
531 lydict_remove(module->ctx, node->name);
532 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100533 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100534 return NULL;
535 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100536 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100537}
538
539int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200540yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100541{
542 int ret;
543
544 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100545 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100546 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100547 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100548 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100549 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100550 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200551 default:
552 free(value);
553 LOGINT;
554 ret = EXIT_FAILURE;
555 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100556 }
557 return ret;
558}
559
560int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200561yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100562{
563 int ret;
564
565 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100566 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100567 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100568 break;
569 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100570 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100571 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100572 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100573 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100574 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200575 default:
576 free(value);
577 LOGINT;
578 ret = EXIT_FAILURE;
579 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100580 }
581 return ret;
582}
Pavol Vican5de33492016-02-22 14:03:24 +0100583
584int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100585yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100586{
587 char *exp, *value;
588
589 exp = value = (char *) list->keys;
590 while ((value = strpbrk(value, " \t\n"))) {
591 list->keys_size++;
592 while (isspace(*value)) {
593 value++;
594 }
595 }
596 list->keys_size++;
597 list->keys = calloc(list->keys_size, sizeof *list->keys);
598 if (!list->keys) {
599 LOGMEM;
600 goto error;
601 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100602 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100603 goto error;
604 }
605 free(exp);
606 return EXIT_SUCCESS;
607
608error:
609 free(exp);
610 return EXIT_FAILURE;
611}
612
613int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100614yang_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 +0100615{
616 int i, j;
617 char *vaux;
618
619 /* count the number of unique leafs in the value */
620 vaux = value;
621 while ((vaux = strpbrk(vaux, " \t\n"))) {
622 unique->expr_size++;
623 while (isspace(*vaux)) {
624 vaux++;
625 }
626 }
627 unique->expr_size++;
628 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
629 if (!unique->expr) {
630 LOGMEM;
631 goto error;
632 }
633
634 for (i = 0; i < unique->expr_size; i++) {
635 vaux = strpbrk(value, " \t\n");
636 if (!vaux) {
637 /* the last token, lydict_insert() will count its size on its own */
638 vaux = value;
639 }
640
641 /* store token into unique structure */
642 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
643
644 /* check that the expression does not repeat */
645 for (j = 0; j < i; j++) {
646 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100647 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
648 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100649 goto error;
650 }
651 }
652 /* try to resolve leaf */
653 if (unres) {
Pavol Vican18b10212016-04-11 15:41:52 +0200654 if (unres_schema_add_str(module, unres, (struct lys_node *) list, UNRES_LIST_UNIQ, unique->expr[i]) == -1) {
655 goto error;
656 }
Pavol Vican85f12022016-03-05 16:30:35 +0100657 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100658 if (resolve_unique((struct lys_node *)list, unique->expr[i])) {
Pavol Vican85f12022016-03-05 16:30:35 +0100659 goto error;
660 }
661 }
662
663 /* move to next token */
664 value = vaux;
665 while(isspace(*value)) {
666 value++;
667 }
668 }
669
670 return EXIT_SUCCESS;
671
672error:
673 return EXIT_FAILURE;
674}
675
676int
Pavol Vican5de33492016-02-22 14:03:24 +0100677yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
678{
679 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100680 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100681
682 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100683 str = (char *)list->unique[k].expr;
684 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100685 goto error;
686 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100687 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100688 }
689 return EXIT_SUCCESS;
690
691error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100692 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100693 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100694}
695
Pavol Vican1ff0e222016-02-26 12:27:01 +0100696static int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100697yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100698{
699 const char *value, *tmp;
700 int rc, ret = EXIT_FAILURE;
701
702 value = tmp = type->info.lref.path;
703 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100704 value = transform_schema2json(module, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100705 if (!value) {
706 goto end;
707 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100708 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100709 lydict_remove(module->ctx, value);
710
711 if (rc == -1) {
712 goto end;
713 }
714
715 ret = EXIT_SUCCESS;
716
717end:
718 lydict_remove(module->ctx, tmp);
719 return ret;
720}
721
Pavol Vican73e7c992016-02-24 12:18:05 +0100722int
723yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
724{
725 int i, rc;
726 int ret = -1;
727 const char *name, *value;
728 LY_DATA_TYPE base;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200729 struct lys_type *type_der;
Pavol Vican73e7c992016-02-24 12:18:05 +0100730
Pavol Vican6b072512016-04-04 10:50:21 +0200731 base = typ->base;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100732 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100733 if (!value) {
734 goto error;
735 }
736
737 i = parse_identifier(value);
738 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100739 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100740 lydict_remove(module->ctx, value);
741 goto error;
742 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200743 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100744 name = value;
745 if (value[i]) {
746 typ->type->module_name = lydict_insert(module->ctx, value, i);
747 name += i;
748 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100749 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100750 lydict_remove(module->ctx, value);
751 goto error;
752 }
753 ++name;
754 }
755
756 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100757 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100758 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200759 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100760 goto error;
761
Michal Vasko01c6fd22016-05-20 11:43:05 +0200762 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100763 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200764 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200765 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100766 ret = EXIT_FAILURE;
767 goto error;
768 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200769 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100770 typ->type->base = typ->type->der->type.base;
771 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100772 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100773 }
774 switch (base) {
775 case LY_TYPE_STRING:
776 if (typ->type->base == LY_TYPE_BINARY) {
777 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100778 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100779 goto error;
780 }
781 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100782 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 +0100783 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100784 goto error;
785 }
786 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100787 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 +0100788 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100789 goto error;
790 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100791 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200792 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100793 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100794 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100795 break;
796 case LY_TYPE_DEC64:
797 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100798 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100799 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100800 goto error;
801 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100802 /* mandatory sub-statement(s) check */
803 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
804 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100805 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100806 goto error;
807 }
808 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
809 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100810 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100811 goto error;
812 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100813 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
814 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100815 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100816 goto error;
817 }
818 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100819 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 +0100820 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100821 goto error;
822 }
823 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200824 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100825 goto error;
826 }
827 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100828 case LY_TYPE_ENUM:
829 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200830 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100831 goto error;
832 }
Pavol Vican03a59442016-03-21 15:23:45 +0100833 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
Pavol Vican79a763d2016-02-25 15:41:27 +0100834 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100835 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Pavol Vican79a763d2016-02-25 15:41:27 +0100836 goto error;
837 }
838 if (typ->type->der->type.der && typ->type->info.enums.count) {
839 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100840 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Pavol Vican79a763d2016-02-25 15:41:27 +0100841 goto error;
842 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100843 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100844 case LY_TYPE_BITS:
845 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200846 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100847 goto error;
848 }
849 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
850 /* type is derived directly from buit-in bits type and bit statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100851 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Pavol Vican03a59442016-03-21 15:23:45 +0100852 goto error;
853 }
854 if (typ->type->der->type.der && typ->type->info.bits.count) {
855 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100856 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Pavol Vican03a59442016-03-21 15:23:45 +0100857 goto error;
858 }
859 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100860 case LY_TYPE_LEAFREF:
Pavol Vican6b072512016-04-04 10:50:21 +0200861 if (typ->type->base == LY_TYPE_IDENT && (typ->flags & LYS_TYPE_BASE)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100862 if (yang_read_identyref(module, typ->type, unres)) {
Pavol Vican1ff0e222016-02-26 12:27:01 +0100863 goto error;
864 }
Pavol Vican191613a2016-02-26 16:21:32 +0100865 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Pavol Vican6b072512016-04-04 10:50:21 +0200866 if (typ->type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +0100867 value = typ->type->info.lref.path;
868 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100869 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100870 lydict_remove(module->ctx, value);
871 if (!typ->type->info.lref.path) {
872 goto error;
873 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100874 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100875 goto error;
876 }
Pavol Vican6b072512016-04-04 10:50:21 +0200877 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100878 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100879 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200880 } else {
881 for (type_der = &typ->type->der->type; !type_der->info.lref.path && type_der->der; type_der = &type_der->der->type);
882 if (!type_der->info.lref.path || !type_der->info.lref.target) {
883 LOGINT;
884 goto error;
885 }
886 /* add pointer to leafref target, only on leaves (not in typedefs) */
887 if (lys_leaf_add_leafref_target(type_der->info.lref.target, (struct lys_node *)typ->type->parent)) {
888 goto error;
889 }
Pavol Vican191613a2016-02-26 16:21:32 +0100890 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100891 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200892 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100893 goto error;
894 }
895 break;
896 case LY_TYPE_IDENT:
897 if (typ->type->der->type.der) {
898 /* this is just a derived type with no base specified/required */
899 break;
900 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100901 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100902 goto error;
903 }
904 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100905 case LY_TYPE_UNION:
906 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200907 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100908 goto error;
909 }
910 if (!typ->type->info.uni.types) {
911 if (typ->type->der->type.der) {
912 /* this is just a derived type with no additional type specified/required */
913 break;
914 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100915 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100916 goto error;
917 }
918 for (i = 0; i < typ->type->info.uni.count; i++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100919 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent)) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100920 goto error;
921 }
922 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100923 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100924 goto error;
925 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100926 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100927 goto error;
928 }
929 }
930 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100931
932 default:
933 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
934 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200935 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +0100936 goto error;
937 }
938 } else {
939 LOGINT;
940 goto error;
941 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100942 }
943 return EXIT_SUCCESS;
944
945error:
946 if (typ->type->module_name) {
947 lydict_remove(module->ctx, typ->type->module_name);
948 typ->type->module_name = NULL;
949 }
950 return ret;
951}
952
953void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200954yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +0100955{
956 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100957 struct type_deviation *dev;
958 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +0100959
Pavol Vicand01d8ae2016-03-01 10:45:59 +0100960 typ = calloc(1, sizeof *typ);
961 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100962 LOGMEM;
963 return NULL;
964 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100965
966 typ->flags = LY_YANG_STRUCTURE_FLAG;
967 switch (type) {
968 case LEAF_KEYWORD:
969 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
970 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
971 typ->type = &((struct lys_node_leaf *)parent)->type;
972 break;
Pavol Vicana55992a2016-03-01 13:37:17 +0100973 case LEAF_LIST_KEYWORD:
974 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
975 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
976 typ->type = &((struct lys_node_leaflist *)parent)->type;
977 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100978 case UNION_KEYWORD:
979 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
980 typ->type = (struct lys_type *)parent;
981 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100982 case TYPEDEF_KEYWORD:
983 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
984 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +0100985 break;
986 case REPLACE_KEYWORD:
987 /* deviation replace type*/
988 dev = (struct type_deviation *)parent;
989 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100990 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +0100991 goto error;
992 }
993 /* check target node type */
994 if (dev->target->nodetype == LYS_LEAF) {
995 typ->type = &((struct lys_node_leaf *)dev->target)->type;
996 } else if (dev->target->nodetype == LYS_LEAFLIST) {
997 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
998 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100999 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1000 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001001 goto error;
1002 }
1003
1004 /* remove type and initialize it */
1005 lys_type_free(module->ctx, typ->type);
1006 tmp_parent = typ->type->parent;
1007 memset(typ->type, 0, sizeof *typ->type);
1008 typ->type->parent = tmp_parent;
1009
1010 /* replace it with the value specified in deviation */
1011 /* HACK for unres */
1012 typ->type->der = (struct lys_tpdf *)typ;
1013 dev->deviate->type = typ->type;
1014 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001015 default:
1016 goto error;
1017 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001018 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001019 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001020 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001021
1022error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001023 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001024 free(typ);
1025 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001026}
1027
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001028void
1029yang_delete_type(struct lys_module *module, struct yang_type *stype)
1030{
1031 int i;
1032
1033 stype->type->base = stype->base;
1034 stype->type->der = NULL;
1035 lydict_remove(module->ctx, stype->name);
1036 if (stype->base == LY_TYPE_UNION) {
1037 for (i = 0; i < stype->type->info.uni.count; i++) {
1038 if (stype->type->info.uni.types[i].der) {
1039 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1040 }
1041 }
1042 }
1043 free(stype);
1044}
1045
Pavol Vican73e7c992016-02-24 12:18:05 +01001046void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001047yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001048{
1049 struct lys_restr **length;
1050
Pavol Vican6b072512016-04-04 10:50:21 +02001051 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001052 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001053 typ->base = LY_TYPE_STRING;
1054 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001055 length = &typ->type->info.binary.length;
1056 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001057 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001058 goto error;
1059 }
1060
1061 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001062 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001063 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001064 }
1065 *length = calloc(1, sizeof **length);
1066 if (!*length) {
1067 LOGMEM;
1068 goto error;
1069 }
1070 (*length)->expr = lydict_insert_zc(module->ctx, value);
1071 return *length;
1072
1073error:
1074 free(value);
1075 return NULL;
1076
1077}
Pavol Vican1c203db2016-02-24 14:05:23 +01001078
1079void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001080yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican1c203db2016-02-24 14:05:23 +01001081{
Michal Vasko0aee5c12016-06-17 14:27:26 +02001082 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001083 free(value);
1084 return NULL;
1085 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001086
1087 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1088 typ->type->info.str.pat_count++;
1089 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1090}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001091
1092void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001093yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001094{
Pavol Vican6b072512016-04-04 10:50:21 +02001095 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001096 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001097 goto error;
1098 }
Pavol Vican6b072512016-04-04 10:50:21 +02001099 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001100 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001101 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001102 goto error;
1103 }
1104 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1105 if (!typ->type->info.dec64.range) {
1106 LOGMEM;
1107 goto error;
1108 }
1109 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1110 return typ->type->info.dec64.range;
1111
1112error:
1113 free(value);
1114 return NULL;
1115}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001116
1117int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001118yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001119{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001120 unsigned int i;
1121
Pavol Vican6b072512016-04-04 10:50:21 +02001122 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1123 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001124 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001125 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001126 goto error;
1127 }
1128 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001129 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001130 goto error;
1131 }
1132 /* range check */
1133 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001134 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001135 goto error;
1136 }
1137 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001138 typ->type->info.dec64.div = 10;
1139 for (i = 1; i < value; i++) {
1140 typ->type->info.dec64.div *= 10;
1141 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001142 return EXIT_SUCCESS;
1143
1144error:
1145 return EXIT_FAILURE;
1146}
Pavol Vican79a763d2016-02-25 15:41:27 +01001147
1148void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001149yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001150{
1151 struct lys_type_enum *enm;
1152 int i;
1153
1154 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1155 enm->name = lydict_insert_zc(module->ctx, value);
1156
1157 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1158 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001159 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001160 goto error;
1161 }
1162
1163 /* check the name uniqueness */
1164 for (i = 0; i < typ->type->info.enums.count; i++) {
1165 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001166 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001167 goto error;
1168 }
1169 }
1170
1171 typ->type->info.enums.count++;
1172 return enm;
1173
1174error:
1175 typ->type->info.enums.count++;
1176 return NULL;
1177}
1178
1179int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001180yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001181{
1182 int i, j;
1183
1184 if (!assign) {
1185 /* assign value automatically */
1186 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001187 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001188 goto error;
1189 }
1190 enm->value = *value;
1191 enm->flags |= LYS_AUTOASSIGNED;
1192 (*value)++;
1193 }
1194
1195 /* check that the value is unique */
1196 j = typ->type->info.enums.count-1;
1197 for (i = 0; i < j; i++) {
1198 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001199 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican79a763d2016-02-25 15:41:27 +01001200 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1201 goto error;
1202 }
1203 }
1204
1205 return EXIT_SUCCESS;
1206
1207error:
1208 return EXIT_FAILURE;
1209}
Pavol Vican9887c682016-02-29 11:32:01 +01001210
1211void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001212yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001213{
1214 int i;
1215 struct lys_type_bit *bit;
1216
1217 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001218 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001219 free(value);
1220 goto error;
1221 }
1222 bit->name = lydict_insert_zc(module->ctx, value);
1223
1224 /* check the name uniqueness */
1225 for (i = 0; i < typ->type->info.bits.count; i++) {
1226 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001227 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001228 typ->type->info.bits.count++;
1229 goto error;
1230 }
1231 }
1232 typ->type->info.bits.count++;
1233 return bit;
1234
1235error:
1236 return NULL;
1237}
1238
1239int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001240yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001241{
1242 int i,j;
1243 struct lys_type_bit bit_tmp;
1244
1245 if (!assign) {
1246 /* assign value automatically */
1247 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001248 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001249 goto error;
1250 }
1251 bit->pos = (uint32_t)*value;
1252 bit->flags |= LYS_AUTOASSIGNED;
1253 (*value)++;
1254 }
1255
1256 j = typ->type->info.bits.count - 1;
1257 /* check that the value is unique */
1258 for (i = 0; i < j; i++) {
1259 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001260 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001261 goto error;
1262 }
1263 }
1264
1265 /* keep them ordered by position */
1266 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1267 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001268 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1269 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1270 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001271 j--;
1272 }
1273
1274 return EXIT_SUCCESS;
1275
1276error:
1277 return EXIT_FAILURE;
1278}
Pavol Vican0df02b02016-03-01 10:28:50 +01001279
1280void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001281yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001282{
1283 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001284 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001285
Pavol Vican810892e2016-07-12 16:55:34 +02001286 root = (parent) ? NULL : lys_main_module(module)->data;
1287 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001288 free(value);
1289 return NULL;
1290 }
Pavol Vican810892e2016-07-12 16:55:34 +02001291
Pavol Vican0df02b02016-03-01 10:28:50 +01001292 if (!parent) {
1293 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001294 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001295 } else {
1296 switch (parent->nodetype) {
1297 case LYS_GROUPING:
1298 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001299 ((struct lys_node_grp *)parent)->tpdf_size++;
1300 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001301 case LYS_CONTAINER:
1302 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1303 ((struct lys_node_container *)parent)->tpdf_size++;
1304 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001305 case LYS_LIST:
1306 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1307 ((struct lys_node_list *)parent)->tpdf_size++;
1308 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001309 case LYS_RPC:
1310 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1311 ((struct lys_node_rpc *)parent)->tpdf_size++;
1312 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001313 case LYS_INPUT:
1314 case LYS_OUTPUT:
1315 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1316 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1317 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001318 case LYS_NOTIF:
1319 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1320 ((struct lys_node_notif *)parent)->tpdf_size++;
1321 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001322 default:
1323 /* another type of nodetype is error*/
1324 LOGINT;
1325 free(value);
1326 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001327 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001328 }
1329
Pavol Vican79436472016-04-04 11:22:02 +02001330 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001331 ret->name = lydict_insert_zc(module->ctx, value);
1332 ret->module = module;
1333 return ret;
1334}
Pavol Vican1003ead2016-03-02 12:24:52 +01001335
1336void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001337yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001338{
1339 struct lys_refine *rfn;
1340
1341 rfn = &uses->refine[uses->refine_size];
1342 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001343 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001344 free(value);
1345 if (!rfn->target_name) {
1346 return NULL;
1347 }
1348 return rfn;
1349}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001350
1351void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001352yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001353{
1354 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001355
1356 if (parent) {
1357 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1358 } else {
1359 aug = &module->augment[module->augment_size];
1360 }
1361 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001362 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001363 free(value);
1364 if (!aug->target_name) {
1365 return NULL;
1366 }
1367 aug->parent = parent;
1368 aug->module = module;
1369 if (parent) {
1370 ((struct lys_node_uses *)parent)->augment_size++;
1371 } else {
1372 module->augment_size++;
1373 }
1374 return aug;
1375}
Pavol Vican220e5a12016-03-03 14:19:43 +01001376
1377void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001378yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001379{
1380 struct lys_node *dev_target = NULL;
1381 struct lys_deviation *dev;
1382 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001383 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001384
Pavol Vican220e5a12016-03-03 14:19:43 +01001385 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001386 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001387 free(value);
1388 if (!dev->target_name) {
1389 goto error;
1390 }
1391
Pavol Vican974377b2016-03-23 00:38:53 +01001392 deviation = calloc(1, sizeof *deviation);
1393 if (!deviation) {
1394 LOGMEM;
1395 goto error;
1396 }
1397
Pavol Vican220e5a12016-03-03 14:19:43 +01001398 /* resolve target node */
1399 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1400 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001401 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001402 goto error;
1403 }
Radek Krejcic4283442016-04-22 09:19:27 +02001404 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001405 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1406 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001407 goto error;
1408 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001409
1410 lys_deviation_add_ext_imports(lys_node_module(dev_target), module);
1411
Pavol Vican220e5a12016-03-03 14:19:43 +01001412 /*save pointer to the deviation and deviated target*/
1413 deviation->deviation = dev;
1414 deviation->target = dev_target;
1415
Pavol Vican220e5a12016-03-03 14:19:43 +01001416 return deviation;
1417
1418error:
1419 free(deviation);
1420 lydict_remove(module->ctx, dev->target_name);
1421 return NULL;
1422}
Pavol Vican4c90c642016-03-03 15:06:47 +01001423
1424int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001425yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001426{
1427 int i;
1428
1429 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001430 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001431 return EXIT_FAILURE;
1432 }
1433 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1434
1435 /* you cannot remove a key leaf */
1436 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1437 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1438 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001439 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1440 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001441 return EXIT_FAILURE;
1442 }
1443 }
1444 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001445
Pavol Vican4c90c642016-03-03 15:06:47 +01001446 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001447 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001448 dev->deviation->orig_node = dev->target;
1449
1450 dev->deviation->deviate_size = 1;
1451 return EXIT_SUCCESS;
1452}
Pavol Vican85f12022016-03-05 16:30:35 +01001453
1454int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001455yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001456{
1457 struct unres_schema tmp_unres;
1458
1459 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1460 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1461 dev->deviation->deviate_size++;
1462 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001463 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1464 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001465 return EXIT_FAILURE;
1466 }
1467
1468 /* store a shallow copy of the original node */
1469 if (!dev->deviation->orig_node) {
1470 memset(&tmp_unres, 0, sizeof tmp_unres);
1471 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1472 /* just to be safe */
1473 if (tmp_unres.count) {
1474 LOGINT;
1475 return EXIT_FAILURE;
1476 }
1477 }
1478
1479 return EXIT_SUCCESS;
1480}
1481
1482int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001483yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001484{
1485 const char **stritem;
1486
1487 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001488 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001489 free(value);
1490 goto error;
1491 }
1492
1493 /* check target node type */
1494 if (dev->target->nodetype == LYS_LEAFLIST) {
1495 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1496 } else if (dev->target->nodetype == LYS_LEAF) {
1497 stritem = &((struct lys_node_leaf *)dev->target)->units;
1498 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001499 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1500 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001501 free(value);
1502 goto error;
1503 }
1504
1505 dev->deviate->units = lydict_insert_zc(ctx, value);
1506
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001507 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1508 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001509 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001510 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1511 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001512 goto error;
1513 }
1514 /* remove current units value of the target */
1515 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001516 } else {
1517 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1518 /* check that there is no current value */
1519 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001520 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1521 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001522 goto error;
1523 }
1524 } else { /* replace */
1525 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001526 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1527 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001528 goto error;
1529 }
1530 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001531 /* remove current units value of the target ... */
1532 lydict_remove(ctx, *stritem);
1533
1534 /* ... and replace it with the value specified in deviation */
1535 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1536 }
1537
Pavol Vican85f12022016-03-05 16:30:35 +01001538 return EXIT_SUCCESS;
1539
1540error:
1541 return EXIT_FAILURE;
1542}
1543
1544int
Pavol Vican974377b2016-03-23 00:38:53 +01001545yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001546{
Pavol Vican85f12022016-03-05 16:30:35 +01001547 /* check target node type */
1548 switch (dev->target->nodetype) {
1549 case LYS_LEAF:
1550 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1551 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1552 break;
1553 case LYS_CONTAINER:
1554 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1555 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1556 break;
1557 case LYS_LEAFLIST:
1558 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1559 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1560 break;
1561 case LYS_LIST:
1562 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1563 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1564 break;
1565 case LYS_ANYXML:
1566 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1567 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1568 break;
1569 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001570 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1571 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001572 goto error;
1573 }
1574
1575 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1576 /* reallocate the must array of the target */
1577 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1578 if (!dev->deviate->must) {
1579 LOGMEM;
1580 goto error;
1581 }
1582 *dev->trg_must = dev->deviate->must;
1583 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1584 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001585 } else {
1586 /* LY_DEVIATE_DEL */
1587 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1588 if (!dev->deviate->must) {
1589 LOGMEM;
1590 goto error;
1591 }
Pavol Vican85f12022016-03-05 16:30:35 +01001592 }
1593
1594 return EXIT_SUCCESS;
1595
1596error:
1597 return EXIT_FAILURE;
1598}
1599
1600int
Pavol Vican974377b2016-03-23 00:38:53 +01001601yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001602{
Pavol Vican85f12022016-03-05 16:30:35 +01001603 struct lys_node_list *list;
1604
1605 /* check target node type */
1606 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001607 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1608 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001609 goto error;
1610 }
1611
1612 list = (struct lys_node_list *)dev->target;
1613 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1614 /* reallocate the unique array of the target */
1615 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1616 if (!dev->deviate->unique) {
1617 LOGMEM;
1618 goto error;
1619 }
1620 list->unique = dev->deviate->unique;
1621 dev->deviate->unique = &list->unique[list->unique_size];
1622 dev->deviate->unique_size = c_uniq;
1623 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001624 } else {
1625 /* LY_DEVIATE_DEL */
1626 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1627 if (!dev->deviate->unique) {
1628 LOGMEM;
1629 goto error;
1630 }
Pavol Vican85f12022016-03-05 16:30:35 +01001631 }
1632
1633 return EXIT_SUCCESS;
1634
1635error:
1636 return EXIT_FAILURE;
1637}
1638
1639int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001640yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001641{
1642 int rc;
1643 struct lys_node_choice *choice;
1644 struct lys_node_leaf *leaf;
1645 struct lys_node *node;
1646
1647 if (dev->deviate->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001648 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001649 free(value);
1650 goto error;
1651 }
1652
1653 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1654
1655 if (dev->target->nodetype == LYS_CHOICE) {
1656 choice = (struct lys_node_choice *)dev->target;
1657
Pavol Vican85f12022016-03-05 16:30:35 +01001658 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1659 if (rc || !node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001660 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vican85f12022016-03-05 16:30:35 +01001661 goto error;
1662 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001663 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1664 if (!choice->dflt || (choice->dflt != node)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001665 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1666 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001667 goto error;
1668 }
1669 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001670 } else {
1671 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1672 /* check that there is no current value */
1673 if (choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001674 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1675 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001676 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001677 } else if (choice->flags & LYS_MAND_TRUE) {
1678 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
1679 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
1680 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001681 }
1682 } else { /* replace*/
1683 if (!choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001684 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1685 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001686 goto error;
1687 }
1688 }
1689
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001690 choice->dflt = node;
1691 if (!choice->dflt) {
1692 /* default branch not found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001693 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001694 goto error;
1695 }
Pavol Vican85f12022016-03-05 16:30:35 +01001696 }
1697 } else if (dev->target->nodetype == LYS_LEAF) {
1698 leaf = (struct lys_node_leaf *)dev->target;
1699
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001700 if (dev->deviate->mod == LY_DEVIATE_DEL) {
Michal Vaskob42b6972016-06-06 14:21:30 +02001701 if (!leaf->dflt || !ly_strequal(leaf->dflt, dev->deviate->dflt, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001702 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1703 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001704 goto error;
1705 }
1706 /* remove value */
1707 lydict_remove(ctx, leaf->dflt);
1708 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001709 } else {
1710 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1711 /* check that there is no current value */
1712 if (leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001713 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1714 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001715 goto error;
Pavol Vicanfdf81c42016-04-05 15:55:31 +02001716 } else if (leaf->flags & LYS_MAND_TRUE) {
1717 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1718 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "leaf");
1719 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on leaf with \"mandatory\".");
1720 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001721 }
1722 } else { /* replace*/
1723 if (!leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001724 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1725 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001726 goto error;
1727 }
1728 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001729 /* remove value */
1730 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001731
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001732 /* set new value */
1733 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1734 }
Pavol Vican85f12022016-03-05 16:30:35 +01001735 } else {
1736 /* invalid target for default value */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001737 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1738 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001739 goto error;
1740 }
1741
1742 return EXIT_SUCCESS;
1743
1744error:
1745 return EXIT_FAILURE;
1746}
1747
1748int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001749yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001750{
1751 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001752 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001753 goto error;
1754 }
1755
1756 /* for we deviate from RFC 6020 and allow config property even it is/is not
1757 * specified in the target explicitly since config property inherits. So we expect
1758 * that config is specified in every node. But for delete, we check that the value
1759 * is the same as here in deviation
1760 */
1761 dev->deviate->flags |= value;
1762
1763 /* add and replace are the same in this case */
1764 /* remove current config value of the target ... */
1765 dev->target->flags &= ~LYS_CONFIG_MASK;
1766
1767 /* ... and replace it with the value specified in deviation */
1768 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1769
1770 return EXIT_SUCCESS;
1771
1772error:
1773 return EXIT_FAILURE;
1774}
1775
1776int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001777yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001778{
1779 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001780 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001781 goto error;
1782 }
1783
1784 /* check target node type */
1785 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001786 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1787 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001788 goto error;
1789 }
1790
1791 dev->deviate->flags |= value;
1792
1793 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1794 /* check that there is no current value */
1795 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001796 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1797 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001798 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001799 } else {
1800 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
1801 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1802 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1803 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1804 goto error;
1805 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
1806 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1807 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1808 goto error;
1809 }
Pavol Vican85f12022016-03-05 16:30:35 +01001810 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001811 } else { /* replace */
1812 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001813 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1814 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001815 goto error;
1816 }
Pavol Vican85f12022016-03-05 16:30:35 +01001817 }
1818
Pavol Vican85f12022016-03-05 16:30:35 +01001819 /* remove current mandatory value of the target ... */
1820 dev->target->flags &= ~LYS_MAND_MASK;
1821
1822 /* ... and replace it with the value specified in deviation */
1823 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1824
1825 return EXIT_SUCCESS;
1826
1827error:
1828 return EXIT_FAILURE;
1829}
1830
1831int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001832yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001833{
1834 uint32_t *ui32val;
1835
1836 /* check target node type */
1837 if (dev->target->nodetype == LYS_LEAFLIST) {
1838 if (type) {
1839 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1840 } else {
1841 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1842 }
1843 } else if (dev->target->nodetype == LYS_LIST) {
1844 if (type) {
1845 ui32val = &((struct lys_node_list *)dev->target)->max;
1846 } else {
1847 ui32val = &((struct lys_node_list *)dev->target)->min;
1848 }
1849 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001850 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1851 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 +01001852 goto error;
1853 }
1854
1855 if (type) {
1856 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001857 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001858 } else {
1859 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001860 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001861 }
1862
1863 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1864 /* check that there is no current value */
1865 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001866 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1867 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001868 goto error;
1869 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001870 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1871 /* unfortunately, there is no way to check reliably that there
1872 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001873 }
1874
1875 /* add (already checked) and replace */
1876 /* set new value specified in deviation */
1877 *ui32val = value;
1878
1879 return EXIT_SUCCESS;
1880
1881error:
1882 return EXIT_FAILURE;
1883}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001884
1885int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001886yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001887{
1888 int i;
1889
1890 /* find must to delete, we are ok with just matching conditions */
1891 for (i = 0; i < *dev->trg_must_size; i++) {
1892 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1893 /* we have a match, free the must structure ... */
1894 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1895 /* ... and maintain the array */
1896 (*dev->trg_must_size)--;
1897 if (i != *dev->trg_must_size) {
1898 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1899 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1900 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1901 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1902 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1903 }
1904 if (!(*dev->trg_must_size)) {
1905 free(*dev->trg_must);
1906 *dev->trg_must = NULL;
1907 } else {
1908 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1909 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1910 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1911 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1912 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1913 }
1914
1915 i = -1; /* set match flag */
1916 break;
1917 }
1918 }
1919 if (i != -1) {
1920 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001921 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1922 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001923 return EXIT_FAILURE;
1924 }
1925
1926 return EXIT_SUCCESS;
1927}
1928
1929int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001930yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001931{
1932 struct lys_node_list *list;
1933 int i, j;
1934
1935 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001936 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001937 dev->deviate->unique_size++;
1938 goto error;
1939 }
1940
1941 /* find unique structures to delete */
1942 for (i = 0; i < list->unique_size; i++) {
1943 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1944 continue;
1945 }
1946
1947 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1948 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1949 break;
1950 }
1951 }
1952
1953 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1954 /* we have a match, free the unique structure ... */
1955 for (j = 0; j < list->unique[i].expr_size; j++) {
1956 lydict_remove(module->ctx, list->unique[i].expr[j]);
1957 }
1958 free(list->unique[i].expr);
1959 /* ... and maintain the array */
1960 list->unique_size--;
1961 if (i != list->unique_size) {
1962 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1963 list->unique[i].expr = list->unique[list->unique_size].expr;
1964 }
1965
1966 if (!list->unique_size) {
1967 free(list->unique);
1968 list->unique = NULL;
1969 } else {
1970 list->unique[list->unique_size].expr_size = 0;
1971 list->unique[list->unique_size].expr = NULL;
1972 }
1973
1974 i = -1; /* set match flag */
1975 break;
1976 }
1977 }
1978 dev->deviate->unique_size++;
1979
1980 if (i != -1) {
1981 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001982 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001984 goto error;
1985 }
1986
1987 free(value);
1988 return EXIT_SUCCESS;
1989
1990error:
1991 free(value);
1992 return EXIT_FAILURE;
1993}
Pavol Vicane92421d2016-03-08 10:12:33 +01001994
1995int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001996yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01001997{
1998 int i, rc;
1999
2000 if (dev->target->nodetype == LYS_LEAF) {
2001 for(i = 0; i < dev->deviation->deviate_size; ++i) {
2002 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
2003 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002004 rc = unres_schema_add_str(module, unres, &((struct lys_node_leaf *)dev->target)->type, UNRES_TYPE_DFLT, ((struct lys_node_leaf *)dev->target)->dflt);
Pavol Vicane92421d2016-03-08 10:12:33 +01002005 if (rc == -1) {
2006 return EXIT_FAILURE;
2007 } else if (rc == EXIT_FAILURE) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002008 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->deviation->target_name);
Pavol Vicane92421d2016-03-08 10:12:33 +01002009 return EXIT_FAILURE;
2010 }
2011 break;
2012 }
2013 }
2014 }
2015 }
2016 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002017}
2018
2019int
2020yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Radek Krejci4dcd3392016-06-22 10:28:40 +02002021 char *rev, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002022{
2023 struct lys_include inc;
2024 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002025 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002026 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002027 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002028
Pavol Vican55870412016-03-10 12:36:21 +01002029 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002030 trg = (submodule) ? (struct lys_module *)submodule : module;
2031 inc.submodule = NULL;
2032 inc.external = 0;
2033 memcpy(inc.rev, rev, LY_REV_SIZE);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002034 rc = lyp_check_include(module, submodule, str, &inc, unres);
2035 if (!rc) {
2036 /* success, copy the filled data into the final array */
Radek Krejci4dcd3392016-06-22 10:28:40 +02002037 memcpy(&trg->inc[trg->inc_size], &inc, sizeof inc);
2038 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002039 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002040 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002041 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002042
Pavol Vican55870412016-03-10 12:36:21 +01002043 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002044 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002045}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002046
2047int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002048yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002049{
2050 char *prefix;
2051 char *identif;
2052 const char *ns = NULL;
2053 int i;
2054
Pavol Vicanf4717e62016-03-16 11:30:01 +01002055 /* check to the same pointer */
2056 if (data_node != actual) {
2057 return EXIT_SUCCESS;
2058 }
2059
Pavol Vicana302aa62016-03-17 10:45:35 +01002060 prefix = strdup(value);
2061 if (!prefix) {
2062 LOGMEM;
2063 goto error;
2064 }
2065 /* find prefix anf identificator*/
2066 identif = strchr(prefix, ':');
2067 *identif = '\0';
2068 identif++;
2069
Pavol Vicanf4717e62016-03-16 11:30:01 +01002070 for(i = 0; i < module->imp_size; ++i) {
2071 if (!strcmp(module->imp[i].prefix, prefix)) {
2072 ns = module->imp[i].module->ns;
2073 break;
2074 }
2075 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002076 if (!ns && !strcmp(module->prefix, prefix)) {
2077 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2078 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002079 if (ns && !strcmp(ns, LY_NSNACM)) {
2080 if (!strcmp(identif, "default-deny-write")) {
2081 data_node->nacm |= LYS_NACM_DENYW;
2082 } else if (!strcmp(identif, "default-deny-all")) {
2083 data_node->nacm |= LYS_NACM_DENYA;
2084 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002085 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002086 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002087 }
2088 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002089 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002090 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002091
2092error:
2093 free(prefix);
2094 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002095}
2096
2097void
2098nacm_inherit(struct lys_module *module)
2099{
Pavol Vican10ffba52016-04-04 12:21:22 +02002100 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002101
2102 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002103 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002104 if (elem->parent) {
2105 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002106 case LYS_GROUPING:
2107 /* extension nacm not inherited*/
2108 break;
2109 case LYS_CHOICE:
2110 case LYS_ANYXML:
2111 case LYS_USES:
2112 if (elem->parent->nodetype != LYS_GROUPING) {
2113 elem->nacm |= elem->parent->nacm;
2114 }
2115 break;
2116 case LYS_CONTAINER:
2117 case LYS_LIST:
2118 case LYS_CASE:
2119 case LYS_NOTIF:
2120 case LYS_RPC:
2121 case LYS_INPUT:
2122 case LYS_OUTPUT:
2123 case LYS_AUGMENT:
2124 elem->nacm |= elem->parent->nacm;
2125 break;
2126 case LYS_LEAF:
2127 case LYS_LEAFLIST:
2128 tmp_node = elem;
2129 tmp_child = elem->child;
2130 elem->child = NULL;
2131 default:
2132 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002133 }
2134 }
2135 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002136 if (tmp_node) {
2137 tmp_node->child = tmp_child;
2138 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002139 }
2140}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002141
2142void
2143store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2144{
2145 node->flags |= flags;
2146 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2147 /* get config flag from parent */
2148 if (node->parent) {
2149 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2150 } else {
2151 /* default config is true */
2152 node->flags |= LYS_CONFIG_W;
2153 }
2154 }
2155}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002156
Pavol Vican1938d882016-04-10 13:36:31 +02002157static int
2158yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2159 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002160{
2161 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002162 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002163 int ret = EXIT_SUCCESS;
2164
2165 yylex_init(&scanner);
2166 bp = yy_scan_buffer((char *)data, size, scanner);
2167 yy_switch_to_buffer(bp, scanner);
2168 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2169 ret = EXIT_FAILURE;
2170 }
2171 yy_delete_buffer(bp, scanner);
2172 yylex_destroy(scanner);
2173 return ret;
2174}
2175
2176int
2177yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2178{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002179 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002180 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002181 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002182
2183 size_arrays = calloc(1, sizeof *size_arrays);
2184 if (!size_arrays) {
2185 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002186 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002187 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002188 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002189 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2190 if (!ret) {
2191 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002192 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002193 free(size_arrays->node);
2194 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002195 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002196}
2197
2198struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002199yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002200{
2201
Pavol Vican10ffba52016-04-04 12:21:22 +02002202 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002203 struct unres_schema *unres = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002204 int i;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002205
2206 unres = calloc(1, sizeof *unres);
2207 if (!unres) {
2208 LOGMEM;
2209 goto error;
2210 }
2211
2212 module = calloc(1, sizeof *module);
2213 if (!module) {
2214 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002215 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002216 }
2217
2218 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002219 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002220 module->type = 0;
2221 module->implemented = (implement ? 1 : 0);
2222
2223 if (yang_parse_mem(module, NULL, unres, data, size)) {
2224 goto error;
2225 }
2226
2227 if (module && unres->count && resolve_unres_schema(module, unres)) {
2228 goto error;
2229 }
2230
2231 if (revision) {
2232 /* check revision of the parsed model */
2233 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2234 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2235 module->name, module->rev[0].date, revision);
2236 goto error;
2237 }
2238 }
2239
Pavol Vican10ffba52016-04-04 12:21:22 +02002240 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002241 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002242 goto error;
2243 }
2244
Pavol Vican10ffba52016-04-04 12:21:22 +02002245 if (module == tmp_module) {
2246 nacm_inherit(module);
2247 }
2248
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002249 if (module->augment_size || module->deviation_size) {
Michal Vasko5cec3312016-05-04 08:59:41 +02002250 if (!module->implemented) {
2251 LOGVRB("Module \"%s\" includes augments or deviations, changing conformance to \"implement\".", module->name);
2252 }
Michal Vasko26055752016-05-03 11:36:31 +02002253 if (lys_module_set_implement(module)) {
2254 goto error;
2255 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002256
Michal Vasko26055752016-05-03 11:36:31 +02002257 if (lys_sub_module_set_dev_aug_target_implement(module)) {
2258 goto error;
2259 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002260 for (i = 0; i < module->inc_size; ++i) {
Radek Krejci4dcd3392016-06-22 10:28:40 +02002261 if (!module->inc[i].submodule) {
2262 continue;
2263 }
Michal Vasko26055752016-05-03 11:36:31 +02002264 if (lys_sub_module_set_dev_aug_target_implement((struct lys_module *)module->inc[i].submodule)) {
2265 goto error;
2266 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002267 }
2268 }
2269
Pavol Vican8e7110b2016-03-22 17:00:26 +01002270 unres_schema_free(NULL, &unres);
2271 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2272 return module;
2273
2274error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002275 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002276 unres_schema_free(module, &unres);
2277 if (!module || !module->name) {
2278 free(module);
2279 LOGERR(ly_errno, "Module parsing failed.");
2280 return NULL;
2281 }
2282
2283 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002284
2285 lys_sub_module_remove_devs_augs(module);
2286 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002287 return NULL;
2288}
2289
2290struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002291yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002292{
2293 struct lys_submodule *submodule;
2294
2295 submodule = calloc(1, sizeof *submodule);
2296 if (!submodule) {
2297 LOGMEM;
2298 goto error;
2299 }
2300
2301 submodule->ctx = module->ctx;
2302 submodule->type = 1;
2303 submodule->belongsto = module;
2304
2305 if (yang_parse_mem(module, submodule, unres, data, size)) {
2306 goto error;
2307 }
2308
Pavol Vican8e7110b2016-03-22 17:00:26 +01002309 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002310 return submodule;
2311
2312error:
2313 /* cleanup */
2314 unres_schema_free((struct lys_module *)submodule, &unres);
2315
2316 if (!submodule || !submodule->name) {
2317 free(submodule);
2318 LOGERR(ly_errno, "Submodule parsing failed.");
2319 return NULL;
2320 }
2321
2322 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2323
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002324 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2325 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002326 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002327 return NULL;
2328}
Pavol Vican8760bb72016-04-07 09:44:01 +02002329
2330static int
2331count_substring(const char *str, char c)
2332{
2333 const char *tmp = str;
2334 int count = 0;
2335
2336 while ((tmp = strchr(tmp, c))) {
2337 tmp++;
2338 count++;
2339 }
2340 return count;
2341}
2342
2343static int
2344read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2345{
2346 int k = 0, j;
2347
2348 while (in_index < size) {
2349 if (input[in_index] == ' ') {
2350 k++;
2351 } else if (input[in_index] == '\t') {
2352 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2353 k += 8;
2354 } else {
2355 break;
2356 }
2357 ++in_index;
2358 if (k >= indent) {
2359 for (j = k - indent; j > 0; --j) {
2360 output[*out_index] = ' ';
2361 ++(*out_index);
2362 }
2363 break;
2364 }
2365 }
2366 return in_index;
2367}
2368
2369char *
2370yang_read_string(const char *input, int size, int indent)
2371{
2372 int space, count;
2373 int in_index, out_index;
2374 char *value;
2375 char *retval = NULL;
2376
2377 value = malloc(size + 1);
2378 if (!value) {
2379 LOGMEM;
2380 return NULL;
2381 }
2382 /* replace special character in escape sequence */
2383 in_index = out_index = 0;
2384 while (in_index < size) {
2385 if (input[in_index] == '\\') {
2386 if (input[in_index + 1] == 'n') {
2387 value[out_index] = '\n';
2388 ++in_index;
2389 } else if (input[in_index + 1] == 't') {
2390 value[out_index] = '\t';
2391 ++in_index;
2392 } else if (input[in_index + 1] == '\\') {
2393 value[out_index] = '\\';
2394 ++in_index;
2395 } else if ((in_index + 1) != size && input[in_index + 1] == '"') {
2396 value[out_index] = '"';
2397 ++in_index;
2398 } else {
2399 value[out_index] = input[in_index];
2400 }
2401 } else {
2402 value[out_index] = input[in_index];
2403 }
2404 ++in_index;
2405 ++out_index;
2406 }
2407 value[out_index] = '\0';
2408 size = out_index;
2409 count = count_substring(value, '\t');
2410
2411 /* extend size of string due to replacing character '\t' with 8 spaces */
2412 retval = malloc(size + 1 + 7 * count);
2413 if (!retval) {
2414 LOGMEM;
2415 goto error;
2416 }
2417 in_index = out_index = space = 0;
2418 while (in_index < size) {
2419 if (value[in_index] == '\n') {
2420 out_index -= space;
2421 space = 0;
2422 retval[out_index] = '\n';
2423 ++out_index;
2424 ++in_index;
2425 in_index = read_indent(value, indent, size, in_index, &out_index, retval);
2426 continue;
2427 } else {
2428 space = (value[in_index] == ' ' || value[in_index] == '\t') ? space + 1 : 0;
2429 retval[out_index] = value[in_index];
2430 ++out_index;
2431 }
2432 ++in_index;
2433 }
2434 retval[out_index] = '\0';
2435 if (out_index != size) {
2436 retval = ly_realloc(retval, out_index + 1);
2437 }
2438 free(value);
2439 return retval;
2440error:
2441 free(value);
2442 return NULL;
2443}