blob: 9cbb435c0c8c2c22157de181edeb4b716d31f8a1 [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
30yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value, int line)
31{
Pavol Vicanbf805472016-01-26 14:24:56 +010032 if (*target) {
Pavol Vicand72227c2016-02-21 20:29:52 +010033 LOGVAL(LYE_TOOMANY, line, 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
43yang_read_common(struct lys_module *module, char *value, int type, int line)
44{
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:
52 ret = yang_check_string(module, &module->ns, "namespace", "module", value, line);
53 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010054 case ORGANIZATION_KEYWORD:
55 ret = yang_check_string(module, &module->org, "organization", "module", value, line);
56 break;
57 case CONTACT_KEYWORD:
58 ret = yang_check_string(module, &module->contact, "contact", "module", value, line);
59 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
66yang_read_prefix(struct lys_module *module, void *save, char *value, int type, int line)
67{
Pavol Vican6eb14e82016-02-03 12:27:13 +010068 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010069
Pavol Vican6eb14e82016-02-03 12:27:13 +010070 if (lyp_check_identifier(value, LY_IDENT_PREFIX, line, module, NULL)) {
71 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:
76 ret = yang_check_string(module, &module->prefix, "prefix", "module", value, line);
77 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
109yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value, int line)
110{
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);
115 rc = lyp_check_import(module, exp, line, imp);
116 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 Vican723de602016-03-21 15:13:20 +0100124 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, module->imp[i].module->name, "import");
125 LOGVAL(LYE_SPEC, 0, 0, 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 Vican9bcd7c62016-03-17 19:36:35 +0100138yang_read_description(struct lys_module *module, void *node, char *value, char *where, int line)
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 Vican9bcd7c62016-03-17 19:36:35 +0100144 ret = yang_check_string(module, &module->dsc, dsc, "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100145 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100146 if (!strcmp("revision", where)) {
147 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value, line);
148 } else {
149 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100150 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100151 }
152 return ret;
153}
154
155int
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100156yang_read_reference(struct lys_module *module, void *node, char *value, char *where, int line)
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) {
162 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100163 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100164 if (!strcmp("revision", where)) {
165 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value, line);
166 } else {
167 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value, line);
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 *
213yang_read_feature(struct lys_module *module, char *value, int line)
214{
215 struct lys_feature *retval;
216
217 /* check uniqueness of feature's names */
218 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
219 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 Vicanf37eeaa2016-02-09 20:54:06 +0100233yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, int type, int line)
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
240 if (!(exp = transform_schema2json(module, value, line))) {
241 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;
250 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
251 f->features_size++;
252 } else {
253 n = (struct lys_node *) ptr;
254 n->features[n->features_size] = (struct lys_feature *) n;
255 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
256 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 Vicane1354e92016-02-09 14:02:09 +0100268yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
269{
270 if (*flags & mask) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100271 LOGVAL(LYE_TOOMANY, line, 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
292yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
293{
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 Vicanbbdef532016-02-09 14:52:12 +0100300 exp = transform_schema2json(module, value, line);
301 free(value);
302 if (!exp) {
303 return EXIT_FAILURE;
304 }
305 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
306 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 Vicanf37eeaa2016-02-09 20:54:06 +0100315yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
316{
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 }
346 retval->expr = transform_schema2json(module, value, line);
347 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
348 goto error;
349 }
350 free(value);
351 return retval;
352
353error:
354 free(value);
355 return NULL;
356}
357
358int
Pavol Vicana3436942016-03-21 09:25:52 +0100359yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message, int line)
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 Vicana3436942016-03-21 09:25:52 +0100364 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100365 } else {
Pavol Vicana3436942016-03-21 09:25:52 +0100366 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100367 }
368 return ret;
369}
Pavol Vicanb5687112016-02-09 22:35:59 +0100370
371int
372yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
373{
374 if (cont->presence) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100375 LOGVAL(LYE_TOOMANY, line, 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 *
385yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
386{
387 struct lys_when *retval;
388
389 retval = calloc(1, sizeof *retval);
390 if (!retval) {
391 LOGMEM;
392 free(value);
393 return NULL;
394 }
395 retval->cond = transform_schema2json(module, value, line);
396 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
397 goto error;
398 }
399 switch (type) {
400 case CONTAINER_KEYWORD:
401 if (((struct lys_node_container *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100402 LOGVAL(LYE_TOOMANY, line, 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 Vicand72227c2016-02-21 20:29:52 +0100409 LOGVAL(LYE_TOOMANY, line, 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 Vicand72227c2016-02-21 20:29:52 +0100416 LOGVAL(LYE_TOOMANY, line, 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 Vicand72227c2016-02-21 20:29:52 +0100423 LOGVAL(LYE_TOOMANY, line, 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 Vicand72227c2016-02-21 20:29:52 +0100430 LOGVAL(LYE_TOOMANY, line, 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 Vicand72227c2016-02-21 20:29:52 +0100437 LOGVAL(LYE_TOOMANY, line, 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) {
444 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "list");
445 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) {
451 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "uses");
452 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) {
458 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "augment");
459 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 Vican096c6db2016-02-11 15:08:10 +0100503yang_read_default(struct lys_module *module, void *node, char *value, int type, int line)
504{
505 int ret;
506
507 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100508 case LEAF_KEYWORD:
509 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, line);
510 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100511 case TYPEDEF_KEYWORD:
512 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, line);
513 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100514 }
515 return ret;
516}
517
518int
519yang_read_units(struct lys_module *module, void *node, char *value, int type, int line)
520{
521 int ret;
522
523 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100524 case LEAF_KEYWORD:
525 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, line);
526 break;
527 case LEAF_LIST_KEYWORD:
528 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, line);
529 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100530 case TYPEDEF_KEYWORD:
531 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, line);
532 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100533 }
534 return ret;
535}
Pavol Vican5de33492016-02-22 14:03:24 +0100536
537int
538yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres, int line)
539{
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 }
555 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp, line) == -1) {
556 goto error;
557 }
558 free(exp);
559 return EXIT_SUCCESS;
560
561error:
562 free(exp);
563 return EXIT_FAILURE;
564}
565
566int
Pavol Vican85f12022016-03-05 16:30:35 +0100567yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres, int line)
568{
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)) {
600 LOGVAL(LYE_INARG, line, LY_VLOG_LYS, list, unique->expr[i], "unique");
601 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
602 goto error;
603 }
604 }
605 /* try to resolve leaf */
606 if (unres) {
607 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i], line);
608 } else {
609 if (resolve_unique((struct lys_node *)list, unique->expr[i], 0, line)) {
610 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 Vican5de33492016-02-22 14:03:24 +0100631 struct type_ident *ident;
632
633 for(k=0; k<list->unique_size; k++) {
Pavol Vican5de33492016-02-22 14:03:24 +0100634 ident = (struct type_ident *)list->unique[k].expr;
Pavol Vican85f12022016-03-05 16:30:35 +0100635 if (yang_fill_unique(module, list, &list->unique[k], ident->s, unres, ident->line)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100636 goto error;
637 }
Pavol Vican5de33492016-02-22 14:03:24 +0100638 free(ident);
639 }
640 return EXIT_SUCCESS;
641
642error:
643 free(ident);
644 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100645}
646
Pavol Vican1ff0e222016-02-26 12:27:01 +0100647static int
648yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres, int line)
649{
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 */
655 value = transform_schema2json(module, value, line);
656 if (!value) {
657 goto end;
658 }
659 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, line);
660 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 Vican73e7c992016-02-24 12:18:05 +0100683 value = transform_schema2json(module, typ->name, typ->line);
684 if (!value) {
685 goto error;
686 }
687
688 i = parse_identifier(value);
689 if (i < 1) {
690 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
691 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)) {
700 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, name[0], name);
701 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) {
710 LOGVAL(LYE_INMOD, typ->line, LY_VLOG_NONE, NULL, typ->type->module_name);
711 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) {
726 LOGVAL(LYE_SPEC, typ->line, 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 Vican73e7c992016-02-24 12:18:05 +0100732 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
733 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 Vican73e7c992016-02-24 12:18:05 +0100737 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
738 goto error;
739 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100740 } else {
741 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
742 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 Vicanaff5c802016-02-24 15:56:45 +0100748 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
749 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 Vican723de602016-03-21 15:13:20 +0100754 LOGVAL(LYE_MISSCHILDSTMT, typ->line, 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 */
759 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits");
760 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) {
764 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
765 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 Vicanaff5c802016-02-24 15:56:45 +0100770 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
771 goto error;
772 }
773 } else {
774 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
775 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) {
780 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
781 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 Vican723de602016-03-21 15:13:20 +0100785 LOGVAL(LYE_MISSCHILDSTMT, typ->line, 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 */
790 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "enum");
791 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) {
796 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
797 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 */
801 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "bit", "type");
802 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 */
806 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "bit");
807 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) {
812 if (yang_read_identyref(module, typ->type, unres, typ->line)) {
813 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 */
819 typ->type->info.lref.path = transform_schema2json(module, value, typ->line);
820 lydict_remove(module->ctx, value);
821 if (!typ->type->info.lref.path) {
822 goto error;
823 }
824 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent, typ->line) == -1) {
825 goto error;
826 }
827 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
Pavol Vican723de602016-03-21 15:13:20 +0100828 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100829 goto error;
830 } else {
831 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "path");
832 goto error;
833 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100834 } else {
835 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
836 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 Vican723de602016-03-21 15:13:20 +0100844 LOGVAL(LYE_MISSCHILDSTMT, typ->line, 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;
851 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
852 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 Vican723de602016-03-21 15:13:20 +0100859 LOGVAL(LYE_MISSCHILDSTMT, typ->line, 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;
864 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent, typ_tmp->line)) {
865 goto error;
866 }
867 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
868 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "empty", typ->name);
869 goto error;
870 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
871 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "leafref", typ->name);
872 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) {
880 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
881 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 Vican4766aca2016-03-07 12:42:36 +0100900yang_read_type(struct lys_module *module, void *parent, char *value, int type, int line)
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) {
936 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "type", "deviation");
937 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 {
945 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "type");
946 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"type\" property.");
947 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;
963 typ->line = line;
Pavol Vican73e7c992016-02-24 12:18:05 +0100964 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100965
966error:
967 free(typ);
968 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +0100969}
970
971void *
972yang_read_length(struct lys_module *module, struct yang_type *typ, char *value, int line)
973{
974 struct lys_restr **length;
975
976 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
977 length = &typ->type->info.str.length;
978 typ->type->base = LY_TYPE_STRING;
979 } else if (typ->type->base == LY_TYPE_BINARY) {
980 length = &typ->type->info.binary.length;
981 } else {
982 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected length statement.");
983 goto error;
984 }
985
986 if (*length) {
987 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "length", "type");
988 }
989 *length = calloc(1, sizeof **length);
990 if (!*length) {
991 LOGMEM;
992 goto error;
993 }
994 (*length)->expr = lydict_insert_zc(module->ctx, value);
995 return *length;
996
997error:
998 free(value);
999 return NULL;
1000
1001}
Pavol Vican1c203db2016-02-24 14:05:23 +01001002
1003void *
1004yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value, int line)
1005{
1006 pcre *precomp;
1007 int err_offset;
1008 const char *err_ptr;
1009
1010 /* check that the regex is valid */
1011 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1012 if (!precomp) {
1013 LOGVAL(LYE_INREGEX, line, LY_VLOG_NONE, NULL, value, err_ptr);
1014 free(value);
1015 return NULL;
1016 }
1017 free(precomp);
1018
1019 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1020 typ->type->info.str.pat_count++;
1021 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1022}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001023
1024void *
1025yang_read_range(struct lys_module *module, struct yang_type *typ, char *value, int line)
1026{
1027 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
1028 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1029 goto error;
1030 }
1031 typ->type->base = LY_TYPE_DEC64;
1032 if (typ->type->info.dec64.range) {
1033 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
1034 goto error;
1035 }
1036 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1037 if (!typ->type->info.dec64.range) {
1038 LOGMEM;
1039 goto error;
1040 }
1041 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1042 return typ->type->info.dec64.range;
1043
1044error:
1045 free(value);
1046 return NULL;
1047}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001048
1049int
1050yang_read_fraction(struct yang_type *typ, uint32_t value, int line)
1051{
1052 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1053 typ->type->base = LY_TYPE_DEC64;
1054 } else {
1055 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
1056 goto error;
1057 }
1058 if (typ->type->info.dec64.dig) {
1059 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1060 goto error;
1061 }
1062 /* range check */
1063 if (value < 1 || value > 18) {
1064 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
1065 goto error;
1066 }
1067 typ->type->info.dec64.dig = value;
1068 return EXIT_SUCCESS;
1069
1070error:
1071 return EXIT_FAILURE;
1072}
Pavol Vican79a763d2016-02-25 15:41:27 +01001073
1074void *
1075yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value, int line)
1076{
1077 struct lys_type_enum *enm;
1078 int i;
1079
1080 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1081 enm->name = lydict_insert_zc(module->ctx, value);
1082
1083 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1084 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
1085 LOGVAL(LYE_ENUM_WS, line, LY_VLOG_NONE, NULL, enm->name);
1086 goto error;
1087 }
1088
1089 /* check the name uniqueness */
1090 for (i = 0; i < typ->type->info.enums.count; i++) {
1091 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
1092 LOGVAL(LYE_ENUM_DUPNAME, line, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1093 goto error;
1094 }
1095 }
1096
1097 typ->type->info.enums.count++;
1098 return enm;
1099
1100error:
1101 typ->type->info.enums.count++;
1102 return NULL;
1103}
1104
1105int
1106yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign, int line)
1107{
1108 int i, j;
1109
1110 if (!assign) {
1111 /* assign value automatically */
1112 if (*value > INT32_MAX) {
1113 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1114 goto error;
1115 }
1116 enm->value = *value;
1117 enm->flags |= LYS_AUTOASSIGNED;
1118 (*value)++;
1119 }
1120
1121 /* check that the value is unique */
1122 j = typ->type->info.enums.count-1;
1123 for (i = 0; i < j; i++) {
1124 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
1125 LOGVAL(LYE_ENUM_DUPVAL, line, LY_VLOG_NONE, NULL,
1126 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1127 goto error;
1128 }
1129 }
1130
1131 return EXIT_SUCCESS;
1132
1133error:
1134 return EXIT_FAILURE;
1135}
Pavol Vican9887c682016-02-29 11:32:01 +01001136
1137void *
1138yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value, int line)
1139{
1140 int i;
1141 struct lys_type_bit *bit;
1142
1143 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
1144 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, line, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001145 free(value);
1146 goto error;
1147 }
1148 bit->name = lydict_insert_zc(module->ctx, value);
1149
1150 /* check the name uniqueness */
1151 for (i = 0; i < typ->type->info.bits.count; i++) {
1152 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
1153 LOGVAL(LYE_BITS_DUPNAME, line, LY_VLOG_NONE, NULL, bit->name);
1154 typ->type->info.bits.count++;
1155 goto error;
1156 }
1157 }
1158 typ->type->info.bits.count++;
1159 return bit;
1160
1161error:
1162 return NULL;
1163}
1164
1165int
1166yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign, int line)
1167{
1168 int i,j;
1169 struct lys_type_bit bit_tmp;
1170
1171 if (!assign) {
1172 /* assign value automatically */
1173 if (*value > UINT32_MAX) {
1174 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
1175 goto error;
1176 }
1177 bit->pos = (uint32_t)*value;
1178 bit->flags |= LYS_AUTOASSIGNED;
1179 (*value)++;
1180 }
1181
1182 j = typ->type->info.bits.count - 1;
1183 /* check that the value is unique */
1184 for (i = 0; i < j; i++) {
1185 if (typ->type->info.bits.bit[i].pos == bit->pos) {
1186 LOGVAL(LYE_BITS_DUPVAL, line, LY_VLOG_NONE, NULL, bit->pos, bit->name);
1187 goto error;
1188 }
1189 }
1190
1191 /* keep them ordered by position */
1192 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1193 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001194 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1195 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1196 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001197 j--;
1198 }
1199
1200 return EXIT_SUCCESS;
1201
1202error:
1203 return EXIT_FAILURE;
1204}
Pavol Vican0df02b02016-03-01 10:28:50 +01001205
1206void *
1207yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value, int line)
1208{
1209 struct lys_tpdf *ret;
1210
1211 if (lyp_check_identifier(value, LY_IDENT_TYPE, line, module, parent)) {
1212 free(value);
1213 return NULL;
1214 }
1215 if (!parent) {
1216 ret = &module->tpdf[module->tpdf_size];
1217 ret->type.parent = NULL;
1218 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001219 } else {
1220 switch (parent->nodetype) {
1221 case LYS_GROUPING:
1222 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001223 ((struct lys_node_grp *)parent)->tpdf_size++;
1224 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001225 case LYS_CONTAINER:
1226 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1227 ((struct lys_node_container *)parent)->tpdf_size++;
1228 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001229 case LYS_LIST:
1230 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1231 ((struct lys_node_list *)parent)->tpdf_size++;
1232 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001233 case LYS_RPC:
1234 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1235 ((struct lys_node_rpc *)parent)->tpdf_size++;
1236 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001237 case LYS_INPUT:
1238 case LYS_OUTPUT:
1239 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1240 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1241 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001242 case LYS_NOTIF:
1243 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1244 ((struct lys_node_notif *)parent)->tpdf_size++;
1245 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001246 default:
1247 /* another type of nodetype is error*/
1248 LOGINT;
1249 free(value);
1250 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001251 }
Pavol Vican535d50e2016-03-01 13:05:33 +01001252 ret->type.parent = (struct lys_tpdf *)parent;
Pavol Vican0df02b02016-03-01 10:28:50 +01001253 }
1254
1255 ret->name = lydict_insert_zc(module->ctx, value);
1256 ret->module = module;
1257 return ret;
1258}
Pavol Vican1003ead2016-03-02 12:24:52 +01001259
1260void *
1261yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value, int line)
1262{
1263 struct lys_refine *rfn;
1264
1265 rfn = &uses->refine[uses->refine_size];
1266 uses->refine_size++;
1267 rfn->target_name = transform_schema2json(module, value, line);
1268 free(value);
1269 if (!rfn->target_name) {
1270 return NULL;
1271 }
1272 return rfn;
1273}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001274
1275void *
1276yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value, int line)
1277{
1278 struct lys_node_augment *aug;
1279 uint16_t *size;
1280
1281 if (parent) {
1282 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1283 } else {
1284 aug = &module->augment[module->augment_size];
1285 }
1286 aug->nodetype = LYS_AUGMENT;
1287 aug->target_name = transform_schema2json(module, value, line);
1288 free(value);
1289 if (!aug->target_name) {
1290 return NULL;
1291 }
1292 aug->parent = parent;
1293 aug->module = module;
1294 if (parent) {
1295 ((struct lys_node_uses *)parent)->augment_size++;
1296 } else {
1297 module->augment_size++;
1298 }
1299 return aug;
1300}
Pavol Vican220e5a12016-03-03 14:19:43 +01001301
1302void *
1303yang_read_deviation(struct lys_module *module, char *value, int line)
1304{
1305 struct lys_node *dev_target = NULL;
1306 struct lys_deviation *dev;
1307 struct type_deviation *deviation = NULL;
1308 int i, j, rc;
1309
1310 deviation = calloc(1, sizeof *deviation);
1311 if (!deviation) {
1312 LOGMEM;
1313 goto error;
1314 }
1315
1316 dev = &module->deviation[module->deviation_size];
1317 dev->target_name = transform_schema2json(module, value, line);
1318 free(value);
1319 if (!dev->target_name) {
1320 goto error;
1321 }
1322
1323 /* resolve target node */
1324 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1325 if (rc || !dev_target) {
1326 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
1327 goto error;
1328 }
1329 if (dev_target->module == lys_module(module)) {
Pavol Vican723de602016-03-21 15:13:20 +01001330 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1331 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001332 goto error;
1333 }
1334 /*save pointer to the deviation and deviated target*/
1335 deviation->deviation = dev;
1336 deviation->target = dev_target;
1337
1338 /* mark the target module as deviated */
1339 dev_target->module->deviated = 1;
1340
1341 /* copy our imports to the deviated module (deviations may need them to work) */
1342 for (i = 0; i < module->imp_size; ++i) {
1343 for (j = 0; j < dev_target->module->imp_size; ++j) {
1344 if (module->imp[i].module == dev_target->module->imp[j].module) {
1345 break;
1346 }
1347 }
1348
1349 if (j < dev_target->module->imp_size) {
1350 /* import is already there */
1351 continue;
1352 }
1353
1354 /* copy the import, mark it as external */
1355 ++dev_target->module->imp_size;
1356 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1357 if (!dev_target->module->imp) {
1358 LOGMEM;
1359 goto error;
1360 }
1361 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1362 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1363 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1364 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1365 }
1366
1367 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1368 for (i = 0; i < dev_target->module->imp_size; ++i) {
1369 if (dev_target->module->imp[i].module == module) {
1370 break;
1371 }
1372 }
1373
1374 if (i == dev_target->module->imp_size) {
1375 ++dev_target->module->imp_size;
1376 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1377 if (!dev_target->module->imp) {
1378 LOGMEM;
1379 goto error;
1380 }
1381 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1382 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1383 if (module->rev_size) {
1384 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1385 } else {
1386 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1387 }
1388 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1389 } else {
1390 /* it could have been added by another deviating module that imported this deviating module */
1391 dev_target->module->imp[i].external = 2;
1392 }
1393
1394
1395 return deviation;
1396
1397error:
1398 free(deviation);
1399 lydict_remove(module->ctx, dev->target_name);
1400 return NULL;
1401}
Pavol Vican4c90c642016-03-03 15:06:47 +01001402
1403int
1404yang_read_deviate_unsupported(struct type_deviation *dev, int line)
1405{
1406 int i;
1407
1408 if (dev->deviation->deviate_size) {
1409 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1410 return EXIT_FAILURE;
1411 }
1412 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1413
1414 /* you cannot remove a key leaf */
1415 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1416 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1417 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
1418 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1419 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1420 return EXIT_FAILURE;
1421 }
1422 }
1423 }
1424
1425 /* unlink and store the original node */
1426 dev->deviation->orig_node = dev->target;
1427
1428 dev->deviation->deviate_size = 1;
1429 return EXIT_SUCCESS;
1430}
Pavol Vican85f12022016-03-05 16:30:35 +01001431
1432int
1433yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod, int line)
1434{
1435 struct unres_schema tmp_unres;
1436
1437 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1438 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1439 dev->deviation->deviate_size++;
1440 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
1441 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "not-supported");
1442 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1443 return EXIT_FAILURE;
1444 }
1445
1446 /* store a shallow copy of the original node */
1447 if (!dev->deviation->orig_node) {
1448 memset(&tmp_unres, 0, sizeof tmp_unres);
1449 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1450 /* just to be safe */
1451 if (tmp_unres.count) {
1452 LOGINT;
1453 return EXIT_FAILURE;
1454 }
1455 }
1456
1457 return EXIT_SUCCESS;
1458}
1459
1460int
1461yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1462{
1463 const char **stritem;
1464
1465 if (dev->deviate->units) {
1466 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "units", "deviate");
1467 free(value);
1468 goto error;
1469 }
1470
1471 /* check target node type */
1472 if (dev->target->nodetype == LYS_LEAFLIST) {
1473 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1474 } else if (dev->target->nodetype == LYS_LEAF) {
1475 stritem = &((struct lys_node_leaf *)dev->target)->units;
1476 } else {
1477 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1478 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"units\" property.");
1479 free(value);
1480 goto error;
1481 }
1482
1483 dev->deviate->units = lydict_insert_zc(ctx, value);
1484
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001485 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1486 /* check values */
1487 if (*stritem != dev->deviate->units) {
1488 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1489 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1490 goto error;
1491 }
1492 /* remove current units value of the target */
1493 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001494 } else {
1495 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1496 /* check that there is no current value */
1497 if (*stritem) {
1498 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1499 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1500 goto error;
1501 }
1502 } else { /* replace */
1503 if (!*stritem) {
1504 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1505 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1506 goto error;
1507 }
1508 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001509 /* remove current units value of the target ... */
1510 lydict_remove(ctx, *stritem);
1511
1512 /* ... and replace it with the value specified in deviation */
1513 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1514 }
1515
Pavol Vican85f12022016-03-05 16:30:35 +01001516 return EXIT_SUCCESS;
1517
1518error:
1519 return EXIT_FAILURE;
1520}
1521
1522int
1523yang_read_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_must, int line)
1524{
1525 uint8_t i;
1526
1527 /* check target node type */
1528 switch (dev->target->nodetype) {
1529 case LYS_LEAF:
1530 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1531 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1532 break;
1533 case LYS_CONTAINER:
1534 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1535 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1536 break;
1537 case LYS_LEAFLIST:
1538 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1539 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1540 break;
1541 case LYS_LIST:
1542 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1543 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1544 break;
1545 case LYS_ANYXML:
1546 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1547 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1548 break;
1549 default:
1550 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "must");
1551 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"must\" property.");
1552 goto error;
1553 }
1554
1555 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1556 /* reallocate the must array of the target */
1557 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1558 if (!dev->deviate->must) {
1559 LOGMEM;
1560 goto error;
1561 }
1562 *dev->trg_must = dev->deviate->must;
1563 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1564 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001565 } else {
1566 /* LY_DEVIATE_DEL */
1567 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1568 if (!dev->deviate->must) {
1569 LOGMEM;
1570 goto error;
1571 }
Pavol Vican85f12022016-03-05 16:30:35 +01001572 }
1573
1574 return EXIT_SUCCESS;
1575
1576error:
1577 return EXIT_FAILURE;
1578}
1579
1580int
1581yang_read_deviate_unique(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_uniq, int line)
1582{
1583 int i, j;
1584 struct lys_node_list *list;
1585
1586 /* check target node type */
1587 if (dev->target->nodetype != LYS_LIST) {
1588 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "unique");
1589 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"unique\" property.");
1590 goto error;
1591 }
1592
1593 list = (struct lys_node_list *)dev->target;
1594 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1595 /* reallocate the unique array of the target */
1596 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1597 if (!dev->deviate->unique) {
1598 LOGMEM;
1599 goto error;
1600 }
1601 list->unique = dev->deviate->unique;
1602 dev->deviate->unique = &list->unique[list->unique_size];
1603 dev->deviate->unique_size = c_uniq;
1604 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001605 } else {
1606 /* LY_DEVIATE_DEL */
1607 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1608 if (!dev->deviate->unique) {
1609 LOGMEM;
1610 goto error;
1611 }
Pavol Vican85f12022016-03-05 16:30:35 +01001612 }
1613
1614 return EXIT_SUCCESS;
1615
1616error:
1617 return EXIT_FAILURE;
1618}
1619
1620int
1621yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1622{
1623 int rc;
1624 struct lys_node_choice *choice;
1625 struct lys_node_leaf *leaf;
1626 struct lys_node *node;
1627
1628 if (dev->deviate->dflt) {
1629 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "default", "deviate");
1630 free(value);
1631 goto error;
1632 }
1633
1634 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1635
1636 if (dev->target->nodetype == LYS_CHOICE) {
1637 choice = (struct lys_node_choice *)dev->target;
1638
Pavol Vican85f12022016-03-05 16:30:35 +01001639 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1640 if (rc || !node) {
1641 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1642 goto error;
1643 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001644 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1645 if (!choice->dflt || (choice->dflt != node)) {
1646 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1647 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1648 goto error;
1649 }
1650 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001651 } else {
1652 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1653 /* check that there is no current value */
1654 if (choice->dflt) {
1655 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1656 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1657 goto error;
1658 }
1659 } else { /* replace*/
1660 if (!choice->dflt) {
1661 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1662 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1663 goto error;
1664 }
1665 }
1666
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001667 choice->dflt = node;
1668 if (!choice->dflt) {
1669 /* default branch not found */
1670 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1671 goto error;
1672 }
Pavol Vican85f12022016-03-05 16:30:35 +01001673 }
1674 } else if (dev->target->nodetype == LYS_LEAF) {
1675 leaf = (struct lys_node_leaf *)dev->target;
1676
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001677 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1678 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
1679 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1680 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1681 goto error;
1682 }
1683 /* remove value */
1684 lydict_remove(ctx, leaf->dflt);
1685 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001686 } else {
1687 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1688 /* check that there is no current value */
1689 if (leaf->dflt) {
1690 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1691 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1692 goto error;
1693 }
1694 } else { /* replace*/
1695 if (!leaf->dflt) {
1696 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1697 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1698 goto error;
1699 }
1700 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001701 /* remove value */
1702 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001703
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001704 /* set new value */
1705 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1706 }
Pavol Vican85f12022016-03-05 16:30:35 +01001707 } else {
1708 /* invalid target for default value */
1709 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1710 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"default\" property.");
1711 goto error;
1712 }
1713
1714 return EXIT_SUCCESS;
1715
1716error:
1717 return EXIT_FAILURE;
1718}
1719
1720int
1721yang_read_deviate_config(struct type_deviation *dev, uint8_t value, int line)
1722{
1723 if (dev->deviate->flags & LYS_CONFIG_MASK) {
1724 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "config", "deviate");
1725 goto error;
1726 }
1727
1728 /* for we deviate from RFC 6020 and allow config property even it is/is not
1729 * specified in the target explicitly since config property inherits. So we expect
1730 * that config is specified in every node. But for delete, we check that the value
1731 * is the same as here in deviation
1732 */
1733 dev->deviate->flags |= value;
1734
1735 /* add and replace are the same in this case */
1736 /* remove current config value of the target ... */
1737 dev->target->flags &= ~LYS_CONFIG_MASK;
1738
1739 /* ... and replace it with the value specified in deviation */
1740 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1741
1742 return EXIT_SUCCESS;
1743
1744error:
1745 return EXIT_FAILURE;
1746}
1747
1748int
1749yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value, int line)
1750{
1751 if (dev->deviate->flags & LYS_MAND_MASK) {
1752 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "mandatory", "deviate");
1753 goto error;
1754 }
1755
1756 /* check target node type */
1757 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
1758 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1759 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"mandatory\" property.");
1760 goto error;
1761 }
1762
1763 dev->deviate->flags |= value;
1764
1765 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1766 /* check that there is no current value */
1767 if (dev->target->flags & LYS_MAND_MASK) {
1768 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1769 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1770 goto error;
1771 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001772 } else { /* replace */
1773 if (!(dev->target->flags & LYS_MAND_MASK)) {
1774 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1775 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1776 goto error;
1777 }
Pavol Vican85f12022016-03-05 16:30:35 +01001778 }
1779
Pavol Vican85f12022016-03-05 16:30:35 +01001780 /* remove current mandatory value of the target ... */
1781 dev->target->flags &= ~LYS_MAND_MASK;
1782
1783 /* ... and replace it with the value specified in deviation */
1784 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1785
1786 return EXIT_SUCCESS;
1787
1788error:
1789 return EXIT_FAILURE;
1790}
1791
1792int
1793yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type, int line)
1794{
1795 uint32_t *ui32val;
1796
1797 /* check target node type */
1798 if (dev->target->nodetype == LYS_LEAFLIST) {
1799 if (type) {
1800 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1801 } else {
1802 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1803 }
1804 } else if (dev->target->nodetype == LYS_LIST) {
1805 if (type) {
1806 ui32val = &((struct lys_node_list *)dev->target)->max;
1807 } else {
1808 ui32val = &((struct lys_node_list *)dev->target)->min;
1809 }
1810 } else {
1811 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1812 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
1813 goto error;
1814 }
1815
1816 if (type) {
1817 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001818 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001819 } else {
1820 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001821 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001822 }
1823
1824 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1825 /* check that there is no current value */
1826 if (*ui32val) {
1827 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1828 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1829 goto error;
1830 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001831 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1832 /* unfortunately, there is no way to check reliably that there
1833 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001834 }
1835
1836 /* add (already checked) and replace */
1837 /* set new value specified in deviation */
1838 *ui32val = value;
1839
1840 return EXIT_SUCCESS;
1841
1842error:
1843 return EXIT_FAILURE;
1844}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001845
1846int
1847yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line)
1848{
1849 int i;
1850
1851 /* find must to delete, we are ok with just matching conditions */
1852 for (i = 0; i < *dev->trg_must_size; i++) {
1853 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1854 /* we have a match, free the must structure ... */
1855 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1856 /* ... and maintain the array */
1857 (*dev->trg_must_size)--;
1858 if (i != *dev->trg_must_size) {
1859 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1860 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1861 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1862 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1863 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1864 }
1865 if (!(*dev->trg_must_size)) {
1866 free(*dev->trg_must);
1867 *dev->trg_must = NULL;
1868 } else {
1869 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1870 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1871 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1872 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1873 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1874 }
1875
1876 i = -1; /* set match flag */
1877 break;
1878 }
1879 }
1880 if (i != -1) {
1881 /* no match found */
1882 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1883 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
1884 return EXIT_FAILURE;
1885 }
1886
1887 return EXIT_SUCCESS;
1888}
1889
1890int
1891yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line)
1892{
1893 struct lys_node_list *list;
1894 int i, j;
1895
1896 list = (struct lys_node_list *)dev->target;
1897 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL, line)) {
1898 dev->deviate->unique_size++;
1899 goto error;
1900 }
1901
1902 /* find unique structures to delete */
1903 for (i = 0; i < list->unique_size; i++) {
1904 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1905 continue;
1906 }
1907
1908 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1909 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1910 break;
1911 }
1912 }
1913
1914 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1915 /* we have a match, free the unique structure ... */
1916 for (j = 0; j < list->unique[i].expr_size; j++) {
1917 lydict_remove(module->ctx, list->unique[i].expr[j]);
1918 }
1919 free(list->unique[i].expr);
1920 /* ... and maintain the array */
1921 list->unique_size--;
1922 if (i != list->unique_size) {
1923 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1924 list->unique[i].expr = list->unique[list->unique_size].expr;
1925 }
1926
1927 if (!list->unique_size) {
1928 free(list->unique);
1929 list->unique = NULL;
1930 } else {
1931 list->unique[list->unique_size].expr_size = 0;
1932 list->unique[list->unique_size].expr = NULL;
1933 }
1934
1935 i = -1; /* set match flag */
1936 break;
1937 }
1938 }
1939 dev->deviate->unique_size++;
1940
1941 if (i != -1) {
1942 /* no match found */
1943 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, value, "unique");
1944 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1945 goto error;
1946 }
1947
1948 free(value);
1949 return EXIT_SUCCESS;
1950
1951error:
1952 free(value);
1953 return EXIT_FAILURE;
1954}
Pavol Vicane92421d2016-03-08 10:12:33 +01001955
1956int
1957yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres, int line)
1958{
1959 int i, rc;
1960
1961 if (dev->target->nodetype == LYS_LEAF) {
1962 for(i = 0; i < dev->deviation->deviate_size; ++i) {
1963 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
1964 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
1965 rc = unres_schema_add_str(module, unres, &((struct lys_node_leaf *)dev->target)->type, UNRES_TYPE_DFLT, ((struct lys_node_leaf *)dev->target)->dflt, 0);
1966 if (rc == -1) {
1967 return EXIT_FAILURE;
1968 } else if (rc == EXIT_FAILURE) {
1969 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->deviation->target_name);
1970 return EXIT_FAILURE;
1971 }
1972 break;
1973 }
1974 }
1975 }
1976 }
1977 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001978}
1979
1980int
1981yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
1982 char *rev, int inc_size, struct unres_schema *unres, int line)
1983{
1984 struct lys_include inc;
1985 struct lys_module *trg;
1986 int i;
Pavol Vican55870412016-03-10 12:36:21 +01001987 const char *str;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001988
Pavol Vican55870412016-03-10 12:36:21 +01001989 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001990 trg = (submodule) ? (struct lys_module *)submodule : module;
1991 inc.submodule = NULL;
1992 inc.external = 0;
1993 memcpy(inc.rev, rev, LY_REV_SIZE);
Pavol Vican55870412016-03-10 12:36:21 +01001994 if (lyp_check_include(module, submodule, str, line, &inc, unres)) {
Pavol Vican9b89dda2016-03-09 15:36:55 +01001995 goto error;
1996 }
1997 memcpy(&trg->inc[inc_size], &inc, sizeof inc);
1998
1999 /* check duplications in include submodules */
2000 for (i = 0; i < inc_size; ++i) {
2001 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size].submodule->name)) {
Pavol Vican723de602016-03-21 15:13:20 +01002002 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
2003 LOGVAL(LYE_SPEC, 0, 0, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01002004 trg->inc[inc_size].submodule = NULL;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002005 goto error;
2006 }
2007 }
Pavol Vican55870412016-03-10 12:36:21 +01002008 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002009 return EXIT_SUCCESS;
2010
2011error:
Pavol Vican55870412016-03-10 12:36:21 +01002012 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002013 return EXIT_FAILURE;
2014}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002015
2016int
2017yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value, int line)
2018{
2019 char *prefix;
2020 char *identif;
2021 const char *ns = NULL;
2022 int i;
2023
Pavol Vicanf4717e62016-03-16 11:30:01 +01002024 /* check to the same pointer */
2025 if (data_node != actual) {
2026 return EXIT_SUCCESS;
2027 }
2028
Pavol Vicana302aa62016-03-17 10:45:35 +01002029 prefix = strdup(value);
2030 if (!prefix) {
2031 LOGMEM;
2032 goto error;
2033 }
2034 /* find prefix anf identificator*/
2035 identif = strchr(prefix, ':');
2036 *identif = '\0';
2037 identif++;
2038
Pavol Vicanf4717e62016-03-16 11:30:01 +01002039 for(i = 0; i < module->imp_size; ++i) {
2040 if (!strcmp(module->imp[i].prefix, prefix)) {
2041 ns = module->imp[i].module->ns;
2042 break;
2043 }
2044 }
2045 if (ns && !strcmp(ns, LY_NSNACM)) {
2046 if (!strcmp(identif, "default-deny-write")) {
2047 data_node->nacm |= LYS_NACM_DENYW;
2048 } else if (!strcmp(identif, "default-deny-all")) {
2049 data_node->nacm |= LYS_NACM_DENYA;
2050 } else {
2051 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002052 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002053 }
2054 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002055 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002056 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002057
2058error:
2059 free(prefix);
2060 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002061}
2062
2063void
2064nacm_inherit(struct lys_module *module)
2065{
2066 struct lys_node *next, *elem;
2067
2068 LY_TREE_DFS_BEGIN(module->data, next, elem) {
2069 if (elem->parent) {
2070 switch (elem->nodetype) {
2071 case LYS_GROUPING:
2072 /* extension nacm not inherited*/
2073 break;
2074 case LYS_CHOICE:
2075 case LYS_ANYXML:
2076 case LYS_USES:
2077 if (elem->parent->nodetype != LYS_GROUPING) {
2078 elem->nacm |= elem->parent->nacm;
2079 }
2080 break;
2081 default:
2082 elem->nacm |= elem->parent->nacm;
2083 break;
2084 }
2085 }
2086 LY_TREE_DFS_END(module->data, next, elem);
2087 }
2088}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002089
2090void
2091store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2092{
2093 node->flags |= flags;
2094 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2095 /* get config flag from parent */
2096 if (node->parent) {
2097 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2098 } else {
2099 /* default config is true */
2100 node->flags |= LYS_CONFIG_W;
2101 }
2102 }
2103}