blob: f54e02c5605e94b1bf8dd8a9184bfa7b24599976 [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 Vican1c203db2016-02-24 14:05:23 +010016#include <pcre.h>
Pavol Vican021488a2016-01-25 23:56:12 +010017#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010018#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010019#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010020#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010021
Pavol Vican2a064652016-02-02 22:54:34 +010022static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010023yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010024{
Pavol Vicanbf805472016-01-26 14:24:56 +010025 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010026 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010027 free(value);
28 return 1;
29 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010030 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010031 return 0;
32 }
33}
34
Pavol Vican2a064652016-02-02 22:54:34 +010035int
Pavol Vican5f0316a2016-04-05 21:21:11 +020036yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010037{
Pavol Vican6eb14e82016-02-03 12:27:13 +010038 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010039
40 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010041 case MODULE_KEYWORD:
42 module->name = lydict_insert_zc(module->ctx, value);
43 break;
44 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010045 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010046 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010047 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010048 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010049 break;
50 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010051 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010052 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020053 default:
54 free(value);
55 LOGINT;
56 ret = EXIT_FAILURE;
57 break;
Pavol Vican2a064652016-02-02 22:54:34 +010058 }
59
Pavol Vican021488a2016-01-25 23:56:12 +010060 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010061}
62
Pavol Vican2a064652016-02-02 22:54:34 +010063int
Pavol Vican5f0316a2016-04-05 21:21:11 +020064yang_read_prefix(struct lys_module *module, void *save, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010065{
Pavol Vican6eb14e82016-02-03 12:27:13 +010066 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010067
Pavol Vican0adf01d2016-03-22 12:29:33 +010068 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +010069 free(value);
70 return EXIT_FAILURE;
71 }
Pavol Vicanbf805472016-01-26 14:24:56 +010072 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +010073 case MODULE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010074 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010075 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010076 case IMPORT_KEYWORD:
77 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
78 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020079 default:
80 free(value);
81 LOGINT;
82 ret = EXIT_FAILURE;
83 break;
Pavol Vican2a064652016-02-02 22:54:34 +010084 }
Pavol Vican6eb14e82016-02-03 12:27:13 +010085
Pavol Vicanbf805472016-01-26 14:24:56 +010086 return ret;
87}
Pavol Vican6eb14e82016-02-03 12:27:13 +010088
Pavol Vican6eb14e82016-02-03 12:27:13 +010089int
Pavol Vican0adf01d2016-03-22 12:29:33 +010090yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +010091{
Pavol Vican0da132e2016-03-21 12:03:03 +010092 const char *exp;
93 int rc, i;
Pavol Vican6eb14e82016-02-03 12:27:13 +010094
Pavol Vican0da132e2016-03-21 12:03:03 +010095 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +010096 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +010097 lydict_remove(module->ctx, exp);
98 if (rc) {
Pavol Vican6eb14e82016-02-03 12:27:13 +010099 goto error;
100 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100101
102 /* check duplicities in imported modules */
Pavol Vican0da132e2016-03-21 12:03:03 +0100103 for (i = 0; i < module->imp_size; i++) {
104 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size].module->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100105 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, module->imp[i].module->name, "import");
106 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Pavol Vican6eb14e82016-02-03 12:27:13 +0100107 goto error;
108 }
109 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100110 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100111 return EXIT_SUCCESS;
112
Pavol Vican0da132e2016-03-21 12:03:03 +0100113error:
114 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100115 return EXIT_FAILURE;
116}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100117
118int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100119yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100120{
121 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100122 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100123
124 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100125 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100126 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100127 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100128 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100129 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100130 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100131 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100132 }
133 return ret;
134}
135
136int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100137yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100138{
139 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100140 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100141
142 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100143 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100144 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100145 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100146 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100147 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100148 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100149 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100150 }
151 return ret;
152}
Pavol Vicanbedff692016-02-03 14:29:17 +0100153
154void *
155yang_read_revision(struct lys_module *module, char *value)
156{
157 struct lys_revision *retval;
158
Pavol Vican1eeb1992016-02-09 11:10:45 +0100159 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100160
161 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100162 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100163 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
164 memcpy(module->rev[0].date, value, LY_REV_SIZE);
165 retval->dsc = module->rev[0].dsc;
166 retval->ref = module->rev[0].ref;
167 retval = module->rev;
168 retval->dsc = NULL;
169 retval->ref = NULL;
170 } else {
171 memcpy(retval->date, value, LY_REV_SIZE);
172 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100173 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100174 free(value);
175 return retval;
176}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100177
178int
Pavol Vicana1827962016-02-29 15:39:42 +0100179yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100180{
Pavol Vican45ccc592016-03-09 18:53:48 +0100181 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100182 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
183 LOGMEM;
184 return EXIT_FAILURE;
185 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100186 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100187 }
188 }
189 (*size)++;
190 return EXIT_SUCCESS;
191}
Pavol Vicane1354e92016-02-09 14:02:09 +0100192
193void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100194yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100195{
196 struct lys_feature *retval;
197
198 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100199 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100200 goto error;
201 }
202 retval = &module->features[module->features_size];
203 retval->name = lydict_insert_zc(module->ctx, value);
204 retval->module = module;
205 module->features_size++;
206 return retval;
207
208error:
209 free(value);
210 return NULL;
211}
212
213int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200214yang_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 +0100215{
216 const char *exp;
217 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100218 struct lys_feature *f;
219 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100220
Pavol Vican0adf01d2016-03-22 12:29:33 +0100221 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100222 free(value);
223 return EXIT_FAILURE;
224 }
225 free(value);
226
227 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100228 if (type == FEATURE_KEYWORD) {
229 f = (struct lys_feature *) ptr;
230 f->features[f->features_size] = f;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100231 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100232 f->features_size++;
233 } else {
234 n = (struct lys_node *) ptr;
235 n->features[n->features_size] = (struct lys_feature *) n;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100236 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100237 n->features_size++;
238 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100239
240 lydict_remove(module->ctx, exp);
241 if (ret == -1) {
242
243 return EXIT_FAILURE;
244 }
245 return EXIT_SUCCESS;
246}
247
Pavol Vican4fb66c92016-03-17 10:32:27 +0100248int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100249yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100250{
251 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100252 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100253 return EXIT_FAILURE;
254 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100255 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100256 return EXIT_SUCCESS;
257 }
258}
259
Pavol Vicanbbdef532016-02-09 14:52:12 +0100260void *
261yang_read_identity(struct lys_module *module, char *value)
262{
263 struct lys_ident *ret;
264
265 ret = &module->ident[module->ident_size];
266 ret->name = lydict_insert_zc(module->ctx, value);
267 ret->module = module;
268 module->ident_size++;
269 return ret;
270}
271
272int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100273yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100274{
275 const char *exp;
276
Pavol Vicane2368982016-03-19 14:37:56 +0100277 if (!value) {
278 /* base statement not found */
279 return EXIT_SUCCESS;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100280 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100281 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100282 free(value);
283 if (!exp) {
284 return EXIT_FAILURE;
285 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100286 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100287 lydict_remove(module->ctx, exp);
288 return EXIT_FAILURE;
289 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100290
Pavol Vicanbbdef532016-02-09 14:52:12 +0100291 lydict_remove(module->ctx, exp);
292 return EXIT_SUCCESS;
293}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100294
295void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200296yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100297{
298 struct lys_restr *retval;
299
300 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100301 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100302 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100303 break;
304 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100305 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
306 break;
307 case LEAF_KEYWORD:
308 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100309 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100310 case LEAF_LIST_KEYWORD:
311 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
312 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100313 case LIST_KEYWORD:
314 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
315 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100316 case REFINE_KEYWORD:
317 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
318 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100319 case ADD_KEYWORD:
320 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
321 memset(retval, 0, sizeof *retval);
322 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100323 case DELETE_KEYWORD:
324 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
325 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200326 default:
327 goto error;
328 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100329 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100330 retval->expr = transform_schema2json(module, value);
331 if (!retval->expr || lyxp_syntax_check(retval->expr)) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100332 goto error;
333 }
334 free(value);
335 return retval;
336
337error:
338 free(value);
339 return NULL;
340}
341
342int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100343yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100344{
345 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100346
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100347 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100348 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100349 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100350 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100351 }
352 return ret;
353}
Pavol Vicanb5687112016-02-09 22:35:59 +0100354
355int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100356yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100357{
358 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100359 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100360 free(value);
361 return EXIT_FAILURE;
362 } else {
363 cont->presence = lydict_insert_zc(module->ctx, value);
364 return EXIT_SUCCESS;
365 }
366}
367
Pavol Vican235dbd42016-02-10 10:34:19 +0100368void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200369yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100370{
371 struct lys_when *retval;
372
373 retval = calloc(1, sizeof *retval);
374 if (!retval) {
375 LOGMEM;
376 free(value);
377 return NULL;
378 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100379 retval->cond = transform_schema2json(module, value);
380 if (!retval->cond || lyxp_syntax_check(retval->cond)) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100381 goto error;
382 }
383 switch (type) {
384 case CONTAINER_KEYWORD:
385 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100386 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100387 goto error;
388 }
389 ((struct lys_node_container *)node)->when = retval;
390 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100391 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100392 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100393 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100394 goto error;
395 }
396 ((struct lys_node_anyxml *)node)->when = retval;
397 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100398 case CHOICE_KEYWORD:
399 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100400 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100401 goto error;
402 }
403 ((struct lys_node_choice *)node)->when = retval;
404 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100405 case CASE_KEYWORD:
406 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100407 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100408 goto error;
409 }
410 ((struct lys_node_case *)node)->when = retval;
411 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100412 case LEAF_KEYWORD:
413 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100414 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100415 goto error;
416 }
417 ((struct lys_node_leaf *)node)->when = retval;
418 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100419 case LEAF_LIST_KEYWORD:
420 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100421 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100422 goto error;
423 }
424 ((struct lys_node_leaflist *)node)->when = retval;
425 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100426 case LIST_KEYWORD:
427 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100428 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100429 goto error;
430 }
431 ((struct lys_node_list *)node)->when = retval;
432 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100433 case USES_KEYWORD:
434 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100435 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100436 goto error;
437 }
438 ((struct lys_node_uses *)node)->when = retval;
439 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100440 case AUGMENT_KEYWORD:
441 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100442 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100443 goto error;
444 }
445 ((struct lys_node_augment *)node)->when = retval;
446 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200447 default:
448 goto error;
449 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100450 }
451 free(value);
452 return retval;
453
454error:
455 free(value);
456 lys_when_free(module->ctx, retval);
457 return NULL;
458}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100459
460void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100461yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100462{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100463 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100464
Pavol Vican7cadfe72016-02-11 12:33:34 +0100465 node = calloc(1, sizeof_struct);
466 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100467 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100468 LOGMEM;
469 return NULL;
470 }
Pavol Vican531a9132016-03-03 10:10:09 +0100471 if (value) {
472 node->name = lydict_insert_zc(module->ctx, value);
473 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100474 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100475 node->nodetype = nodetype;
476 node->prev = node;
477
478 /* insert the node into the schema tree */
479 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100480 if (value) {
481 lydict_remove(module->ctx, node->name);
482 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100483 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100484 return NULL;
485 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100486 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100487}
488
489int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200490yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100491{
492 int ret;
493
494 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100495 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100496 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100497 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100498 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100499 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100500 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200501 default:
502 free(value);
503 LOGINT;
504 ret = EXIT_FAILURE;
505 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100506 }
507 return ret;
508}
509
510int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200511yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100512{
513 int ret;
514
515 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100516 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100517 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100518 break;
519 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100520 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100521 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100522 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100523 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100524 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200525 default:
526 free(value);
527 LOGINT;
528 ret = EXIT_FAILURE;
529 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100530 }
531 return ret;
532}
Pavol Vican5de33492016-02-22 14:03:24 +0100533
534int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100535yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100536{
537 char *exp, *value;
538
539 exp = value = (char *) list->keys;
540 while ((value = strpbrk(value, " \t\n"))) {
541 list->keys_size++;
542 while (isspace(*value)) {
543 value++;
544 }
545 }
546 list->keys_size++;
547 list->keys = calloc(list->keys_size, sizeof *list->keys);
548 if (!list->keys) {
549 LOGMEM;
550 goto error;
551 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100552 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100553 goto error;
554 }
555 free(exp);
556 return EXIT_SUCCESS;
557
558error:
559 free(exp);
560 return EXIT_FAILURE;
561}
562
563int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100564yang_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 +0100565{
566 int i, j;
567 char *vaux;
568
569 /* count the number of unique leafs in the value */
570 vaux = value;
571 while ((vaux = strpbrk(vaux, " \t\n"))) {
572 unique->expr_size++;
573 while (isspace(*vaux)) {
574 vaux++;
575 }
576 }
577 unique->expr_size++;
578 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
579 if (!unique->expr) {
580 LOGMEM;
581 goto error;
582 }
583
584 for (i = 0; i < unique->expr_size; i++) {
585 vaux = strpbrk(value, " \t\n");
586 if (!vaux) {
587 /* the last token, lydict_insert() will count its size on its own */
588 vaux = value;
589 }
590
591 /* store token into unique structure */
592 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
593
594 /* check that the expression does not repeat */
595 for (j = 0; j < i; j++) {
596 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100597 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
598 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100599 goto error;
600 }
601 }
602 /* try to resolve leaf */
603 if (unres) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100604 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i]);
Pavol Vican85f12022016-03-05 16:30:35 +0100605 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100606 if (resolve_unique((struct lys_node *)list, unique->expr[i])) {
Pavol Vican85f12022016-03-05 16:30:35 +0100607 goto error;
608 }
609 }
610
611 /* move to next token */
612 value = vaux;
613 while(isspace(*value)) {
614 value++;
615 }
616 }
617
618 return EXIT_SUCCESS;
619
620error:
621 return EXIT_FAILURE;
622}
623
624int
Pavol Vican5de33492016-02-22 14:03:24 +0100625yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
626{
627 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100628 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100629
630 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100631 str = (char *)list->unique[k].expr;
632 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100633 goto error;
634 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100635 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100636 }
637 return EXIT_SUCCESS;
638
639error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100640 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100641 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100642}
643
Pavol Vican1ff0e222016-02-26 12:27:01 +0100644static int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100645yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100646{
647 const char *value, *tmp;
648 int rc, ret = EXIT_FAILURE;
649
650 value = tmp = type->info.lref.path;
651 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100652 value = transform_schema2json(module, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100653 if (!value) {
654 goto end;
655 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100656 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100657 lydict_remove(module->ctx, value);
658
659 if (rc == -1) {
660 goto end;
661 }
662
663 ret = EXIT_SUCCESS;
664
665end:
666 lydict_remove(module->ctx, tmp);
667 return ret;
668}
669
Pavol Vican73e7c992016-02-24 12:18:05 +0100670int
671yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
672{
673 int i, rc;
674 int ret = -1;
675 const char *name, *value;
676 LY_DATA_TYPE base;
677
Pavol Vican6b072512016-04-04 10:50:21 +0200678 base = typ->base;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100679 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100680 if (!value) {
681 goto error;
682 }
683
684 i = parse_identifier(value);
685 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100686 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100687 lydict_remove(module->ctx, value);
688 goto error;
689 }
690 /* module name*/
691 name = value;
692 if (value[i]) {
693 typ->type->module_name = lydict_insert(module->ctx, value, i);
694 name += i;
695 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100696 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100697 lydict_remove(module->ctx, value);
698 goto error;
699 }
700 ++name;
701 }
702
703 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
704 lydict_remove(module->ctx, value);
705 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100706 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100707 goto error;
708
709 /* the type could not be resolved or it was resolved to an unresolved typedef*/
710 } else if (rc == EXIT_FAILURE) {
711 ret = EXIT_FAILURE;
712 goto error;
713 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100714 typ->type->base = typ->type->der->type.base;
715 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100716 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100717 }
718 switch (base) {
719 case LY_TYPE_STRING:
720 if (typ->type->base == LY_TYPE_BINARY) {
721 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100723 goto error;
724 }
725 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100726 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 +0100727 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100728 goto error;
729 }
730 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100731 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 +0100732 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100733 goto error;
734 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100735 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200736 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100737 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100738 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100739 break;
740 case LY_TYPE_DEC64:
741 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100742 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 +0100743 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100744 goto error;
745 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100746 /* mandatory sub-statement(s) check */
747 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
748 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100749 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100750 goto error;
751 }
752 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
753 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100754 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100755 goto error;
756 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100757 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
758 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100759 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100760 goto error;
761 }
762 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100763 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 +0100764 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100765 goto error;
766 }
767 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200768 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100769 goto error;
770 }
771 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100772 case LY_TYPE_ENUM:
773 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200774 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100775 goto error;
776 }
Pavol Vican03a59442016-03-21 15:23:45 +0100777 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
Pavol Vican79a763d2016-02-25 15:41:27 +0100778 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100779 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Pavol Vican79a763d2016-02-25 15:41:27 +0100780 goto error;
781 }
782 if (typ->type->der->type.der && typ->type->info.enums.count) {
783 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100784 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Pavol Vican79a763d2016-02-25 15:41:27 +0100785 goto error;
786 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100787 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100788 case LY_TYPE_BITS:
789 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200790 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100791 goto error;
792 }
793 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
794 /* type is derived directly from buit-in bits type and bit statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100795 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Pavol Vican03a59442016-03-21 15:23:45 +0100796 goto error;
797 }
798 if (typ->type->der->type.der && typ->type->info.bits.count) {
799 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100800 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Pavol Vican03a59442016-03-21 15:23:45 +0100801 goto error;
802 }
803 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100804 case LY_TYPE_LEAFREF:
Pavol Vican6b072512016-04-04 10:50:21 +0200805 if (typ->type->base == LY_TYPE_IDENT && (typ->flags & LYS_TYPE_BASE)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100806 if (yang_read_identyref(module, typ->type, unres)) {
Pavol Vican1ff0e222016-02-26 12:27:01 +0100807 goto error;
808 }
Pavol Vican191613a2016-02-26 16:21:32 +0100809 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Pavol Vican6b072512016-04-04 10:50:21 +0200810 if (typ->type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +0100811 value = typ->type->info.lref.path;
812 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100813 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100814 lydict_remove(module->ctx, value);
815 if (!typ->type->info.lref.path) {
816 goto error;
817 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100818 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100819 goto error;
820 }
Pavol Vican6b072512016-04-04 10:50:21 +0200821 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100822 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100823 goto error;
Pavol Vican191613a2016-02-26 16:21:32 +0100824 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100825 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200826 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100827 goto error;
828 }
829 break;
830 case LY_TYPE_IDENT:
831 if (typ->type->der->type.der) {
832 /* this is just a derived type with no base specified/required */
833 break;
834 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100835 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100836 goto error;
837 }
838 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100839 case LY_TYPE_UNION:
840 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200841 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100842 goto error;
843 }
844 if (!typ->type->info.uni.types) {
845 if (typ->type->der->type.der) {
846 /* this is just a derived type with no additional type specified/required */
847 break;
848 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100849 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100850 goto error;
851 }
852 for (i = 0; i < typ->type->info.uni.count; i++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100853 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent)) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100854 goto error;
855 }
856 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100857 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100858 goto error;
859 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100860 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100861 goto error;
862 }
863 }
864 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100865
866 default:
867 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
868 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200869 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +0100870 goto error;
871 }
872 } else {
873 LOGINT;
874 goto error;
875 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100876 }
877 return EXIT_SUCCESS;
878
879error:
880 if (typ->type->module_name) {
881 lydict_remove(module->ctx, typ->type->module_name);
882 typ->type->module_name = NULL;
883 }
884 return ret;
885}
886
887void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200888yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +0100889{
890 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100891 struct type_deviation *dev;
892 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +0100893
Pavol Vicand01d8ae2016-03-01 10:45:59 +0100894 typ = calloc(1, sizeof *typ);
895 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100896 LOGMEM;
897 return NULL;
898 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100899
900 typ->flags = LY_YANG_STRUCTURE_FLAG;
901 switch (type) {
902 case LEAF_KEYWORD:
903 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
904 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
905 typ->type = &((struct lys_node_leaf *)parent)->type;
906 break;
Pavol Vicana55992a2016-03-01 13:37:17 +0100907 case LEAF_LIST_KEYWORD:
908 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
909 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
910 typ->type = &((struct lys_node_leaflist *)parent)->type;
911 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100912 case UNION_KEYWORD:
913 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
914 typ->type = (struct lys_type *)parent;
915 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100916 case TYPEDEF_KEYWORD:
917 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
918 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +0100919 break;
920 case REPLACE_KEYWORD:
921 /* deviation replace type*/
922 dev = (struct type_deviation *)parent;
923 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100924 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +0100925 goto error;
926 }
927 /* check target node type */
928 if (dev->target->nodetype == LYS_LEAF) {
929 typ->type = &((struct lys_node_leaf *)dev->target)->type;
930 } else if (dev->target->nodetype == LYS_LEAFLIST) {
931 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
932 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100933 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
934 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +0100935 goto error;
936 }
937
938 /* remove type and initialize it */
939 lys_type_free(module->ctx, typ->type);
940 tmp_parent = typ->type->parent;
941 memset(typ->type, 0, sizeof *typ->type);
942 typ->type->parent = tmp_parent;
943
944 /* replace it with the value specified in deviation */
945 /* HACK for unres */
946 typ->type->der = (struct lys_tpdf *)typ;
947 dev->deviate->type = typ->type;
948 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200949 default:
950 goto error;
951 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100952 }
Pavol Vican5f0316a2016-04-05 21:21:11 +0200953 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100954 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100955
956error:
Pavol Vican5f0316a2016-04-05 21:21:11 +0200957 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +0100958 free(typ);
959 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +0100960}
961
962void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100963yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +0100964{
965 struct lys_restr **length;
966
Pavol Vican6b072512016-04-04 10:50:21 +0200967 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100968 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +0200969 typ->base = LY_TYPE_STRING;
970 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100971 length = &typ->type->info.binary.length;
972 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100973 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100974 goto error;
975 }
976
977 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100978 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vican73e7c992016-02-24 12:18:05 +0100979 }
980 *length = calloc(1, sizeof **length);
981 if (!*length) {
982 LOGMEM;
983 goto error;
984 }
985 (*length)->expr = lydict_insert_zc(module->ctx, value);
986 return *length;
987
988error:
989 free(value);
990 return NULL;
991
992}
Pavol Vican1c203db2016-02-24 14:05:23 +0100993
994void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100995yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican1c203db2016-02-24 14:05:23 +0100996{
997 pcre *precomp;
998 int err_offset;
999 const char *err_ptr;
1000
1001 /* check that the regex is valid */
1002 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1003 if (!precomp) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001004 LOGVAL(LYE_INREGEX, LY_VLOG_NONE, NULL, value, err_ptr);
Pavol Vican1c203db2016-02-24 14:05:23 +01001005 free(value);
1006 return NULL;
1007 }
1008 free(precomp);
1009
1010 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1011 typ->type->info.str.pat_count++;
1012 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1013}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001014
1015void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001016yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001017{
Pavol Vican6b072512016-04-04 10:50:21 +02001018 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001019 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001020 goto error;
1021 }
Pavol Vican6b072512016-04-04 10:50:21 +02001022 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001023 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001024 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001025 goto error;
1026 }
1027 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1028 if (!typ->type->info.dec64.range) {
1029 LOGMEM;
1030 goto error;
1031 }
1032 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1033 return typ->type->info.dec64.range;
1034
1035error:
1036 free(value);
1037 return NULL;
1038}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001039
1040int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001041yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001042{
Pavol Vican6b072512016-04-04 10:50:21 +02001043 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1044 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001045 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001046 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001047 goto error;
1048 }
1049 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001050 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001051 goto error;
1052 }
1053 /* range check */
1054 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001055 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001056 goto error;
1057 }
1058 typ->type->info.dec64.dig = value;
1059 return EXIT_SUCCESS;
1060
1061error:
1062 return EXIT_FAILURE;
1063}
Pavol Vican79a763d2016-02-25 15:41:27 +01001064
1065void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001066yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001067{
1068 struct lys_type_enum *enm;
1069 int i;
1070
1071 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1072 enm->name = lydict_insert_zc(module->ctx, value);
1073
1074 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1075 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001076 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001077 goto error;
1078 }
1079
1080 /* check the name uniqueness */
1081 for (i = 0; i < typ->type->info.enums.count; i++) {
1082 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 +01001083 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001084 goto error;
1085 }
1086 }
1087
1088 typ->type->info.enums.count++;
1089 return enm;
1090
1091error:
1092 typ->type->info.enums.count++;
1093 return NULL;
1094}
1095
1096int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001097yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001098{
1099 int i, j;
1100
1101 if (!assign) {
1102 /* assign value automatically */
1103 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001104 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001105 goto error;
1106 }
1107 enm->value = *value;
1108 enm->flags |= LYS_AUTOASSIGNED;
1109 (*value)++;
1110 }
1111
1112 /* check that the value is unique */
1113 j = typ->type->info.enums.count-1;
1114 for (i = 0; i < j; i++) {
1115 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001116 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican79a763d2016-02-25 15:41:27 +01001117 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1118 goto error;
1119 }
1120 }
1121
1122 return EXIT_SUCCESS;
1123
1124error:
1125 return EXIT_FAILURE;
1126}
Pavol Vican9887c682016-02-29 11:32:01 +01001127
1128void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001129yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001130{
1131 int i;
1132 struct lys_type_bit *bit;
1133
1134 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001135 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001136 free(value);
1137 goto error;
1138 }
1139 bit->name = lydict_insert_zc(module->ctx, value);
1140
1141 /* check the name uniqueness */
1142 for (i = 0; i < typ->type->info.bits.count; i++) {
1143 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001144 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001145 typ->type->info.bits.count++;
1146 goto error;
1147 }
1148 }
1149 typ->type->info.bits.count++;
1150 return bit;
1151
1152error:
1153 return NULL;
1154}
1155
1156int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001157yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001158{
1159 int i,j;
1160 struct lys_type_bit bit_tmp;
1161
1162 if (!assign) {
1163 /* assign value automatically */
1164 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001165 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001166 goto error;
1167 }
1168 bit->pos = (uint32_t)*value;
1169 bit->flags |= LYS_AUTOASSIGNED;
1170 (*value)++;
1171 }
1172
1173 j = typ->type->info.bits.count - 1;
1174 /* check that the value is unique */
1175 for (i = 0; i < j; i++) {
1176 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001177 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001178 goto error;
1179 }
1180 }
1181
1182 /* keep them ordered by position */
1183 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1184 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001185 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1186 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1187 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001188 j--;
1189 }
1190
1191 return EXIT_SUCCESS;
1192
1193error:
1194 return EXIT_FAILURE;
1195}
Pavol Vican0df02b02016-03-01 10:28:50 +01001196
1197void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001198yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001199{
1200 struct lys_tpdf *ret;
1201
Pavol Vican0adf01d2016-03-22 12:29:33 +01001202 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001203 free(value);
1204 return NULL;
1205 }
1206 if (!parent) {
1207 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001208 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001209 } else {
1210 switch (parent->nodetype) {
1211 case LYS_GROUPING:
1212 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001213 ((struct lys_node_grp *)parent)->tpdf_size++;
1214 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001215 case LYS_CONTAINER:
1216 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1217 ((struct lys_node_container *)parent)->tpdf_size++;
1218 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001219 case LYS_LIST:
1220 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1221 ((struct lys_node_list *)parent)->tpdf_size++;
1222 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001223 case LYS_RPC:
1224 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1225 ((struct lys_node_rpc *)parent)->tpdf_size++;
1226 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001227 case LYS_INPUT:
1228 case LYS_OUTPUT:
1229 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1230 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1231 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001232 case LYS_NOTIF:
1233 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1234 ((struct lys_node_notif *)parent)->tpdf_size++;
1235 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001236 default:
1237 /* another type of nodetype is error*/
1238 LOGINT;
1239 free(value);
1240 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001241 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001242 }
1243
Pavol Vican79436472016-04-04 11:22:02 +02001244 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001245 ret->name = lydict_insert_zc(module->ctx, value);
1246 ret->module = module;
1247 return ret;
1248}
Pavol Vican1003ead2016-03-02 12:24:52 +01001249
1250void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001251yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001252{
1253 struct lys_refine *rfn;
1254
1255 rfn = &uses->refine[uses->refine_size];
1256 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001257 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001258 free(value);
1259 if (!rfn->target_name) {
1260 return NULL;
1261 }
1262 return rfn;
1263}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001264
1265void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001266yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001267{
1268 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001269
1270 if (parent) {
1271 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1272 } else {
1273 aug = &module->augment[module->augment_size];
1274 }
1275 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001276 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001277 free(value);
1278 if (!aug->target_name) {
1279 return NULL;
1280 }
1281 aug->parent = parent;
1282 aug->module = module;
1283 if (parent) {
1284 ((struct lys_node_uses *)parent)->augment_size++;
1285 } else {
1286 module->augment_size++;
1287 }
1288 return aug;
1289}
Pavol Vican220e5a12016-03-03 14:19:43 +01001290
1291void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001292yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001293{
1294 struct lys_node *dev_target = NULL;
1295 struct lys_deviation *dev;
1296 struct type_deviation *deviation = NULL;
1297 int i, j, rc;
1298
Pavol Vican220e5a12016-03-03 14:19:43 +01001299 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001300 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001301 free(value);
1302 if (!dev->target_name) {
1303 goto error;
1304 }
1305
Pavol Vican974377b2016-03-23 00:38:53 +01001306 deviation = calloc(1, sizeof *deviation);
1307 if (!deviation) {
1308 LOGMEM;
1309 goto error;
1310 }
1311
Pavol Vican220e5a12016-03-03 14:19:43 +01001312 /* resolve target node */
1313 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1314 if (rc || !dev_target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001315 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
Pavol Vican220e5a12016-03-03 14:19:43 +01001316 goto error;
1317 }
1318 if (dev_target->module == lys_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001319 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1320 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001321 goto error;
1322 }
1323 /*save pointer to the deviation and deviated target*/
1324 deviation->deviation = dev;
1325 deviation->target = dev_target;
1326
1327 /* mark the target module as deviated */
1328 dev_target->module->deviated = 1;
1329
1330 /* copy our imports to the deviated module (deviations may need them to work) */
1331 for (i = 0; i < module->imp_size; ++i) {
1332 for (j = 0; j < dev_target->module->imp_size; ++j) {
1333 if (module->imp[i].module == dev_target->module->imp[j].module) {
1334 break;
1335 }
1336 }
1337
1338 if (j < dev_target->module->imp_size) {
1339 /* import is already there */
1340 continue;
1341 }
1342
1343 /* copy the import, mark it as external */
1344 ++dev_target->module->imp_size;
1345 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1346 if (!dev_target->module->imp) {
1347 LOGMEM;
1348 goto error;
1349 }
1350 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1351 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1352 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1353 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1354 }
1355
1356 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1357 for (i = 0; i < dev_target->module->imp_size; ++i) {
1358 if (dev_target->module->imp[i].module == module) {
1359 break;
1360 }
1361 }
1362
1363 if (i == dev_target->module->imp_size) {
1364 ++dev_target->module->imp_size;
1365 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1366 if (!dev_target->module->imp) {
1367 LOGMEM;
1368 goto error;
1369 }
1370 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1371 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1372 if (module->rev_size) {
1373 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1374 } else {
1375 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1376 }
1377 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1378 } else {
1379 /* it could have been added by another deviating module that imported this deviating module */
1380 dev_target->module->imp[i].external = 2;
1381 }
1382
1383
1384 return deviation;
1385
1386error:
1387 free(deviation);
1388 lydict_remove(module->ctx, dev->target_name);
1389 return NULL;
1390}
Pavol Vican4c90c642016-03-03 15:06:47 +01001391
1392int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001393yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001394{
1395 int i;
1396
1397 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001398 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001399 return EXIT_FAILURE;
1400 }
1401 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1402
1403 /* you cannot remove a key leaf */
1404 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1405 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1406 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001407 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1408 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001409 return EXIT_FAILURE;
1410 }
1411 }
1412 }
1413
1414 /* unlink and store the original node */
1415 dev->deviation->orig_node = dev->target;
1416
1417 dev->deviation->deviate_size = 1;
1418 return EXIT_SUCCESS;
1419}
Pavol Vican85f12022016-03-05 16:30:35 +01001420
1421int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001422yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001423{
1424 struct unres_schema tmp_unres;
1425
1426 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1427 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1428 dev->deviation->deviate_size++;
1429 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001430 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1431 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001432 return EXIT_FAILURE;
1433 }
1434
1435 /* store a shallow copy of the original node */
1436 if (!dev->deviation->orig_node) {
1437 memset(&tmp_unres, 0, sizeof tmp_unres);
1438 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1439 /* just to be safe */
1440 if (tmp_unres.count) {
1441 LOGINT;
1442 return EXIT_FAILURE;
1443 }
1444 }
1445
1446 return EXIT_SUCCESS;
1447}
1448
1449int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001450yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001451{
1452 const char **stritem;
1453
1454 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001455 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001456 free(value);
1457 goto error;
1458 }
1459
1460 /* check target node type */
1461 if (dev->target->nodetype == LYS_LEAFLIST) {
1462 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1463 } else if (dev->target->nodetype == LYS_LEAF) {
1464 stritem = &((struct lys_node_leaf *)dev->target)->units;
1465 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001466 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1467 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001468 free(value);
1469 goto error;
1470 }
1471
1472 dev->deviate->units = lydict_insert_zc(ctx, value);
1473
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001474 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1475 /* check values */
1476 if (*stritem != dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001477 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1478 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001479 goto error;
1480 }
1481 /* remove current units value of the target */
1482 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001483 } else {
1484 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1485 /* check that there is no current value */
1486 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001487 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1488 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001489 goto error;
1490 }
1491 } else { /* replace */
1492 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001493 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1494 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001495 goto error;
1496 }
1497 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001498 /* remove current units value of the target ... */
1499 lydict_remove(ctx, *stritem);
1500
1501 /* ... and replace it with the value specified in deviation */
1502 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1503 }
1504
Pavol Vican85f12022016-03-05 16:30:35 +01001505 return EXIT_SUCCESS;
1506
1507error:
1508 return EXIT_FAILURE;
1509}
1510
1511int
Pavol Vican974377b2016-03-23 00:38:53 +01001512yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001513{
Pavol Vican85f12022016-03-05 16:30:35 +01001514 /* check target node type */
1515 switch (dev->target->nodetype) {
1516 case LYS_LEAF:
1517 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1518 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1519 break;
1520 case LYS_CONTAINER:
1521 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1522 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1523 break;
1524 case LYS_LEAFLIST:
1525 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1526 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1527 break;
1528 case LYS_LIST:
1529 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1530 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1531 break;
1532 case LYS_ANYXML:
1533 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1534 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1535 break;
1536 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001537 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1538 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001539 goto error;
1540 }
1541
1542 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1543 /* reallocate the must array of the target */
1544 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1545 if (!dev->deviate->must) {
1546 LOGMEM;
1547 goto error;
1548 }
1549 *dev->trg_must = dev->deviate->must;
1550 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1551 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001552 } else {
1553 /* LY_DEVIATE_DEL */
1554 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1555 if (!dev->deviate->must) {
1556 LOGMEM;
1557 goto error;
1558 }
Pavol Vican85f12022016-03-05 16:30:35 +01001559 }
1560
1561 return EXIT_SUCCESS;
1562
1563error:
1564 return EXIT_FAILURE;
1565}
1566
1567int
Pavol Vican974377b2016-03-23 00:38:53 +01001568yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001569{
Pavol Vican85f12022016-03-05 16:30:35 +01001570 struct lys_node_list *list;
1571
1572 /* check target node type */
1573 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001574 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1575 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001576 goto error;
1577 }
1578
1579 list = (struct lys_node_list *)dev->target;
1580 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1581 /* reallocate the unique array of the target */
1582 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1583 if (!dev->deviate->unique) {
1584 LOGMEM;
1585 goto error;
1586 }
1587 list->unique = dev->deviate->unique;
1588 dev->deviate->unique = &list->unique[list->unique_size];
1589 dev->deviate->unique_size = c_uniq;
1590 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001591 } else {
1592 /* LY_DEVIATE_DEL */
1593 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1594 if (!dev->deviate->unique) {
1595 LOGMEM;
1596 goto error;
1597 }
Pavol Vican85f12022016-03-05 16:30:35 +01001598 }
1599
1600 return EXIT_SUCCESS;
1601
1602error:
1603 return EXIT_FAILURE;
1604}
1605
1606int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001607yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001608{
1609 int rc;
1610 struct lys_node_choice *choice;
1611 struct lys_node_leaf *leaf;
1612 struct lys_node *node;
1613
1614 if (dev->deviate->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001615 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001616 free(value);
1617 goto error;
1618 }
1619
1620 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1621
1622 if (dev->target->nodetype == LYS_CHOICE) {
1623 choice = (struct lys_node_choice *)dev->target;
1624
Pavol Vican85f12022016-03-05 16:30:35 +01001625 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1626 if (rc || !node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001627 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vican85f12022016-03-05 16:30:35 +01001628 goto error;
1629 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001630 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1631 if (!choice->dflt || (choice->dflt != node)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001632 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1633 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001634 goto error;
1635 }
1636 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001637 } else {
1638 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1639 /* check that there is no current value */
1640 if (choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001641 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1642 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001643 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001644 } else if (choice->flags & LYS_MAND_TRUE) {
1645 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice");
1646 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
1647 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001648 }
1649 } else { /* replace*/
1650 if (!choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001651 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1652 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001653 goto error;
1654 }
1655 }
1656
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001657 choice->dflt = node;
1658 if (!choice->dflt) {
1659 /* default branch not found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001660 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001661 goto error;
1662 }
Pavol Vican85f12022016-03-05 16:30:35 +01001663 }
1664 } else if (dev->target->nodetype == LYS_LEAF) {
1665 leaf = (struct lys_node_leaf *)dev->target;
1666
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001667 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1668 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001669 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1670 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001671 goto error;
1672 }
1673 /* remove value */
1674 lydict_remove(ctx, leaf->dflt);
1675 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001676 } else {
1677 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1678 /* check that there is no current value */
1679 if (leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001680 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1681 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001682 goto error;
Pavol Vicanfdf81c42016-04-05 15:55:31 +02001683 } else if (leaf->flags & LYS_MAND_TRUE) {
1684 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1685 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "leaf");
1686 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on leaf with \"mandatory\".");
1687 goto error;
Pavol Vican4766aca2016-03-07 12:42:36 +01001688 }
1689 } else { /* replace*/
1690 if (!leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001691 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1692 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001693 goto error;
1694 }
1695 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001696 /* remove value */
1697 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001698
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001699 /* set new value */
1700 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1701 }
Pavol Vican85f12022016-03-05 16:30:35 +01001702 } else {
1703 /* invalid target for default value */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001704 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1705 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001706 goto error;
1707 }
1708
1709 return EXIT_SUCCESS;
1710
1711error:
1712 return EXIT_FAILURE;
1713}
1714
1715int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001716yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001717{
1718 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001719 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001720 goto error;
1721 }
1722
1723 /* for we deviate from RFC 6020 and allow config property even it is/is not
1724 * specified in the target explicitly since config property inherits. So we expect
1725 * that config is specified in every node. But for delete, we check that the value
1726 * is the same as here in deviation
1727 */
1728 dev->deviate->flags |= value;
1729
1730 /* add and replace are the same in this case */
1731 /* remove current config value of the target ... */
1732 dev->target->flags &= ~LYS_CONFIG_MASK;
1733
1734 /* ... and replace it with the value specified in deviation */
1735 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1736
1737 return EXIT_SUCCESS;
1738
1739error:
1740 return EXIT_FAILURE;
1741}
1742
1743int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001744yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001745{
1746 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001747 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001748 goto error;
1749 }
1750
1751 /* check target node type */
1752 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001753 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1754 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001755 goto error;
1756 }
1757
1758 dev->deviate->flags |= value;
1759
1760 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1761 /* check that there is no current value */
1762 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001763 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1764 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001765 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001766 } else {
1767 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
1768 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1769 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1770 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1771 goto error;
1772 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
1773 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1774 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1775 goto error;
1776 }
Pavol Vican85f12022016-03-05 16:30:35 +01001777 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001778 } else { /* replace */
1779 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001780 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1781 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001782 goto error;
1783 }
Pavol Vican85f12022016-03-05 16:30:35 +01001784 }
1785
Pavol Vican85f12022016-03-05 16:30:35 +01001786 /* remove current mandatory value of the target ... */
1787 dev->target->flags &= ~LYS_MAND_MASK;
1788
1789 /* ... and replace it with the value specified in deviation */
1790 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1791
1792 return EXIT_SUCCESS;
1793
1794error:
1795 return EXIT_FAILURE;
1796}
1797
1798int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001799yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001800{
1801 uint32_t *ui32val;
1802
1803 /* check target node type */
1804 if (dev->target->nodetype == LYS_LEAFLIST) {
1805 if (type) {
1806 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1807 } else {
1808 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1809 }
1810 } else if (dev->target->nodetype == LYS_LIST) {
1811 if (type) {
1812 ui32val = &((struct lys_node_list *)dev->target)->max;
1813 } else {
1814 ui32val = &((struct lys_node_list *)dev->target)->min;
1815 }
1816 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001817 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1818 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 +01001819 goto error;
1820 }
1821
1822 if (type) {
1823 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001824 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001825 } else {
1826 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001827 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001828 }
1829
1830 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1831 /* check that there is no current value */
1832 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001833 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1834 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001835 goto error;
1836 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001837 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1838 /* unfortunately, there is no way to check reliably that there
1839 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001840 }
1841
1842 /* add (already checked) and replace */
1843 /* set new value specified in deviation */
1844 *ui32val = value;
1845
1846 return EXIT_SUCCESS;
1847
1848error:
1849 return EXIT_FAILURE;
1850}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001851
1852int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001853yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001854{
1855 int i;
1856
1857 /* find must to delete, we are ok with just matching conditions */
1858 for (i = 0; i < *dev->trg_must_size; i++) {
1859 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1860 /* we have a match, free the must structure ... */
1861 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1862 /* ... and maintain the array */
1863 (*dev->trg_must_size)--;
1864 if (i != *dev->trg_must_size) {
1865 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1866 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1867 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1868 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1869 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1870 }
1871 if (!(*dev->trg_must_size)) {
1872 free(*dev->trg_must);
1873 *dev->trg_must = NULL;
1874 } else {
1875 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1876 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1877 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1878 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1879 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1880 }
1881
1882 i = -1; /* set match flag */
1883 break;
1884 }
1885 }
1886 if (i != -1) {
1887 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001888 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1889 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001890 return EXIT_FAILURE;
1891 }
1892
1893 return EXIT_SUCCESS;
1894}
1895
1896int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001897yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001898{
1899 struct lys_node_list *list;
1900 int i, j;
1901
1902 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001903 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001904 dev->deviate->unique_size++;
1905 goto error;
1906 }
1907
1908 /* find unique structures to delete */
1909 for (i = 0; i < list->unique_size; i++) {
1910 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1911 continue;
1912 }
1913
1914 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1915 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1916 break;
1917 }
1918 }
1919
1920 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1921 /* we have a match, free the unique structure ... */
1922 for (j = 0; j < list->unique[i].expr_size; j++) {
1923 lydict_remove(module->ctx, list->unique[i].expr[j]);
1924 }
1925 free(list->unique[i].expr);
1926 /* ... and maintain the array */
1927 list->unique_size--;
1928 if (i != list->unique_size) {
1929 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1930 list->unique[i].expr = list->unique[list->unique_size].expr;
1931 }
1932
1933 if (!list->unique_size) {
1934 free(list->unique);
1935 list->unique = NULL;
1936 } else {
1937 list->unique[list->unique_size].expr_size = 0;
1938 list->unique[list->unique_size].expr = NULL;
1939 }
1940
1941 i = -1; /* set match flag */
1942 break;
1943 }
1944 }
1945 dev->deviate->unique_size++;
1946
1947 if (i != -1) {
1948 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001949 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1950 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001951 goto error;
1952 }
1953
1954 free(value);
1955 return EXIT_SUCCESS;
1956
1957error:
1958 free(value);
1959 return EXIT_FAILURE;
1960}
Pavol Vicane92421d2016-03-08 10:12:33 +01001961
1962int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001963yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01001964{
1965 int i, rc;
1966
1967 if (dev->target->nodetype == LYS_LEAF) {
1968 for(i = 0; i < dev->deviation->deviate_size; ++i) {
1969 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
1970 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001971 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 +01001972 if (rc == -1) {
1973 return EXIT_FAILURE;
1974 } else if (rc == EXIT_FAILURE) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001975 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 +01001976 return EXIT_FAILURE;
1977 }
1978 break;
1979 }
1980 }
1981 }
1982 }
1983 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001984}
1985
1986int
1987yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vican0adf01d2016-03-22 12:29:33 +01001988 char *rev, int inc_size, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01001989{
1990 struct lys_include inc;
1991 struct lys_module *trg;
1992 int i;
Pavol Vican55870412016-03-10 12:36:21 +01001993 const char *str;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001994
Pavol Vican55870412016-03-10 12:36:21 +01001995 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001996 trg = (submodule) ? (struct lys_module *)submodule : module;
1997 inc.submodule = NULL;
1998 inc.external = 0;
1999 memcpy(inc.rev, rev, LY_REV_SIZE);
Pavol Vican0adf01d2016-03-22 12:29:33 +01002000 if (lyp_check_include(module, submodule, str, &inc, unres)) {
Pavol Vican9b89dda2016-03-09 15:36:55 +01002001 goto error;
2002 }
2003 memcpy(&trg->inc[inc_size], &inc, sizeof inc);
2004
2005 /* check duplications in include submodules */
2006 for (i = 0; i < inc_size; ++i) {
2007 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size].submodule->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002008 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
2009 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01002010 trg->inc[inc_size].submodule = NULL;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002011 goto error;
2012 }
2013 }
Pavol Vican55870412016-03-10 12:36:21 +01002014 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002015 return EXIT_SUCCESS;
2016
2017error:
Pavol Vican55870412016-03-10 12:36:21 +01002018 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002019 return EXIT_FAILURE;
2020}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002021
2022int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002023yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002024{
2025 char *prefix;
2026 char *identif;
2027 const char *ns = NULL;
2028 int i;
2029
Pavol Vicanf4717e62016-03-16 11:30:01 +01002030 /* check to the same pointer */
2031 if (data_node != actual) {
2032 return EXIT_SUCCESS;
2033 }
2034
Pavol Vicana302aa62016-03-17 10:45:35 +01002035 prefix = strdup(value);
2036 if (!prefix) {
2037 LOGMEM;
2038 goto error;
2039 }
2040 /* find prefix anf identificator*/
2041 identif = strchr(prefix, ':');
2042 *identif = '\0';
2043 identif++;
2044
Pavol Vicanf4717e62016-03-16 11:30:01 +01002045 for(i = 0; i < module->imp_size; ++i) {
2046 if (!strcmp(module->imp[i].prefix, prefix)) {
2047 ns = module->imp[i].module->ns;
2048 break;
2049 }
2050 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002051 if (!ns && !strcmp(module->prefix, prefix)) {
2052 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2053 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002054 if (ns && !strcmp(ns, LY_NSNACM)) {
2055 if (!strcmp(identif, "default-deny-write")) {
2056 data_node->nacm |= LYS_NACM_DENYW;
2057 } else if (!strcmp(identif, "default-deny-all")) {
2058 data_node->nacm |= LYS_NACM_DENYA;
2059 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002060 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002061 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002062 }
2063 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002064 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002065 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002066
2067error:
2068 free(prefix);
2069 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002070}
2071
2072void
2073nacm_inherit(struct lys_module *module)
2074{
Pavol Vican10ffba52016-04-04 12:21:22 +02002075 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002076
2077 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002078 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002079 if (elem->parent) {
2080 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002081 case LYS_GROUPING:
2082 /* extension nacm not inherited*/
2083 break;
2084 case LYS_CHOICE:
2085 case LYS_ANYXML:
2086 case LYS_USES:
2087 if (elem->parent->nodetype != LYS_GROUPING) {
2088 elem->nacm |= elem->parent->nacm;
2089 }
2090 break;
2091 case LYS_CONTAINER:
2092 case LYS_LIST:
2093 case LYS_CASE:
2094 case LYS_NOTIF:
2095 case LYS_RPC:
2096 case LYS_INPUT:
2097 case LYS_OUTPUT:
2098 case LYS_AUGMENT:
2099 elem->nacm |= elem->parent->nacm;
2100 break;
2101 case LYS_LEAF:
2102 case LYS_LEAFLIST:
2103 tmp_node = elem;
2104 tmp_child = elem->child;
2105 elem->child = NULL;
2106 default:
2107 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002108 }
2109 }
2110 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002111 if (tmp_node) {
2112 tmp_node->child = tmp_child;
2113 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002114 }
2115}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002116
2117void
2118store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2119{
2120 node->flags |= flags;
2121 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2122 /* get config flag from parent */
2123 if (node->parent) {
2124 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2125 } else {
2126 /* default config is true */
2127 node->flags |= LYS_CONFIG_W;
2128 }
2129 }
2130}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002131
Pavol Vican1938d882016-04-10 13:36:31 +02002132static int
2133yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2134 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002135{
2136 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002137 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002138 int ret = EXIT_SUCCESS;
2139
2140 yylex_init(&scanner);
2141 bp = yy_scan_buffer((char *)data, size, scanner);
2142 yy_switch_to_buffer(bp, scanner);
2143 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2144 ret = EXIT_FAILURE;
2145 }
2146 yy_delete_buffer(bp, scanner);
2147 yylex_destroy(scanner);
2148 return ret;
2149}
2150
2151int
2152yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2153{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002154 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002155 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002156 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002157
2158 size_arrays = calloc(1, sizeof *size_arrays);
2159 if (!size_arrays) {
2160 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002161 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002162 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002163 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002164 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2165 if (!ret) {
2166 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002167 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002168 free(size_arrays->node);
2169 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002170 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002171}
2172
2173struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002174yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002175{
2176
Pavol Vican10ffba52016-04-04 12:21:22 +02002177 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002178 struct unres_schema *unres = NULL;
2179
2180 unres = calloc(1, sizeof *unres);
2181 if (!unres) {
2182 LOGMEM;
2183 goto error;
2184 }
2185
2186 module = calloc(1, sizeof *module);
2187 if (!module) {
2188 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002189 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002190 }
2191
2192 /* initiale module */
2193 module->ctx=ctx;
2194 module->type = 0;
2195 module->implemented = (implement ? 1 : 0);
2196
2197 if (yang_parse_mem(module, NULL, unres, data, size)) {
2198 goto error;
2199 }
2200
2201 if (module && unres->count && resolve_unres_schema(module, unres)) {
2202 goto error;
2203 }
2204
2205 if (revision) {
2206 /* check revision of the parsed model */
2207 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2208 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2209 module->name, module->rev[0].date, revision);
2210 goto error;
2211 }
2212 }
2213
Pavol Vican10ffba52016-04-04 12:21:22 +02002214 tmp_module = module;
Radek Krejci5deaafd2016-03-30 13:27:47 +02002215 if (lyp_add_module(&module, implement)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002216 goto error;
2217 }
2218
Pavol Vican10ffba52016-04-04 12:21:22 +02002219 if (module == tmp_module) {
2220 nacm_inherit(module);
2221 }
2222
Pavol Vican8e7110b2016-03-22 17:00:26 +01002223 unres_schema_free(NULL, &unres);
2224 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2225 return module;
2226
2227error:
2228 unres_schema_free(module, &unres);
2229 if (!module || !module->name) {
2230 free(module);
2231 LOGERR(ly_errno, "Module parsing failed.");
2232 return NULL;
2233 }
2234
2235 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
2236 lyp_fail_module(module);
2237 lys_free(module,NULL,1);
2238 return NULL;
2239}
2240
2241struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002242yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002243{
2244 struct lys_submodule *submodule;
2245
2246 submodule = calloc(1, sizeof *submodule);
2247 if (!submodule) {
2248 LOGMEM;
2249 goto error;
2250 }
2251
2252 submodule->ctx = module->ctx;
2253 submodule->type = 1;
2254 submodule->belongsto = module;
2255
2256 if (yang_parse_mem(module, submodule, unres, data, size)) {
2257 goto error;
2258 }
2259
2260 /* cleanup */
2261
2262 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
2263
2264 return submodule;
2265
2266error:
2267 /* cleanup */
2268 unres_schema_free((struct lys_module *)submodule, &unres);
2269
2270 if (!submodule || !submodule->name) {
2271 free(submodule);
2272 LOGERR(ly_errno, "Submodule parsing failed.");
2273 return NULL;
2274 }
2275
2276 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2277
2278 lyp_fail_submodule(submodule);
2279 lys_submodule_free(submodule, NULL);
2280
2281 return NULL;
2282}
Pavol Vican8760bb72016-04-07 09:44:01 +02002283
2284static int
2285count_substring(const char *str, char c)
2286{
2287 const char *tmp = str;
2288 int count = 0;
2289
2290 while ((tmp = strchr(tmp, c))) {
2291 tmp++;
2292 count++;
2293 }
2294 return count;
2295}
2296
2297static int
2298read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2299{
2300 int k = 0, j;
2301
2302 while (in_index < size) {
2303 if (input[in_index] == ' ') {
2304 k++;
2305 } else if (input[in_index] == '\t') {
2306 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2307 k += 8;
2308 } else {
2309 break;
2310 }
2311 ++in_index;
2312 if (k >= indent) {
2313 for (j = k - indent; j > 0; --j) {
2314 output[*out_index] = ' ';
2315 ++(*out_index);
2316 }
2317 break;
2318 }
2319 }
2320 return in_index;
2321}
2322
2323char *
2324yang_read_string(const char *input, int size, int indent)
2325{
2326 int space, count;
2327 int in_index, out_index;
2328 char *value;
2329 char *retval = NULL;
2330
2331 value = malloc(size + 1);
2332 if (!value) {
2333 LOGMEM;
2334 return NULL;
2335 }
2336 /* replace special character in escape sequence */
2337 in_index = out_index = 0;
2338 while (in_index < size) {
2339 if (input[in_index] == '\\') {
2340 if (input[in_index + 1] == 'n') {
2341 value[out_index] = '\n';
2342 ++in_index;
2343 } else if (input[in_index + 1] == 't') {
2344 value[out_index] = '\t';
2345 ++in_index;
2346 } else if (input[in_index + 1] == '\\') {
2347 value[out_index] = '\\';
2348 ++in_index;
2349 } else if ((in_index + 1) != size && input[in_index + 1] == '"') {
2350 value[out_index] = '"';
2351 ++in_index;
2352 } else {
2353 value[out_index] = input[in_index];
2354 }
2355 } else {
2356 value[out_index] = input[in_index];
2357 }
2358 ++in_index;
2359 ++out_index;
2360 }
2361 value[out_index] = '\0';
2362 size = out_index;
2363 count = count_substring(value, '\t');
2364
2365 /* extend size of string due to replacing character '\t' with 8 spaces */
2366 retval = malloc(size + 1 + 7 * count);
2367 if (!retval) {
2368 LOGMEM;
2369 goto error;
2370 }
2371 in_index = out_index = space = 0;
2372 while (in_index < size) {
2373 if (value[in_index] == '\n') {
2374 out_index -= space;
2375 space = 0;
2376 retval[out_index] = '\n';
2377 ++out_index;
2378 ++in_index;
2379 in_index = read_indent(value, indent, size, in_index, &out_index, retval);
2380 continue;
2381 } else {
2382 space = (value[in_index] == ' ' || value[in_index] == '\t') ? space + 1 : 0;
2383 retval[out_index] = value[in_index];
2384 ++out_index;
2385 }
2386 ++in_index;
2387 }
2388 retval[out_index] = '\0';
2389 if (out_index != size) {
2390 retval = ly_realloc(retval, out_index + 1);
2391 }
2392 free(value);
2393 return retval;
2394error:
2395 free(value);
2396 return NULL;
2397}