blob: 43c3124a91925c26baf180926205a75ff841e9ae [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Pavol Vican5de33492016-02-22 14:03:24 +010022#include <ctype.h>
Pavol Vican1c203db2016-02-24 14:05:23 +010023#include <pcre.h>
Pavol Vican021488a2016-01-25 23:56:12 +010024#include "parser_yang.h"
25#include "parser_yang_bis.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010026#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010027#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010028
Pavol Vican2a064652016-02-02 22:54:34 +010029static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010030yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010031{
Pavol Vicanbf805472016-01-26 14:24:56 +010032 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010033 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010034 free(value);
35 return 1;
36 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010037 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010038 return 0;
39 }
40}
41
Pavol Vican2a064652016-02-02 22:54:34 +010042int
Pavol Vican0adf01d2016-03-22 12:29:33 +010043yang_read_common(struct lys_module *module, char *value, int type)
Pavol Vican2a064652016-02-02 22:54:34 +010044{
Pavol Vican6eb14e82016-02-03 12:27:13 +010045 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010046
47 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010048 case MODULE_KEYWORD:
49 module->name = lydict_insert_zc(module->ctx, value);
50 break;
51 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010052 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010053 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010054 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010055 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010056 break;
57 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010058 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010059 break;
Pavol Vican2a064652016-02-02 22:54:34 +010060 }
61
Pavol Vican021488a2016-01-25 23:56:12 +010062 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010063}
64
Pavol Vican2a064652016-02-02 22:54:34 +010065int
Pavol Vican0adf01d2016-03-22 12:29:33 +010066yang_read_prefix(struct lys_module *module, void *save, char *value, int type)
Pavol Vican2a064652016-02-02 22:54:34 +010067{
Pavol Vican6eb14e82016-02-03 12:27:13 +010068 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010069
Pavol Vican0adf01d2016-03-22 12:29:33 +010070 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +010071 free(value);
72 return EXIT_FAILURE;
73 }
Pavol Vicanbf805472016-01-26 14:24:56 +010074 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +010075 case MODULE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010076 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010077 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010078 case IMPORT_KEYWORD:
79 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
80 break;
Pavol Vican2a064652016-02-02 22:54:34 +010081 }
Pavol Vican6eb14e82016-02-03 12:27:13 +010082
Pavol Vicanbf805472016-01-26 14:24:56 +010083 return ret;
84}
Pavol Vican6eb14e82016-02-03 12:27:13 +010085
86void *
87yang_elem_of_array(void **ptr, uint8_t *act_size, int type, int sizeof_struct)
88{
89 void *retval;
90
91 if (!(*act_size % LY_ARRAY_SIZE) && !(*ptr = ly_realloc(*ptr, (*act_size + LY_ARRAY_SIZE) * sizeof_struct))) {
92 LOGMEM;
93 return NULL;
94 }
95 switch (type) {
96 case IMPORT_KEYWORD:
97 retval = &((struct lys_import *)(*ptr))[*act_size];
98 break;
Pavol Vicanbedff692016-02-03 14:29:17 +010099 case REVISION_KEYWORD:
100 retval = &((struct lys_revision *)(*ptr))[*act_size];
101 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100102 }
103 (*act_size)++;
104 memset(retval,0,sizeof_struct);
105 return retval;
106}
107
108int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100109yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100110{
Pavol Vican0da132e2016-03-21 12:03:03 +0100111 const char *exp;
112 int rc, i;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100113
Pavol Vican0da132e2016-03-21 12:03:03 +0100114 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100115 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +0100116 lydict_remove(module->ctx, exp);
117 if (rc) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100118 goto error;
119 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120
121 /* check duplicities in imported modules */
Pavol Vican0da132e2016-03-21 12:03:03 +0100122 for (i = 0; i < module->imp_size; i++) {
123 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size].module->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100124 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, module->imp[i].module->name, "import");
125 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Pavol Vican6eb14e82016-02-03 12:27:13 +0100126 goto error;
127 }
128 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100129 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100130 return EXIT_SUCCESS;
131
Pavol Vican0da132e2016-03-21 12:03:03 +0100132error:
133 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100134 return EXIT_FAILURE;
135}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100136
137int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100138yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100139{
140 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100141 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100142
143 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100144 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100145 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100146 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100147 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100148 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100149 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100150 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100151 }
152 return ret;
153}
154
155int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100156yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100157{
158 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100159 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100160
161 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100162 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100163 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100164 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100166 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100167 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100168 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100169 }
170 return ret;
171}
Pavol Vicanbedff692016-02-03 14:29:17 +0100172
173void *
174yang_read_revision(struct lys_module *module, char *value)
175{
176 struct lys_revision *retval;
177
Pavol Vican1eeb1992016-02-09 11:10:45 +0100178 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100179
180 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100181 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100182 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
183 memcpy(module->rev[0].date, value, LY_REV_SIZE);
184 retval->dsc = module->rev[0].dsc;
185 retval->ref = module->rev[0].ref;
186 retval = module->rev;
187 retval->dsc = NULL;
188 retval->ref = NULL;
189 } else {
190 memcpy(retval->date, value, LY_REV_SIZE);
191 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100192 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100193 free(value);
194 return retval;
195}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100196
197int
Pavol Vicana1827962016-02-29 15:39:42 +0100198yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100199{
Pavol Vican45ccc592016-03-09 18:53:48 +0100200 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100201 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
202 LOGMEM;
203 return EXIT_FAILURE;
204 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100205 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100206 }
207 }
208 (*size)++;
209 return EXIT_SUCCESS;
210}
Pavol Vicane1354e92016-02-09 14:02:09 +0100211
212void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100213yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100214{
215 struct lys_feature *retval;
216
217 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100218 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100219 goto error;
220 }
221 retval = &module->features[module->features_size];
222 retval->name = lydict_insert_zc(module->ctx, value);
223 retval->module = module;
224 module->features_size++;
225 return retval;
226
227error:
228 free(value);
229 return NULL;
230}
231
232int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100233yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, int type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100234{
235 const char *exp;
236 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100237 struct lys_feature *f;
238 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100239
Pavol Vican0adf01d2016-03-22 12:29:33 +0100240 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100241 free(value);
242 return EXIT_FAILURE;
243 }
244 free(value);
245
246 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100247 if (type == FEATURE_KEYWORD) {
248 f = (struct lys_feature *) ptr;
249 f->features[f->features_size] = f;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100250 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100251 f->features_size++;
252 } else {
253 n = (struct lys_node *) ptr;
254 n->features[n->features_size] = (struct lys_feature *) n;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100255 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100256 n->features_size++;
257 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100258
259 lydict_remove(module->ctx, exp);
260 if (ret == -1) {
261
262 return EXIT_FAILURE;
263 }
264 return EXIT_SUCCESS;
265}
266
Pavol Vican4fb66c92016-03-17 10:32:27 +0100267int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100268yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100269{
270 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100271 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100272 return EXIT_FAILURE;
273 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100274 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100275 return EXIT_SUCCESS;
276 }
277}
278
Pavol Vicanbbdef532016-02-09 14:52:12 +0100279void *
280yang_read_identity(struct lys_module *module, char *value)
281{
282 struct lys_ident *ret;
283
284 ret = &module->ident[module->ident_size];
285 ret->name = lydict_insert_zc(module->ctx, value);
286 ret->module = module;
287 module->ident_size++;
288 return ret;
289}
290
291int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100292yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100293{
294 const char *exp;
295
Pavol Vicane2368982016-03-19 14:37:56 +0100296 if (!value) {
297 /* base statement not found */
298 return EXIT_SUCCESS;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100299 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100300 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100301 free(value);
302 if (!exp) {
303 return EXIT_FAILURE;
304 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100305 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100306 lydict_remove(module->ctx, exp);
307 return EXIT_FAILURE;
308 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100309
Pavol Vicanbbdef532016-02-09 14:52:12 +0100310 lydict_remove(module->ctx, exp);
311 return EXIT_SUCCESS;
312}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100313
314void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100315yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100316{
317 struct lys_restr *retval;
318
319 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100320 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100321 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100322 break;
323 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100324 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
325 break;
326 case LEAF_KEYWORD:
327 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100328 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100329 case LEAF_LIST_KEYWORD:
330 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
331 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100332 case LIST_KEYWORD:
333 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
334 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100335 case REFINE_KEYWORD:
336 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
337 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100338 case ADD_KEYWORD:
339 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
340 memset(retval, 0, sizeof *retval);
341 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100342 case DELETE_KEYWORD:
343 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
344 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100345 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100346 retval->expr = transform_schema2json(module, value);
347 if (!retval->expr || lyxp_syntax_check(retval->expr)) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100348 goto error;
349 }
350 free(value);
351 return retval;
352
353error:
354 free(value);
355 return NULL;
356}
357
358int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100359yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100360{
361 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100362
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100363 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100364 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100365 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100366 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100367 }
368 return ret;
369}
Pavol Vicanb5687112016-02-09 22:35:59 +0100370
371int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100372yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100373{
374 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100375 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100376 free(value);
377 return EXIT_FAILURE;
378 } else {
379 cont->presence = lydict_insert_zc(module->ctx, value);
380 return EXIT_SUCCESS;
381 }
382}
383
Pavol Vican235dbd42016-02-10 10:34:19 +0100384void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100385yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100386{
387 struct lys_when *retval;
388
389 retval = calloc(1, sizeof *retval);
390 if (!retval) {
391 LOGMEM;
392 free(value);
393 return NULL;
394 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100395 retval->cond = transform_schema2json(module, value);
396 if (!retval->cond || lyxp_syntax_check(retval->cond)) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100397 goto error;
398 }
399 switch (type) {
400 case CONTAINER_KEYWORD:
401 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100402 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100403 goto error;
404 }
405 ((struct lys_node_container *)node)->when = retval;
406 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100407 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100408 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100409 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100410 goto error;
411 }
412 ((struct lys_node_anyxml *)node)->when = retval;
413 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100414 case CHOICE_KEYWORD:
415 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100416 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100417 goto error;
418 }
419 ((struct lys_node_choice *)node)->when = retval;
420 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100421 case CASE_KEYWORD:
422 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100423 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100424 goto error;
425 }
426 ((struct lys_node_case *)node)->when = retval;
427 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100428 case LEAF_KEYWORD:
429 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100430 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100431 goto error;
432 }
433 ((struct lys_node_leaf *)node)->when = retval;
434 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100435 case LEAF_LIST_KEYWORD:
436 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100437 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100438 goto error;
439 }
440 ((struct lys_node_leaflist *)node)->when = retval;
441 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100442 case LIST_KEYWORD:
443 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100444 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100445 goto error;
446 }
447 ((struct lys_node_list *)node)->when = retval;
448 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100449 case USES_KEYWORD:
450 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100451 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100452 goto error;
453 }
454 ((struct lys_node_uses *)node)->when = retval;
455 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100456 case AUGMENT_KEYWORD:
457 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100458 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100459 goto error;
460 }
461 ((struct lys_node_augment *)node)->when = retval;
462 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100463 }
464 free(value);
465 return retval;
466
467error:
468 free(value);
469 lys_when_free(module->ctx, retval);
470 return NULL;
471}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100472
473void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100474yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100475{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100476 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100477
Pavol Vican7cadfe72016-02-11 12:33:34 +0100478 node = calloc(1, sizeof_struct);
479 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100480 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100481 LOGMEM;
482 return NULL;
483 }
Pavol Vican531a9132016-03-03 10:10:09 +0100484 if (value) {
485 node->name = lydict_insert_zc(module->ctx, value);
486 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100487 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100488 node->nodetype = nodetype;
489 node->prev = node;
490
491 /* insert the node into the schema tree */
492 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100493 if (value) {
494 lydict_remove(module->ctx, node->name);
495 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100496 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100497 return NULL;
498 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100499 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100500}
501
502int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100503yang_read_default(struct lys_module *module, void *node, char *value, int type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100504{
505 int ret;
506
507 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100508 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100509 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100510 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100511 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100512 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100513 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100514 }
515 return ret;
516}
517
518int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100519yang_read_units(struct lys_module *module, void *node, char *value, int type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100520{
521 int ret;
522
523 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100524 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100525 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100526 break;
527 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100528 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100529 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100530 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100531 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100532 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100533 }
534 return ret;
535}
Pavol Vican5de33492016-02-22 14:03:24 +0100536
537int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100538yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100539{
540 char *exp, *value;
541
542 exp = value = (char *) list->keys;
543 while ((value = strpbrk(value, " \t\n"))) {
544 list->keys_size++;
545 while (isspace(*value)) {
546 value++;
547 }
548 }
549 list->keys_size++;
550 list->keys = calloc(list->keys_size, sizeof *list->keys);
551 if (!list->keys) {
552 LOGMEM;
553 goto error;
554 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100555 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100556 goto error;
557 }
558 free(exp);
559 return EXIT_SUCCESS;
560
561error:
562 free(exp);
563 return EXIT_FAILURE;
564}
565
566int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100567yang_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 +0100568{
569 int i, j;
570 char *vaux;
571
572 /* count the number of unique leafs in the value */
573 vaux = value;
574 while ((vaux = strpbrk(vaux, " \t\n"))) {
575 unique->expr_size++;
576 while (isspace(*vaux)) {
577 vaux++;
578 }
579 }
580 unique->expr_size++;
581 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
582 if (!unique->expr) {
583 LOGMEM;
584 goto error;
585 }
586
587 for (i = 0; i < unique->expr_size; i++) {
588 vaux = strpbrk(value, " \t\n");
589 if (!vaux) {
590 /* the last token, lydict_insert() will count its size on its own */
591 vaux = value;
592 }
593
594 /* store token into unique structure */
595 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
596
597 /* check that the expression does not repeat */
598 for (j = 0; j < i; j++) {
599 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100600 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
601 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100602 goto error;
603 }
604 }
605 /* try to resolve leaf */
606 if (unres) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100607 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i]);
Pavol Vican85f12022016-03-05 16:30:35 +0100608 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100609 if (resolve_unique((struct lys_node *)list, unique->expr[i])) {
Pavol Vican85f12022016-03-05 16:30:35 +0100610 goto error;
611 }
612 }
613
614 /* move to next token */
615 value = vaux;
616 while(isspace(*value)) {
617 value++;
618 }
619 }
620
621 return EXIT_SUCCESS;
622
623error:
624 return EXIT_FAILURE;
625}
626
627int
Pavol Vican5de33492016-02-22 14:03:24 +0100628yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
629{
630 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100631 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100632
633 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100634 str = (char *)list->unique[k].expr;
635 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100636 goto error;
637 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100638 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100639 }
640 return EXIT_SUCCESS;
641
642error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100643 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100644 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100645}
646
Pavol Vican1ff0e222016-02-26 12:27:01 +0100647static int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100648yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100649{
650 const char *value, *tmp;
651 int rc, ret = EXIT_FAILURE;
652
653 value = tmp = type->info.lref.path;
654 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100655 value = transform_schema2json(module, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100656 if (!value) {
657 goto end;
658 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100659 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100660 lydict_remove(module->ctx, value);
661
662 if (rc == -1) {
663 goto end;
664 }
665
666 ret = EXIT_SUCCESS;
667
668end:
669 lydict_remove(module->ctx, tmp);
670 return ret;
671}
672
Pavol Vican73e7c992016-02-24 12:18:05 +0100673int
674yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
675{
676 int i, rc;
677 int ret = -1;
678 const char *name, *value;
679 LY_DATA_TYPE base;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100680 struct yang_type *typ_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100681
Pavol Vican0df02b02016-03-01 10:28:50 +0100682 base = typ->type->base;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100683 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100684 if (!value) {
685 goto error;
686 }
687
688 i = parse_identifier(value);
689 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100690 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100691 lydict_remove(module->ctx, value);
692 goto error;
693 }
694 /* module name*/
695 name = value;
696 if (value[i]) {
697 typ->type->module_name = lydict_insert(module->ctx, value, i);
698 name += i;
699 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100700 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100701 lydict_remove(module->ctx, value);
702 goto error;
703 }
704 ++name;
705 }
706
707 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
708 lydict_remove(module->ctx, value);
709 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100710 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100711 goto error;
712
713 /* the type could not be resolved or it was resolved to an unresolved typedef*/
714 } else if (rc == EXIT_FAILURE) {
715 ret = EXIT_FAILURE;
716 goto error;
717 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100718 typ->type->base = typ->type->der->type.base;
719 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100720 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100721 }
722 switch (base) {
723 case LY_TYPE_STRING:
724 if (typ->type->base == LY_TYPE_BINARY) {
725 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100726 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100727 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100728 goto error;
729 }
730 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100731 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 +0100732 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100733 goto error;
734 }
735 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100736 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 +0100737 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100738 goto error;
739 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100740 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100741 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100742 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100743 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100744 break;
745 case LY_TYPE_DEC64:
746 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100747 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 +0100748 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100749 goto error;
750 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100751 /* mandatory sub-statement(s) check */
752 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
753 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100754 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100755 goto error;
756 }
757 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
758 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100759 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100760 goto error;
761 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100762 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
763 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100764 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100765 typ->type->base = base;
766 goto error;
767 }
768 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100769 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 +0100770 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100771 goto error;
772 }
773 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100774 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100775 goto error;
776 }
777 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100778 case LY_TYPE_ENUM:
779 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100780 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100781 goto error;
782 }
Pavol Vican03a59442016-03-21 15:23:45 +0100783 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
Pavol Vican79a763d2016-02-25 15:41:27 +0100784 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100785 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
Pavol Vican79a763d2016-02-25 15:41:27 +0100786 goto error;
787 }
788 if (typ->type->der->type.der && typ->type->info.enums.count) {
789 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100790 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
Pavol Vican79a763d2016-02-25 15:41:27 +0100791 goto error;
792 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100793 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100794 case LY_TYPE_BITS:
795 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100796 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100797 goto error;
798 }
799 if (!typ->type->der->type.der && !typ->type->info.bits.count) {
800 /* type is derived directly from buit-in bits type and bit statement is required */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100801 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
Pavol Vican03a59442016-03-21 15:23:45 +0100802 goto error;
803 }
804 if (typ->type->der->type.der && typ->type->info.bits.count) {
805 /* type is not directly derived from buit-in bits type and bit statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100806 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
Pavol Vican03a59442016-03-21 15:23:45 +0100807 goto error;
808 }
809 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100810 case LY_TYPE_LEAFREF:
811 if (typ->type->base == LY_TYPE_IDENT && typ->flags & LYS_TYPE_BASE) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100812 if (yang_read_identyref(module, typ->type, unres)) {
Pavol Vican1ff0e222016-02-26 12:27:01 +0100813 goto error;
814 }
Pavol Vican191613a2016-02-26 16:21:32 +0100815 } else if (typ->type->base == LY_TYPE_LEAFREF) {
816 if (typ->type->info.lref.path && !typ->type->der->type.der) {
817 value = typ->type->info.lref.path;
818 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100819 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100820 lydict_remove(module->ctx, value);
821 if (!typ->type->info.lref.path) {
822 goto error;
823 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100824 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100825 goto error;
826 }
827 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100828 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100829 goto error;
830 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100831 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican191613a2016-02-26 16:21:32 +0100832 goto error;
833 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100834 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100835 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100836 goto error;
837 }
838 break;
839 case LY_TYPE_IDENT:
840 if (typ->type->der->type.der) {
841 /* this is just a derived type with no base specified/required */
842 break;
843 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100844 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100845 goto error;
846 }
847 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100848 case LY_TYPE_UNION:
849 if (typ->type->base != LY_TYPE_UNION) {
850 typ->type->base = LY_TYPE_UNION;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100852 goto error;
853 }
854 if (!typ->type->info.uni.types) {
855 if (typ->type->der->type.der) {
856 /* this is just a derived type with no additional type specified/required */
857 break;
858 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100859 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100860 goto error;
861 }
862 for (i = 0; i < typ->type->info.uni.count; i++) {
863 typ_tmp = (struct yang_type *)typ->type->info.uni.types[i].der;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100864 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent)) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100865 goto error;
866 }
867 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100868 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100869 goto error;
870 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100871 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100872 goto error;
873 }
874 }
875 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100876
877 default:
878 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
879 if (typ->type->base != base) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100880 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +0100881 goto error;
882 }
883 } else {
884 LOGINT;
885 goto error;
886 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100887 }
888 return EXIT_SUCCESS;
889
890error:
Pavol Vicana1827962016-02-29 15:39:42 +0100891 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100892 if (typ->type->module_name) {
893 lydict_remove(module->ctx, typ->type->module_name);
894 typ->type->module_name = NULL;
895 }
896 return ret;
897}
898
899void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100900yang_read_type(struct lys_module *module, void *parent, char *value, int type)
Pavol Vican73e7c992016-02-24 12:18:05 +0100901{
902 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100903 struct type_deviation *dev;
904 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +0100905
Pavol Vicand01d8ae2016-03-01 10:45:59 +0100906 typ = calloc(1, sizeof *typ);
907 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100908 LOGMEM;
909 return NULL;
910 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100911
912 typ->flags = LY_YANG_STRUCTURE_FLAG;
913 switch (type) {
914 case LEAF_KEYWORD:
915 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
916 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
917 typ->type = &((struct lys_node_leaf *)parent)->type;
918 break;
Pavol Vicana55992a2016-03-01 13:37:17 +0100919 case LEAF_LIST_KEYWORD:
920 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
921 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
922 typ->type = &((struct lys_node_leaflist *)parent)->type;
923 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100924 case UNION_KEYWORD:
925 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
926 typ->type = (struct lys_type *)parent;
927 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100928 case TYPEDEF_KEYWORD:
929 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
930 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +0100931 break;
932 case REPLACE_KEYWORD:
933 /* deviation replace type*/
934 dev = (struct type_deviation *)parent;
935 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100936 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +0100937 goto error;
938 }
939 /* check target node type */
940 if (dev->target->nodetype == LYS_LEAF) {
941 typ->type = &((struct lys_node_leaf *)dev->target)->type;
942 } else if (dev->target->nodetype == LYS_LEAFLIST) {
943 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
944 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100945 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
946 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +0100947 goto error;
948 }
949
950 /* remove type and initialize it */
951 lys_type_free(module->ctx, typ->type);
952 tmp_parent = typ->type->parent;
953 memset(typ->type, 0, sizeof *typ->type);
954 typ->type->parent = tmp_parent;
955
956 /* replace it with the value specified in deviation */
957 /* HACK for unres */
958 typ->type->der = (struct lys_tpdf *)typ;
959 dev->deviate->type = typ->type;
960 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100961 }
962 typ->name = value;
Pavol Vican73e7c992016-02-24 12:18:05 +0100963 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100964
965error:
966 free(typ);
967 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +0100968}
969
970void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100971yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +0100972{
973 struct lys_restr **length;
974
975 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
976 length = &typ->type->info.str.length;
977 typ->type->base = LY_TYPE_STRING;
978 } else if (typ->type->base == LY_TYPE_BINARY) {
979 length = &typ->type->info.binary.length;
980 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100981 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100982 goto error;
983 }
984
985 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100986 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vican73e7c992016-02-24 12:18:05 +0100987 }
988 *length = calloc(1, sizeof **length);
989 if (!*length) {
990 LOGMEM;
991 goto error;
992 }
993 (*length)->expr = lydict_insert_zc(module->ctx, value);
994 return *length;
995
996error:
997 free(value);
998 return NULL;
999
1000}
Pavol Vican1c203db2016-02-24 14:05:23 +01001001
1002void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001003yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican1c203db2016-02-24 14:05:23 +01001004{
1005 pcre *precomp;
1006 int err_offset;
1007 const char *err_ptr;
1008
1009 /* check that the regex is valid */
1010 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1011 if (!precomp) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001012 LOGVAL(LYE_INREGEX, LY_VLOG_NONE, NULL, value, err_ptr);
Pavol Vican1c203db2016-02-24 14:05:23 +01001013 free(value);
1014 return NULL;
1015 }
1016 free(precomp);
1017
1018 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1019 typ->type->info.str.pat_count++;
1020 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1021}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001022
1023void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001024yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001025{
1026 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001027 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001028 goto error;
1029 }
1030 typ->type->base = LY_TYPE_DEC64;
1031 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001032 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001033 goto error;
1034 }
1035 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1036 if (!typ->type->info.dec64.range) {
1037 LOGMEM;
1038 goto error;
1039 }
1040 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1041 return typ->type->info.dec64.range;
1042
1043error:
1044 free(value);
1045 return NULL;
1046}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001047
1048int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001049yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001050{
1051 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1052 typ->type->base = LY_TYPE_DEC64;
1053 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001054 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001055 goto error;
1056 }
1057 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001058 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001059 goto error;
1060 }
1061 /* range check */
1062 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001063 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001064 goto error;
1065 }
1066 typ->type->info.dec64.dig = value;
1067 return EXIT_SUCCESS;
1068
1069error:
1070 return EXIT_FAILURE;
1071}
Pavol Vican79a763d2016-02-25 15:41:27 +01001072
1073void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001074yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001075{
1076 struct lys_type_enum *enm;
1077 int i;
1078
1079 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1080 enm->name = lydict_insert_zc(module->ctx, value);
1081
1082 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1083 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001084 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001085 goto error;
1086 }
1087
1088 /* check the name uniqueness */
1089 for (i = 0; i < typ->type->info.enums.count; i++) {
1090 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 +01001091 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001092 goto error;
1093 }
1094 }
1095
1096 typ->type->info.enums.count++;
1097 return enm;
1098
1099error:
1100 typ->type->info.enums.count++;
1101 return NULL;
1102}
1103
1104int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001105yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001106{
1107 int i, j;
1108
1109 if (!assign) {
1110 /* assign value automatically */
1111 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001112 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001113 goto error;
1114 }
1115 enm->value = *value;
1116 enm->flags |= LYS_AUTOASSIGNED;
1117 (*value)++;
1118 }
1119
1120 /* check that the value is unique */
1121 j = typ->type->info.enums.count-1;
1122 for (i = 0; i < j; i++) {
1123 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001124 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Pavol Vican79a763d2016-02-25 15:41:27 +01001125 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1126 goto error;
1127 }
1128 }
1129
1130 return EXIT_SUCCESS;
1131
1132error:
1133 return EXIT_FAILURE;
1134}
Pavol Vican9887c682016-02-29 11:32:01 +01001135
1136void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001137yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001138{
1139 int i;
1140 struct lys_type_bit *bit;
1141
1142 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001143 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001144 free(value);
1145 goto error;
1146 }
1147 bit->name = lydict_insert_zc(module->ctx, value);
1148
1149 /* check the name uniqueness */
1150 for (i = 0; i < typ->type->info.bits.count; i++) {
1151 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001152 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001153 typ->type->info.bits.count++;
1154 goto error;
1155 }
1156 }
1157 typ->type->info.bits.count++;
1158 return bit;
1159
1160error:
1161 return NULL;
1162}
1163
1164int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001165yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001166{
1167 int i,j;
1168 struct lys_type_bit bit_tmp;
1169
1170 if (!assign) {
1171 /* assign value automatically */
1172 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001173 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001174 goto error;
1175 }
1176 bit->pos = (uint32_t)*value;
1177 bit->flags |= LYS_AUTOASSIGNED;
1178 (*value)++;
1179 }
1180
1181 j = typ->type->info.bits.count - 1;
1182 /* check that the value is unique */
1183 for (i = 0; i < j; i++) {
1184 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001185 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001186 goto error;
1187 }
1188 }
1189
1190 /* keep them ordered by position */
1191 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1192 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001193 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1194 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1195 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001196 j--;
1197 }
1198
1199 return EXIT_SUCCESS;
1200
1201error:
1202 return EXIT_FAILURE;
1203}
Pavol Vican0df02b02016-03-01 10:28:50 +01001204
1205void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001206yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001207{
1208 struct lys_tpdf *ret;
1209
Pavol Vican0adf01d2016-03-22 12:29:33 +01001210 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001211 free(value);
1212 return NULL;
1213 }
1214 if (!parent) {
1215 ret = &module->tpdf[module->tpdf_size];
1216 ret->type.parent = NULL;
1217 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001218 } else {
1219 switch (parent->nodetype) {
1220 case LYS_GROUPING:
1221 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001222 ((struct lys_node_grp *)parent)->tpdf_size++;
1223 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001224 case LYS_CONTAINER:
1225 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1226 ((struct lys_node_container *)parent)->tpdf_size++;
1227 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001228 case LYS_LIST:
1229 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1230 ((struct lys_node_list *)parent)->tpdf_size++;
1231 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001232 case LYS_RPC:
1233 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1234 ((struct lys_node_rpc *)parent)->tpdf_size++;
1235 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001236 case LYS_INPUT:
1237 case LYS_OUTPUT:
1238 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1239 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1240 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001241 case LYS_NOTIF:
1242 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1243 ((struct lys_node_notif *)parent)->tpdf_size++;
1244 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001245 default:
1246 /* another type of nodetype is error*/
1247 LOGINT;
1248 free(value);
1249 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001250 }
Pavol Vican535d50e2016-03-01 13:05:33 +01001251 ret->type.parent = (struct lys_tpdf *)parent;
Pavol Vican0df02b02016-03-01 10:28:50 +01001252 }
1253
1254 ret->name = lydict_insert_zc(module->ctx, value);
1255 ret->module = module;
1256 return ret;
1257}
Pavol Vican1003ead2016-03-02 12:24:52 +01001258
1259void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001260yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001261{
1262 struct lys_refine *rfn;
1263
1264 rfn = &uses->refine[uses->refine_size];
1265 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001266 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001267 free(value);
1268 if (!rfn->target_name) {
1269 return NULL;
1270 }
1271 return rfn;
1272}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001273
1274void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001275yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001276{
1277 struct lys_node_augment *aug;
1278 uint16_t *size;
1279
1280 if (parent) {
1281 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1282 } else {
1283 aug = &module->augment[module->augment_size];
1284 }
1285 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001286 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001287 free(value);
1288 if (!aug->target_name) {
1289 return NULL;
1290 }
1291 aug->parent = parent;
1292 aug->module = module;
1293 if (parent) {
1294 ((struct lys_node_uses *)parent)->augment_size++;
1295 } else {
1296 module->augment_size++;
1297 }
1298 return aug;
1299}
Pavol Vican220e5a12016-03-03 14:19:43 +01001300
1301void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001302yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001303{
1304 struct lys_node *dev_target = NULL;
1305 struct lys_deviation *dev;
1306 struct type_deviation *deviation = NULL;
1307 int i, j, rc;
1308
1309 deviation = calloc(1, sizeof *deviation);
1310 if (!deviation) {
1311 LOGMEM;
1312 goto error;
1313 }
1314
1315 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001316 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001317 free(value);
1318 if (!dev->target_name) {
1319 goto error;
1320 }
1321
1322 /* resolve target node */
1323 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1324 if (rc || !dev_target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001325 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
Pavol Vican220e5a12016-03-03 14:19:43 +01001326 goto error;
1327 }
1328 if (dev_target->module == lys_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001329 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1330 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001331 goto error;
1332 }
1333 /*save pointer to the deviation and deviated target*/
1334 deviation->deviation = dev;
1335 deviation->target = dev_target;
1336
1337 /* mark the target module as deviated */
1338 dev_target->module->deviated = 1;
1339
1340 /* copy our imports to the deviated module (deviations may need them to work) */
1341 for (i = 0; i < module->imp_size; ++i) {
1342 for (j = 0; j < dev_target->module->imp_size; ++j) {
1343 if (module->imp[i].module == dev_target->module->imp[j].module) {
1344 break;
1345 }
1346 }
1347
1348 if (j < dev_target->module->imp_size) {
1349 /* import is already there */
1350 continue;
1351 }
1352
1353 /* copy the import, mark it as external */
1354 ++dev_target->module->imp_size;
1355 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1356 if (!dev_target->module->imp) {
1357 LOGMEM;
1358 goto error;
1359 }
1360 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1361 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1362 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1363 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1364 }
1365
1366 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1367 for (i = 0; i < dev_target->module->imp_size; ++i) {
1368 if (dev_target->module->imp[i].module == module) {
1369 break;
1370 }
1371 }
1372
1373 if (i == dev_target->module->imp_size) {
1374 ++dev_target->module->imp_size;
1375 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1376 if (!dev_target->module->imp) {
1377 LOGMEM;
1378 goto error;
1379 }
1380 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1381 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1382 if (module->rev_size) {
1383 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1384 } else {
1385 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1386 }
1387 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1388 } else {
1389 /* it could have been added by another deviating module that imported this deviating module */
1390 dev_target->module->imp[i].external = 2;
1391 }
1392
1393
1394 return deviation;
1395
1396error:
1397 free(deviation);
1398 lydict_remove(module->ctx, dev->target_name);
1399 return NULL;
1400}
Pavol Vican4c90c642016-03-03 15:06:47 +01001401
1402int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001403yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001404{
1405 int i;
1406
1407 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001408 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001409 return EXIT_FAILURE;
1410 }
1411 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1412
1413 /* you cannot remove a key leaf */
1414 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1415 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1416 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001417 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1418 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001419 return EXIT_FAILURE;
1420 }
1421 }
1422 }
1423
1424 /* unlink and store the original node */
1425 dev->deviation->orig_node = dev->target;
1426
1427 dev->deviation->deviate_size = 1;
1428 return EXIT_SUCCESS;
1429}
Pavol Vican85f12022016-03-05 16:30:35 +01001430
1431int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001432yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001433{
1434 struct unres_schema tmp_unres;
1435
1436 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1437 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1438 dev->deviation->deviate_size++;
1439 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001440 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1441 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001442 return EXIT_FAILURE;
1443 }
1444
1445 /* store a shallow copy of the original node */
1446 if (!dev->deviation->orig_node) {
1447 memset(&tmp_unres, 0, sizeof tmp_unres);
1448 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1449 /* just to be safe */
1450 if (tmp_unres.count) {
1451 LOGINT;
1452 return EXIT_FAILURE;
1453 }
1454 }
1455
1456 return EXIT_SUCCESS;
1457}
1458
1459int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001460yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001461{
1462 const char **stritem;
1463
1464 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001465 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001466 free(value);
1467 goto error;
1468 }
1469
1470 /* check target node type */
1471 if (dev->target->nodetype == LYS_LEAFLIST) {
1472 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1473 } else if (dev->target->nodetype == LYS_LEAF) {
1474 stritem = &((struct lys_node_leaf *)dev->target)->units;
1475 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001476 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1477 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001478 free(value);
1479 goto error;
1480 }
1481
1482 dev->deviate->units = lydict_insert_zc(ctx, value);
1483
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001484 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1485 /* check values */
1486 if (*stritem != dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001487 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1488 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001489 goto error;
1490 }
1491 /* remove current units value of the target */
1492 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001493 } else {
1494 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1495 /* check that there is no current value */
1496 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001497 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1498 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001499 goto error;
1500 }
1501 } else { /* replace */
1502 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001503 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1504 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001505 goto error;
1506 }
1507 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001508 /* remove current units value of the target ... */
1509 lydict_remove(ctx, *stritem);
1510
1511 /* ... and replace it with the value specified in deviation */
1512 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1513 }
1514
Pavol Vican85f12022016-03-05 16:30:35 +01001515 return EXIT_SUCCESS;
1516
1517error:
1518 return EXIT_FAILURE;
1519}
1520
1521int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001522yang_read_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001523{
1524 uint8_t i;
1525
1526 /* check target node type */
1527 switch (dev->target->nodetype) {
1528 case LYS_LEAF:
1529 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1530 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1531 break;
1532 case LYS_CONTAINER:
1533 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1534 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1535 break;
1536 case LYS_LEAFLIST:
1537 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1538 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1539 break;
1540 case LYS_LIST:
1541 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1542 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1543 break;
1544 case LYS_ANYXML:
1545 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1546 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1547 break;
1548 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001549 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1550 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001551 goto error;
1552 }
1553
1554 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1555 /* reallocate the must array of the target */
1556 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1557 if (!dev->deviate->must) {
1558 LOGMEM;
1559 goto error;
1560 }
1561 *dev->trg_must = dev->deviate->must;
1562 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1563 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001564 } else {
1565 /* LY_DEVIATE_DEL */
1566 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1567 if (!dev->deviate->must) {
1568 LOGMEM;
1569 goto error;
1570 }
Pavol Vican85f12022016-03-05 16:30:35 +01001571 }
1572
1573 return EXIT_SUCCESS;
1574
1575error:
1576 return EXIT_FAILURE;
1577}
1578
1579int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001580yang_read_deviate_unique(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001581{
1582 int i, j;
1583 struct lys_node_list *list;
1584
1585 /* check target node type */
1586 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001587 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1588 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001589 goto error;
1590 }
1591
1592 list = (struct lys_node_list *)dev->target;
1593 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1594 /* reallocate the unique array of the target */
1595 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1596 if (!dev->deviate->unique) {
1597 LOGMEM;
1598 goto error;
1599 }
1600 list->unique = dev->deviate->unique;
1601 dev->deviate->unique = &list->unique[list->unique_size];
1602 dev->deviate->unique_size = c_uniq;
1603 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001604 } else {
1605 /* LY_DEVIATE_DEL */
1606 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1607 if (!dev->deviate->unique) {
1608 LOGMEM;
1609 goto error;
1610 }
Pavol Vican85f12022016-03-05 16:30:35 +01001611 }
1612
1613 return EXIT_SUCCESS;
1614
1615error:
1616 return EXIT_FAILURE;
1617}
1618
1619int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001620yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001621{
1622 int rc;
1623 struct lys_node_choice *choice;
1624 struct lys_node_leaf *leaf;
1625 struct lys_node *node;
1626
1627 if (dev->deviate->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001628 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001629 free(value);
1630 goto error;
1631 }
1632
1633 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1634
1635 if (dev->target->nodetype == LYS_CHOICE) {
1636 choice = (struct lys_node_choice *)dev->target;
1637
Pavol Vican85f12022016-03-05 16:30:35 +01001638 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1639 if (rc || !node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001640 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vican85f12022016-03-05 16:30:35 +01001641 goto error;
1642 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001643 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1644 if (!choice->dflt || (choice->dflt != node)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001645 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1646 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001647 goto error;
1648 }
1649 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001650 } else {
1651 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1652 /* check that there is no current value */
1653 if (choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1655 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001656 goto error;
1657 }
1658 } else { /* replace*/
1659 if (!choice->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001660 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1661 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001662 goto error;
1663 }
1664 }
1665
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001666 choice->dflt = node;
1667 if (!choice->dflt) {
1668 /* default branch not found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001669 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001670 goto error;
1671 }
Pavol Vican85f12022016-03-05 16:30:35 +01001672 }
1673 } else if (dev->target->nodetype == LYS_LEAF) {
1674 leaf = (struct lys_node_leaf *)dev->target;
1675
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001676 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1677 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001678 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1679 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001680 goto error;
1681 }
1682 /* remove value */
1683 lydict_remove(ctx, leaf->dflt);
1684 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001685 } else {
1686 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1687 /* check that there is no current value */
1688 if (leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001689 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1690 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001691 goto error;
1692 }
1693 } else { /* replace*/
1694 if (!leaf->dflt) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001695 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1696 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001697 goto error;
1698 }
1699 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001700 /* remove value */
1701 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001702
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001703 /* set new value */
1704 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1705 }
Pavol Vican85f12022016-03-05 16:30:35 +01001706 } else {
1707 /* invalid target for default value */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001708 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1709 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001710 goto error;
1711 }
1712
1713 return EXIT_SUCCESS;
1714
1715error:
1716 return EXIT_FAILURE;
1717}
1718
1719int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001720yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001721{
1722 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001723 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001724 goto error;
1725 }
1726
1727 /* for we deviate from RFC 6020 and allow config property even it is/is not
1728 * specified in the target explicitly since config property inherits. So we expect
1729 * that config is specified in every node. But for delete, we check that the value
1730 * is the same as here in deviation
1731 */
1732 dev->deviate->flags |= value;
1733
1734 /* add and replace are the same in this case */
1735 /* remove current config value of the target ... */
1736 dev->target->flags &= ~LYS_CONFIG_MASK;
1737
1738 /* ... and replace it with the value specified in deviation */
1739 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1740
1741 return EXIT_SUCCESS;
1742
1743error:
1744 return EXIT_FAILURE;
1745}
1746
1747int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001748yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001749{
1750 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001751 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001752 goto error;
1753 }
1754
1755 /* check target node type */
1756 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001757 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1758 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001759 goto error;
1760 }
1761
1762 dev->deviate->flags |= value;
1763
1764 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1765 /* check that there is no current value */
1766 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001767 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1768 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001769 goto error;
1770 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001771 } else { /* replace */
1772 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001773 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1774 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001775 goto error;
1776 }
Pavol Vican85f12022016-03-05 16:30:35 +01001777 }
1778
Pavol Vican85f12022016-03-05 16:30:35 +01001779 /* remove current mandatory value of the target ... */
1780 dev->target->flags &= ~LYS_MAND_MASK;
1781
1782 /* ... and replace it with the value specified in deviation */
1783 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1784
1785 return EXIT_SUCCESS;
1786
1787error:
1788 return EXIT_FAILURE;
1789}
1790
1791int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001792yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001793{
1794 uint32_t *ui32val;
1795
1796 /* check target node type */
1797 if (dev->target->nodetype == LYS_LEAFLIST) {
1798 if (type) {
1799 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1800 } else {
1801 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1802 }
1803 } else if (dev->target->nodetype == LYS_LIST) {
1804 if (type) {
1805 ui32val = &((struct lys_node_list *)dev->target)->max;
1806 } else {
1807 ui32val = &((struct lys_node_list *)dev->target)->min;
1808 }
1809 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001810 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1811 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 +01001812 goto error;
1813 }
1814
1815 if (type) {
1816 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001817 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001818 } else {
1819 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001820 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001821 }
1822
1823 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1824 /* check that there is no current value */
1825 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001826 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1827 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001828 goto error;
1829 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001830 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1831 /* unfortunately, there is no way to check reliably that there
1832 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001833 }
1834
1835 /* add (already checked) and replace */
1836 /* set new value specified in deviation */
1837 *ui32val = value;
1838
1839 return EXIT_SUCCESS;
1840
1841error:
1842 return EXIT_FAILURE;
1843}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001844
1845int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001846yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001847{
1848 int i;
1849
1850 /* find must to delete, we are ok with just matching conditions */
1851 for (i = 0; i < *dev->trg_must_size; i++) {
1852 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1853 /* we have a match, free the must structure ... */
1854 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1855 /* ... and maintain the array */
1856 (*dev->trg_must_size)--;
1857 if (i != *dev->trg_must_size) {
1858 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1859 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1860 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1861 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1862 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1863 }
1864 if (!(*dev->trg_must_size)) {
1865 free(*dev->trg_must);
1866 *dev->trg_must = NULL;
1867 } else {
1868 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1869 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1870 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1871 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1872 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1873 }
1874
1875 i = -1; /* set match flag */
1876 break;
1877 }
1878 }
1879 if (i != -1) {
1880 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001881 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1882 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001883 return EXIT_FAILURE;
1884 }
1885
1886 return EXIT_SUCCESS;
1887}
1888
1889int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001890yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001891{
1892 struct lys_node_list *list;
1893 int i, j;
1894
1895 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001896 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001897 dev->deviate->unique_size++;
1898 goto error;
1899 }
1900
1901 /* find unique structures to delete */
1902 for (i = 0; i < list->unique_size; i++) {
1903 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1904 continue;
1905 }
1906
1907 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1908 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1909 break;
1910 }
1911 }
1912
1913 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1914 /* we have a match, free the unique structure ... */
1915 for (j = 0; j < list->unique[i].expr_size; j++) {
1916 lydict_remove(module->ctx, list->unique[i].expr[j]);
1917 }
1918 free(list->unique[i].expr);
1919 /* ... and maintain the array */
1920 list->unique_size--;
1921 if (i != list->unique_size) {
1922 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1923 list->unique[i].expr = list->unique[list->unique_size].expr;
1924 }
1925
1926 if (!list->unique_size) {
1927 free(list->unique);
1928 list->unique = NULL;
1929 } else {
1930 list->unique[list->unique_size].expr_size = 0;
1931 list->unique[list->unique_size].expr = NULL;
1932 }
1933
1934 i = -1; /* set match flag */
1935 break;
1936 }
1937 }
1938 dev->deviate->unique_size++;
1939
1940 if (i != -1) {
1941 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001942 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1943 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001944 goto error;
1945 }
1946
1947 free(value);
1948 return EXIT_SUCCESS;
1949
1950error:
1951 free(value);
1952 return EXIT_FAILURE;
1953}
Pavol Vicane92421d2016-03-08 10:12:33 +01001954
1955int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001956yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01001957{
1958 int i, rc;
1959
1960 if (dev->target->nodetype == LYS_LEAF) {
1961 for(i = 0; i < dev->deviation->deviate_size; ++i) {
1962 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
1963 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001964 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 +01001965 if (rc == -1) {
1966 return EXIT_FAILURE;
1967 } else if (rc == EXIT_FAILURE) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001968 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 +01001969 return EXIT_FAILURE;
1970 }
1971 break;
1972 }
1973 }
1974 }
1975 }
1976 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001977}
1978
1979int
1980yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vican0adf01d2016-03-22 12:29:33 +01001981 char *rev, int inc_size, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01001982{
1983 struct lys_include inc;
1984 struct lys_module *trg;
1985 int i;
Pavol Vican55870412016-03-10 12:36:21 +01001986 const char *str;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001987
Pavol Vican55870412016-03-10 12:36:21 +01001988 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001989 trg = (submodule) ? (struct lys_module *)submodule : module;
1990 inc.submodule = NULL;
1991 inc.external = 0;
1992 memcpy(inc.rev, rev, LY_REV_SIZE);
Pavol Vican0adf01d2016-03-22 12:29:33 +01001993 if (lyp_check_include(module, submodule, str, &inc, unres)) {
Pavol Vican9b89dda2016-03-09 15:36:55 +01001994 goto error;
1995 }
1996 memcpy(&trg->inc[inc_size], &inc, sizeof inc);
1997
1998 /* check duplications in include submodules */
1999 for (i = 0; i < inc_size; ++i) {
2000 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size].submodule->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002001 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
2002 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01002003 trg->inc[inc_size].submodule = NULL;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002004 goto error;
2005 }
2006 }
Pavol Vican55870412016-03-10 12:36:21 +01002007 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002008 return EXIT_SUCCESS;
2009
2010error:
Pavol Vican55870412016-03-10 12:36:21 +01002011 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002012 return EXIT_FAILURE;
2013}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002014
2015int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002016yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002017{
2018 char *prefix;
2019 char *identif;
2020 const char *ns = NULL;
2021 int i;
2022
Pavol Vicanf4717e62016-03-16 11:30:01 +01002023 /* check to the same pointer */
2024 if (data_node != actual) {
2025 return EXIT_SUCCESS;
2026 }
2027
Pavol Vicana302aa62016-03-17 10:45:35 +01002028 prefix = strdup(value);
2029 if (!prefix) {
2030 LOGMEM;
2031 goto error;
2032 }
2033 /* find prefix anf identificator*/
2034 identif = strchr(prefix, ':');
2035 *identif = '\0';
2036 identif++;
2037
Pavol Vicanf4717e62016-03-16 11:30:01 +01002038 for(i = 0; i < module->imp_size; ++i) {
2039 if (!strcmp(module->imp[i].prefix, prefix)) {
2040 ns = module->imp[i].module->ns;
2041 break;
2042 }
2043 }
2044 if (ns && !strcmp(ns, LY_NSNACM)) {
2045 if (!strcmp(identif, "default-deny-write")) {
2046 data_node->nacm |= LYS_NACM_DENYW;
2047 } else if (!strcmp(identif, "default-deny-all")) {
2048 data_node->nacm |= LYS_NACM_DENYA;
2049 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002050 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002051 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002052 }
2053 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002054 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002055 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002056
2057error:
2058 free(prefix);
2059 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002060}
2061
2062void
2063nacm_inherit(struct lys_module *module)
2064{
2065 struct lys_node *next, *elem;
2066
2067 LY_TREE_DFS_BEGIN(module->data, next, elem) {
2068 if (elem->parent) {
2069 switch (elem->nodetype) {
2070 case LYS_GROUPING:
2071 /* extension nacm not inherited*/
2072 break;
2073 case LYS_CHOICE:
2074 case LYS_ANYXML:
2075 case LYS_USES:
2076 if (elem->parent->nodetype != LYS_GROUPING) {
2077 elem->nacm |= elem->parent->nacm;
2078 }
2079 break;
2080 default:
2081 elem->nacm |= elem->parent->nacm;
2082 break;
2083 }
2084 }
2085 LY_TREE_DFS_END(module->data, next, elem);
2086 }
2087}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002088
2089void
2090store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2091{
2092 node->flags |= flags;
2093 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2094 /* get config flag from parent */
2095 if (node->parent) {
2096 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2097 } else {
2098 /* default config is true */
2099 node->flags |= LYS_CONFIG_W;
2100 }
2101 }
2102}