blob: 3521882b72587791105fd38bb5427754c8e4d4a0 [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 Vicand72227c2016-02-21 20:29:52 +0100124 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Pavol Vican6eb14e82016-02-03 12:27:13 +0100125 goto error;
126 }
127 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100128 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100129 return EXIT_SUCCESS;
130
Pavol Vican0da132e2016-03-21 12:03:03 +0100131error:
132 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100133 return EXIT_FAILURE;
134}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100135
136int
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100137yang_read_description(struct lys_module *module, void *node, char *value, char *where, int line)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100138{
139 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100140 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100141
142 if (!node) {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100143 ret = yang_check_string(module, &module->dsc, dsc, "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100144 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100145 if (!strcmp("revision", where)) {
146 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value, line);
147 } else {
148 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100149 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100150 }
151 return ret;
152}
153
154int
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100155yang_read_reference(struct lys_module *module, void *node, char *value, char *where, int line)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100156{
157 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100158 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100159
160 if (!node) {
161 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100162 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100163 if (!strcmp("revision", where)) {
164 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value, line);
165 } else {
166 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100167 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100168 }
169 return ret;
170}
Pavol Vicanbedff692016-02-03 14:29:17 +0100171
172void *
173yang_read_revision(struct lys_module *module, char *value)
174{
175 struct lys_revision *retval;
176
Pavol Vican1eeb1992016-02-09 11:10:45 +0100177 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100178
179 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100180 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100181 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
182 memcpy(module->rev[0].date, value, LY_REV_SIZE);
183 retval->dsc = module->rev[0].dsc;
184 retval->ref = module->rev[0].ref;
185 retval = module->rev;
186 retval->dsc = NULL;
187 retval->ref = NULL;
188 } else {
189 memcpy(retval->date, value, LY_REV_SIZE);
190 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100191 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100192 free(value);
193 return retval;
194}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100195
196int
Pavol Vicana1827962016-02-29 15:39:42 +0100197yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100198{
Pavol Vican45ccc592016-03-09 18:53:48 +0100199 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100200 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
201 LOGMEM;
202 return EXIT_FAILURE;
203 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100204 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100205 }
206 }
207 (*size)++;
208 return EXIT_SUCCESS;
209}
Pavol Vicane1354e92016-02-09 14:02:09 +0100210
211void *
212yang_read_feature(struct lys_module *module, char *value, int line)
213{
214 struct lys_feature *retval;
215
216 /* check uniqueness of feature's names */
217 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
218 goto error;
219 }
220 retval = &module->features[module->features_size];
221 retval->name = lydict_insert_zc(module->ctx, value);
222 retval->module = module;
223 module->features_size++;
224 return retval;
225
226error:
227 free(value);
228 return NULL;
229}
230
231int
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100232yang_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 +0100233{
234 const char *exp;
235 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100236 struct lys_feature *f;
237 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100238
239 if (!(exp = transform_schema2json(module, value, line))) {
240 free(value);
241 return EXIT_FAILURE;
242 }
243 free(value);
244
245 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100246 if (type == FEATURE_KEYWORD) {
247 f = (struct lys_feature *) ptr;
248 f->features[f->features_size] = f;
249 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
250 f->features_size++;
251 } else {
252 n = (struct lys_node *) ptr;
253 n->features[n->features_size] = (struct lys_feature *) n;
254 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
255 n->features_size++;
256 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100257
258 lydict_remove(module->ctx, exp);
259 if (ret == -1) {
260
261 return EXIT_FAILURE;
262 }
263 return EXIT_SUCCESS;
264}
265
Pavol Vican4fb66c92016-03-17 10:32:27 +0100266int
Pavol Vicane1354e92016-02-09 14:02:09 +0100267yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
268{
269 if (*flags & mask) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100270 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100271 return EXIT_FAILURE;
272 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100273 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100274 return EXIT_SUCCESS;
275 }
276}
277
Pavol Vicanbbdef532016-02-09 14:52:12 +0100278void *
279yang_read_identity(struct lys_module *module, char *value)
280{
281 struct lys_ident *ret;
282
283 ret = &module->ident[module->ident_size];
284 ret->name = lydict_insert_zc(module->ctx, value);
285 ret->module = module;
286 module->ident_size++;
287 return ret;
288}
289
290int
291yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
292{
293 const char *exp;
294
Pavol Vicane2368982016-03-19 14:37:56 +0100295 if (!value) {
296 /* base statement not found */
297 return EXIT_SUCCESS;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100298 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100299 exp = transform_schema2json(module, value, line);
300 free(value);
301 if (!exp) {
302 return EXIT_FAILURE;
303 }
304 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
305 lydict_remove(module->ctx, exp);
306 return EXIT_FAILURE;
307 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100308
Pavol Vicanbbdef532016-02-09 14:52:12 +0100309 lydict_remove(module->ctx, exp);
310 return EXIT_SUCCESS;
311}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100312
313void *
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100314yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
315{
316 struct lys_restr *retval;
317
318 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100319 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100320 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100321 break;
322 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100323 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
324 break;
325 case LEAF_KEYWORD:
326 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100327 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100328 case LEAF_LIST_KEYWORD:
329 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
330 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100331 case LIST_KEYWORD:
332 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
333 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100334 case REFINE_KEYWORD:
335 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
336 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100337 case ADD_KEYWORD:
338 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
339 memset(retval, 0, sizeof *retval);
340 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100341 case DELETE_KEYWORD:
342 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
343 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100344 }
345 retval->expr = transform_schema2json(module, value, line);
346 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
347 goto error;
348 }
349 free(value);
350 return retval;
351
352error:
353 free(value);
354 return NULL;
355}
356
357int
Pavol Vicana3436942016-03-21 09:25:52 +0100358yang_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 +0100359{
360 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100361
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100362 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vicana3436942016-03-21 09:25:52 +0100363 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100364 } else {
Pavol Vicana3436942016-03-21 09:25:52 +0100365 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100366 }
367 return ret;
368}
Pavol Vicanb5687112016-02-09 22:35:59 +0100369
370int
371yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
372{
373 if (cont->presence) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100374 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100375 free(value);
376 return EXIT_FAILURE;
377 } else {
378 cont->presence = lydict_insert_zc(module->ctx, value);
379 return EXIT_SUCCESS;
380 }
381}
382
Pavol Vican235dbd42016-02-10 10:34:19 +0100383void *
384yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
385{
386 struct lys_when *retval;
387
388 retval = calloc(1, sizeof *retval);
389 if (!retval) {
390 LOGMEM;
391 free(value);
392 return NULL;
393 }
394 retval->cond = transform_schema2json(module, value, line);
395 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
396 goto error;
397 }
398 switch (type) {
399 case CONTAINER_KEYWORD:
400 if (((struct lys_node_container *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100401 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100402 goto error;
403 }
404 ((struct lys_node_container *)node)->when = retval;
405 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100406 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100407 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100408 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100409 goto error;
410 }
411 ((struct lys_node_anyxml *)node)->when = retval;
412 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100413 case CHOICE_KEYWORD:
414 if (((struct lys_node_choice *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100415 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100416 goto error;
417 }
418 ((struct lys_node_choice *)node)->when = retval;
419 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100420 case CASE_KEYWORD:
421 if (((struct lys_node_case *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100422 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100423 goto error;
424 }
425 ((struct lys_node_case *)node)->when = retval;
426 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100427 case LEAF_KEYWORD:
428 if (((struct lys_node_leaf *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100429 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100430 goto error;
431 }
432 ((struct lys_node_leaf *)node)->when = retval;
433 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100434 case LEAF_LIST_KEYWORD:
435 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100436 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100437 goto error;
438 }
439 ((struct lys_node_leaflist *)node)->when = retval;
440 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100441 case LIST_KEYWORD:
442 if (((struct lys_node_list *)node)->when) {
443 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "list");
444 goto error;
445 }
446 ((struct lys_node_list *)node)->when = retval;
447 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100448 case USES_KEYWORD:
449 if (((struct lys_node_uses *)node)->when) {
450 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "uses");
451 goto error;
452 }
453 ((struct lys_node_uses *)node)->when = retval;
454 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100455 case AUGMENT_KEYWORD:
456 if (((struct lys_node_augment *)node)->when) {
457 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "augment");
458 goto error;
459 }
460 ((struct lys_node_augment *)node)->when = retval;
461 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100462 }
463 free(value);
464 return retval;
465
466error:
467 free(value);
468 lys_when_free(module->ctx, retval);
469 return NULL;
470}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100471
472void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100473yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100474{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100475 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100476
Pavol Vican7cadfe72016-02-11 12:33:34 +0100477 node = calloc(1, sizeof_struct);
478 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100479 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100480 LOGMEM;
481 return NULL;
482 }
Pavol Vican531a9132016-03-03 10:10:09 +0100483 if (value) {
484 node->name = lydict_insert_zc(module->ctx, value);
485 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100486 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100487 node->nodetype = nodetype;
488 node->prev = node;
489
490 /* insert the node into the schema tree */
491 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100492 if (value) {
493 lydict_remove(module->ctx, node->name);
494 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100495 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100496 return NULL;
497 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100498 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100499}
500
501int
Pavol Vican096c6db2016-02-11 15:08:10 +0100502yang_read_default(struct lys_module *module, void *node, char *value, int type, int line)
503{
504 int ret;
505
506 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100507 case LEAF_KEYWORD:
508 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, line);
509 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100510 case TYPEDEF_KEYWORD:
511 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, line);
512 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100513 }
514 return ret;
515}
516
517int
518yang_read_units(struct lys_module *module, void *node, char *value, int type, int line)
519{
520 int ret;
521
522 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100523 case LEAF_KEYWORD:
524 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, line);
525 break;
526 case LEAF_LIST_KEYWORD:
527 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, line);
528 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100529 case TYPEDEF_KEYWORD:
530 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, line);
531 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100532 }
533 return ret;
534}
Pavol Vican5de33492016-02-22 14:03:24 +0100535
536int
537yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres, int line)
538{
539 char *exp, *value;
540
541 exp = value = (char *) list->keys;
542 while ((value = strpbrk(value, " \t\n"))) {
543 list->keys_size++;
544 while (isspace(*value)) {
545 value++;
546 }
547 }
548 list->keys_size++;
549 list->keys = calloc(list->keys_size, sizeof *list->keys);
550 if (!list->keys) {
551 LOGMEM;
552 goto error;
553 }
554 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp, line) == -1) {
555 goto error;
556 }
557 free(exp);
558 return EXIT_SUCCESS;
559
560error:
561 free(exp);
562 return EXIT_FAILURE;
563}
564
565int
Pavol Vican85f12022016-03-05 16:30:35 +0100566yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres, int line)
567{
568 int i, j;
569 char *vaux;
570
571 /* count the number of unique leafs in the value */
572 vaux = value;
573 while ((vaux = strpbrk(vaux, " \t\n"))) {
574 unique->expr_size++;
575 while (isspace(*vaux)) {
576 vaux++;
577 }
578 }
579 unique->expr_size++;
580 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
581 if (!unique->expr) {
582 LOGMEM;
583 goto error;
584 }
585
586 for (i = 0; i < unique->expr_size; i++) {
587 vaux = strpbrk(value, " \t\n");
588 if (!vaux) {
589 /* the last token, lydict_insert() will count its size on its own */
590 vaux = value;
591 }
592
593 /* store token into unique structure */
594 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
595
596 /* check that the expression does not repeat */
597 for (j = 0; j < i; j++) {
598 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
599 LOGVAL(LYE_INARG, line, LY_VLOG_LYS, list, unique->expr[i], "unique");
600 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
601 goto error;
602 }
603 }
604 /* try to resolve leaf */
605 if (unres) {
606 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i], line);
607 } else {
608 if (resolve_unique((struct lys_node *)list, unique->expr[i], 0, line)) {
609 goto error;
610 }
611 }
612
613 /* move to next token */
614 value = vaux;
615 while(isspace(*value)) {
616 value++;
617 }
618 }
619
620 return EXIT_SUCCESS;
621
622error:
623 return EXIT_FAILURE;
624}
625
626int
Pavol Vican5de33492016-02-22 14:03:24 +0100627yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
628{
629 uint8_t k;
Pavol Vican5de33492016-02-22 14:03:24 +0100630 struct type_ident *ident;
631
632 for(k=0; k<list->unique_size; k++) {
Pavol Vican5de33492016-02-22 14:03:24 +0100633 ident = (struct type_ident *)list->unique[k].expr;
Pavol Vican85f12022016-03-05 16:30:35 +0100634 if (yang_fill_unique(module, list, &list->unique[k], ident->s, unres, ident->line)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100635 goto error;
636 }
Pavol Vican5de33492016-02-22 14:03:24 +0100637 free(ident);
638 }
639 return EXIT_SUCCESS;
640
641error:
642 free(ident);
643 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100644}
645
Pavol Vican1ff0e222016-02-26 12:27:01 +0100646static int
647yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres, int line)
648{
649 const char *value, *tmp;
650 int rc, ret = EXIT_FAILURE;
651
652 value = tmp = type->info.lref.path;
653 /* store in the JSON format */
654 value = transform_schema2json(module, value, line);
655 if (!value) {
656 goto end;
657 }
658 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, line);
659 lydict_remove(module->ctx, value);
660
661 if (rc == -1) {
662 goto end;
663 }
664
665 ret = EXIT_SUCCESS;
666
667end:
668 lydict_remove(module->ctx, tmp);
669 return ret;
670}
671
Pavol Vican73e7c992016-02-24 12:18:05 +0100672int
673yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
674{
675 int i, rc;
676 int ret = -1;
677 const char *name, *value;
678 LY_DATA_TYPE base;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100679 struct yang_type *typ_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100680
Pavol Vican0df02b02016-03-01 10:28:50 +0100681 base = typ->type->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100682 value = transform_schema2json(module, typ->name, typ->line);
683 if (!value) {
684 goto error;
685 }
686
687 i = parse_identifier(value);
688 if (i < 1) {
689 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
690 lydict_remove(module->ctx, value);
691 goto error;
692 }
693 /* module name*/
694 name = value;
695 if (value[i]) {
696 typ->type->module_name = lydict_insert(module->ctx, value, i);
697 name += i;
698 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
699 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, name[0], name);
700 lydict_remove(module->ctx, value);
701 goto error;
702 }
703 ++name;
704 }
705
706 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
707 lydict_remove(module->ctx, value);
708 if (rc == -1) {
709 LOGVAL(LYE_INMOD, typ->line, LY_VLOG_NONE, NULL, typ->type->module_name);
710 goto error;
711
712 /* the type could not be resolved or it was resolved to an unresolved typedef*/
713 } else if (rc == EXIT_FAILURE) {
714 ret = EXIT_FAILURE;
715 goto error;
716 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100717 typ->type->base = typ->type->der->type.base;
718 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100719 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100720 }
721 switch (base) {
722 case LY_TYPE_STRING:
723 if (typ->type->base == LY_TYPE_BINARY) {
724 if (typ->type->info.str.pat_count) {
725 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100726 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100727 goto error;
728 }
729 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100730 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 +0100731 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
732 goto error;
733 }
734 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100735 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 +0100736 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
737 goto error;
738 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100739 } else {
740 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
741 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100742 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100743 break;
744 case LY_TYPE_DEC64:
745 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100746 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 +0100747 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
748 goto error;
749 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100750 /* mandatory sub-statement(s) check */
751 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
752 /* decimal64 type directly derived from built-in type requires fraction-digits */
753 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
754 goto error;
755 }
756 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
757 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
758 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits");
759 goto error;
760 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100761 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
762 if (typ->type->info.dec64.dig) {
763 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
764 typ->type->base = base;
765 goto error;
766 }
767 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100768 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 +0100769 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
770 goto error;
771 }
772 } else {
773 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
774 goto error;
775 }
776 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100777 case LY_TYPE_ENUM:
778 if (typ->type->base != LY_TYPE_ENUM) {
779 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
780 goto error;
781 }
782 if (!typ->type->der->type.der && !typ->type->info.enums.count) {
783 /* type is derived directly from buit-in enumeartion type and enum statement is required */
784 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "enum", "type");
785 goto error;
786 }
787 if (typ->type->der->type.der && typ->type->info.enums.count) {
788 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
789 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "enum");
790 goto error;
791 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100792 break;
793 case LY_TYPE_LEAFREF:
794 if (typ->type->base == LY_TYPE_IDENT && typ->flags & LYS_TYPE_BASE) {
795 if (yang_read_identyref(module, typ->type, unres, typ->line)) {
796 goto error;
797 }
Pavol Vican191613a2016-02-26 16:21:32 +0100798 } else if (typ->type->base == LY_TYPE_LEAFREF) {
799 if (typ->type->info.lref.path && !typ->type->der->type.der) {
800 value = typ->type->info.lref.path;
801 /* store in the JSON format */
802 typ->type->info.lref.path = transform_schema2json(module, value, typ->line);
803 lydict_remove(module->ctx, value);
804 if (!typ->type->info.lref.path) {
805 goto error;
806 }
807 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent, typ->line) == -1) {
808 goto error;
809 }
810 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
811 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "path", "type");
812 goto error;
813 } else {
814 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "path");
815 goto error;
816 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100817 } else {
818 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
819 goto error;
820 }
821 break;
822 case LY_TYPE_IDENT:
823 if (typ->type->der->type.der) {
824 /* this is just a derived type with no base specified/required */
825 break;
826 } else {
827 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "base", "type");
828 goto error;
829 }
830 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100831 case LY_TYPE_UNION:
832 if (typ->type->base != LY_TYPE_UNION) {
833 typ->type->base = LY_TYPE_UNION;
834 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
835 goto error;
836 }
837 if (!typ->type->info.uni.types) {
838 if (typ->type->der->type.der) {
839 /* this is just a derived type with no additional type specified/required */
840 break;
841 }
842 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "type", "(union) type");
843 goto error;
844 }
845 for (i = 0; i < typ->type->info.uni.count; i++) {
846 typ_tmp = (struct yang_type *)typ->type->info.uni.types[i].der;
847 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent, typ_tmp->line)) {
848 goto error;
849 }
850 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
851 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "empty", typ->name);
852 goto error;
853 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
854 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "leafref", typ->name);
855 goto error;
856 }
857 }
858 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100859
860 default:
861 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
862 if (typ->type->base != base) {
863 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
864 goto error;
865 }
866 } else {
867 LOGINT;
868 goto error;
869 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100870 }
871 return EXIT_SUCCESS;
872
873error:
Pavol Vicana1827962016-02-29 15:39:42 +0100874 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100875 if (typ->type->module_name) {
876 lydict_remove(module->ctx, typ->type->module_name);
877 typ->type->module_name = NULL;
878 }
879 return ret;
880}
881
882void *
Pavol Vican4766aca2016-03-07 12:42:36 +0100883yang_read_type(struct lys_module *module, void *parent, char *value, int type, int line)
Pavol Vican73e7c992016-02-24 12:18:05 +0100884{
885 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100886 struct type_deviation *dev;
887 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +0100888
Pavol Vicand01d8ae2016-03-01 10:45:59 +0100889 typ = calloc(1, sizeof *typ);
890 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100891 LOGMEM;
892 return NULL;
893 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100894
895 typ->flags = LY_YANG_STRUCTURE_FLAG;
896 switch (type) {
897 case LEAF_KEYWORD:
898 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
899 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
900 typ->type = &((struct lys_node_leaf *)parent)->type;
901 break;
Pavol Vicana55992a2016-03-01 13:37:17 +0100902 case LEAF_LIST_KEYWORD:
903 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
904 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
905 typ->type = &((struct lys_node_leaflist *)parent)->type;
906 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100907 case UNION_KEYWORD:
908 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
909 typ->type = (struct lys_type *)parent;
910 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100911 case TYPEDEF_KEYWORD:
912 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
913 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +0100914 break;
915 case REPLACE_KEYWORD:
916 /* deviation replace type*/
917 dev = (struct type_deviation *)parent;
918 if (dev->deviate->type) {
919 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "type", "deviation");
920 goto error;
921 }
922 /* check target node type */
923 if (dev->target->nodetype == LYS_LEAF) {
924 typ->type = &((struct lys_node_leaf *)dev->target)->type;
925 } else if (dev->target->nodetype == LYS_LEAFLIST) {
926 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
927 } else {
928 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "type");
929 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"type\" property.");
930 goto error;
931 }
932
933 /* remove type and initialize it */
934 lys_type_free(module->ctx, typ->type);
935 tmp_parent = typ->type->parent;
936 memset(typ->type, 0, sizeof *typ->type);
937 typ->type->parent = tmp_parent;
938
939 /* replace it with the value specified in deviation */
940 /* HACK for unres */
941 typ->type->der = (struct lys_tpdf *)typ;
942 dev->deviate->type = typ->type;
943 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100944 }
945 typ->name = value;
946 typ->line = line;
Pavol Vican73e7c992016-02-24 12:18:05 +0100947 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100948
949error:
950 free(typ);
951 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +0100952}
953
954void *
955yang_read_length(struct lys_module *module, struct yang_type *typ, char *value, int line)
956{
957 struct lys_restr **length;
958
959 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
960 length = &typ->type->info.str.length;
961 typ->type->base = LY_TYPE_STRING;
962 } else if (typ->type->base == LY_TYPE_BINARY) {
963 length = &typ->type->info.binary.length;
964 } else {
965 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected length statement.");
966 goto error;
967 }
968
969 if (*length) {
970 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "length", "type");
971 }
972 *length = calloc(1, sizeof **length);
973 if (!*length) {
974 LOGMEM;
975 goto error;
976 }
977 (*length)->expr = lydict_insert_zc(module->ctx, value);
978 return *length;
979
980error:
981 free(value);
982 return NULL;
983
984}
Pavol Vican1c203db2016-02-24 14:05:23 +0100985
986void *
987yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value, int line)
988{
989 pcre *precomp;
990 int err_offset;
991 const char *err_ptr;
992
993 /* check that the regex is valid */
994 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
995 if (!precomp) {
996 LOGVAL(LYE_INREGEX, line, LY_VLOG_NONE, NULL, value, err_ptr);
997 free(value);
998 return NULL;
999 }
1000 free(precomp);
1001
1002 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1003 typ->type->info.str.pat_count++;
1004 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1005}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001006
1007void *
1008yang_read_range(struct lys_module *module, struct yang_type *typ, char *value, int line)
1009{
1010 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
1011 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1012 goto error;
1013 }
1014 typ->type->base = LY_TYPE_DEC64;
1015 if (typ->type->info.dec64.range) {
1016 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
1017 goto error;
1018 }
1019 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1020 if (!typ->type->info.dec64.range) {
1021 LOGMEM;
1022 goto error;
1023 }
1024 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1025 return typ->type->info.dec64.range;
1026
1027error:
1028 free(value);
1029 return NULL;
1030}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001031
1032int
1033yang_read_fraction(struct yang_type *typ, uint32_t value, int line)
1034{
1035 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1036 typ->type->base = LY_TYPE_DEC64;
1037 } else {
1038 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
1039 goto error;
1040 }
1041 if (typ->type->info.dec64.dig) {
1042 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1043 goto error;
1044 }
1045 /* range check */
1046 if (value < 1 || value > 18) {
1047 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
1048 goto error;
1049 }
1050 typ->type->info.dec64.dig = value;
1051 return EXIT_SUCCESS;
1052
1053error:
1054 return EXIT_FAILURE;
1055}
Pavol Vican79a763d2016-02-25 15:41:27 +01001056
1057void *
1058yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value, int line)
1059{
1060 struct lys_type_enum *enm;
1061 int i;
1062
1063 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1064 enm->name = lydict_insert_zc(module->ctx, value);
1065
1066 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1067 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
1068 LOGVAL(LYE_ENUM_WS, line, LY_VLOG_NONE, NULL, enm->name);
1069 goto error;
1070 }
1071
1072 /* check the name uniqueness */
1073 for (i = 0; i < typ->type->info.enums.count; i++) {
1074 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
1075 LOGVAL(LYE_ENUM_DUPNAME, line, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1076 goto error;
1077 }
1078 }
1079
1080 typ->type->info.enums.count++;
1081 return enm;
1082
1083error:
1084 typ->type->info.enums.count++;
1085 return NULL;
1086}
1087
1088int
1089yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign, int line)
1090{
1091 int i, j;
1092
1093 if (!assign) {
1094 /* assign value automatically */
1095 if (*value > INT32_MAX) {
1096 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1097 goto error;
1098 }
1099 enm->value = *value;
1100 enm->flags |= LYS_AUTOASSIGNED;
1101 (*value)++;
1102 }
1103
1104 /* check that the value is unique */
1105 j = typ->type->info.enums.count-1;
1106 for (i = 0; i < j; i++) {
1107 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
1108 LOGVAL(LYE_ENUM_DUPVAL, line, LY_VLOG_NONE, NULL,
1109 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1110 goto error;
1111 }
1112 }
1113
1114 return EXIT_SUCCESS;
1115
1116error:
1117 return EXIT_FAILURE;
1118}
Pavol Vican9887c682016-02-29 11:32:01 +01001119
1120void *
1121yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value, int line)
1122{
1123 int i;
1124 struct lys_type_bit *bit;
1125
1126 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
1127 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, line, NULL, NULL)) {
1128 LOGVAL(LYE_PATH, 0, LY_VLOG_NONE, NULL);
1129 free(value);
1130 goto error;
1131 }
1132 bit->name = lydict_insert_zc(module->ctx, value);
1133
1134 /* check the name uniqueness */
1135 for (i = 0; i < typ->type->info.bits.count; i++) {
1136 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
1137 LOGVAL(LYE_BITS_DUPNAME, line, LY_VLOG_NONE, NULL, bit->name);
1138 typ->type->info.bits.count++;
1139 goto error;
1140 }
1141 }
1142 typ->type->info.bits.count++;
1143 return bit;
1144
1145error:
1146 return NULL;
1147}
1148
1149int
1150yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign, int line)
1151{
1152 int i,j;
1153 struct lys_type_bit bit_tmp;
1154
1155 if (!assign) {
1156 /* assign value automatically */
1157 if (*value > UINT32_MAX) {
1158 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
1159 goto error;
1160 }
1161 bit->pos = (uint32_t)*value;
1162 bit->flags |= LYS_AUTOASSIGNED;
1163 (*value)++;
1164 }
1165
1166 j = typ->type->info.bits.count - 1;
1167 /* check that the value is unique */
1168 for (i = 0; i < j; i++) {
1169 if (typ->type->info.bits.bit[i].pos == bit->pos) {
1170 LOGVAL(LYE_BITS_DUPVAL, line, LY_VLOG_NONE, NULL, bit->pos, bit->name);
1171 goto error;
1172 }
1173 }
1174
1175 /* keep them ordered by position */
1176 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1177 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001178 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1179 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1180 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001181 j--;
1182 }
1183
1184 return EXIT_SUCCESS;
1185
1186error:
1187 return EXIT_FAILURE;
1188}
Pavol Vican0df02b02016-03-01 10:28:50 +01001189
1190void *
1191yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value, int line)
1192{
1193 struct lys_tpdf *ret;
1194
1195 if (lyp_check_identifier(value, LY_IDENT_TYPE, line, module, parent)) {
1196 free(value);
1197 return NULL;
1198 }
1199 if (!parent) {
1200 ret = &module->tpdf[module->tpdf_size];
1201 ret->type.parent = NULL;
1202 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001203 } else {
1204 switch (parent->nodetype) {
1205 case LYS_GROUPING:
1206 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001207 ((struct lys_node_grp *)parent)->tpdf_size++;
1208 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001209 case LYS_CONTAINER:
1210 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1211 ((struct lys_node_container *)parent)->tpdf_size++;
1212 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001213 case LYS_LIST:
1214 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1215 ((struct lys_node_list *)parent)->tpdf_size++;
1216 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001217 case LYS_RPC:
1218 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1219 ((struct lys_node_rpc *)parent)->tpdf_size++;
1220 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001221 case LYS_INPUT:
1222 case LYS_OUTPUT:
1223 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1224 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1225 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001226 case LYS_NOTIF:
1227 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1228 ((struct lys_node_notif *)parent)->tpdf_size++;
1229 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001230 default:
1231 /* another type of nodetype is error*/
1232 LOGINT;
1233 free(value);
1234 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001235 }
Pavol Vican535d50e2016-03-01 13:05:33 +01001236 ret->type.parent = (struct lys_tpdf *)parent;
Pavol Vican0df02b02016-03-01 10:28:50 +01001237 }
1238
1239 ret->name = lydict_insert_zc(module->ctx, value);
1240 ret->module = module;
1241 return ret;
1242}
Pavol Vican1003ead2016-03-02 12:24:52 +01001243
1244void *
1245yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value, int line)
1246{
1247 struct lys_refine *rfn;
1248
1249 rfn = &uses->refine[uses->refine_size];
1250 uses->refine_size++;
1251 rfn->target_name = transform_schema2json(module, value, line);
1252 free(value);
1253 if (!rfn->target_name) {
1254 return NULL;
1255 }
1256 return rfn;
1257}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001258
1259void *
1260yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value, int line)
1261{
1262 struct lys_node_augment *aug;
1263 uint16_t *size;
1264
1265 if (parent) {
1266 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1267 } else {
1268 aug = &module->augment[module->augment_size];
1269 }
1270 aug->nodetype = LYS_AUGMENT;
1271 aug->target_name = transform_schema2json(module, value, line);
1272 free(value);
1273 if (!aug->target_name) {
1274 return NULL;
1275 }
1276 aug->parent = parent;
1277 aug->module = module;
1278 if (parent) {
1279 ((struct lys_node_uses *)parent)->augment_size++;
1280 } else {
1281 module->augment_size++;
1282 }
1283 return aug;
1284}
Pavol Vican220e5a12016-03-03 14:19:43 +01001285
1286void *
1287yang_read_deviation(struct lys_module *module, char *value, int line)
1288{
1289 struct lys_node *dev_target = NULL;
1290 struct lys_deviation *dev;
1291 struct type_deviation *deviation = NULL;
1292 int i, j, rc;
1293
1294 deviation = calloc(1, sizeof *deviation);
1295 if (!deviation) {
1296 LOGMEM;
1297 goto error;
1298 }
1299
1300 dev = &module->deviation[module->deviation_size];
1301 dev->target_name = transform_schema2json(module, value, line);
1302 free(value);
1303 if (!dev->target_name) {
1304 goto error;
1305 }
1306
1307 /* resolve target node */
1308 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1309 if (rc || !dev_target) {
1310 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
1311 goto error;
1312 }
1313 if (dev_target->module == lys_module(module)) {
1314 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
1315 goto error;
1316 }
1317 /*save pointer to the deviation and deviated target*/
1318 deviation->deviation = dev;
1319 deviation->target = dev_target;
1320
1321 /* mark the target module as deviated */
1322 dev_target->module->deviated = 1;
1323
1324 /* copy our imports to the deviated module (deviations may need them to work) */
1325 for (i = 0; i < module->imp_size; ++i) {
1326 for (j = 0; j < dev_target->module->imp_size; ++j) {
1327 if (module->imp[i].module == dev_target->module->imp[j].module) {
1328 break;
1329 }
1330 }
1331
1332 if (j < dev_target->module->imp_size) {
1333 /* import is already there */
1334 continue;
1335 }
1336
1337 /* copy the import, mark it as external */
1338 ++dev_target->module->imp_size;
1339 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1340 if (!dev_target->module->imp) {
1341 LOGMEM;
1342 goto error;
1343 }
1344 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1345 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1346 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1347 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1348 }
1349
1350 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1351 for (i = 0; i < dev_target->module->imp_size; ++i) {
1352 if (dev_target->module->imp[i].module == module) {
1353 break;
1354 }
1355 }
1356
1357 if (i == dev_target->module->imp_size) {
1358 ++dev_target->module->imp_size;
1359 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1360 if (!dev_target->module->imp) {
1361 LOGMEM;
1362 goto error;
1363 }
1364 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1365 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1366 if (module->rev_size) {
1367 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1368 } else {
1369 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1370 }
1371 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1372 } else {
1373 /* it could have been added by another deviating module that imported this deviating module */
1374 dev_target->module->imp[i].external = 2;
1375 }
1376
1377
1378 return deviation;
1379
1380error:
1381 free(deviation);
1382 lydict_remove(module->ctx, dev->target_name);
1383 return NULL;
1384}
Pavol Vican4c90c642016-03-03 15:06:47 +01001385
1386int
1387yang_read_deviate_unsupported(struct type_deviation *dev, int line)
1388{
1389 int i;
1390
1391 if (dev->deviation->deviate_size) {
1392 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1393 return EXIT_FAILURE;
1394 }
1395 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1396
1397 /* you cannot remove a key leaf */
1398 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1399 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1400 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
1401 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1402 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1403 return EXIT_FAILURE;
1404 }
1405 }
1406 }
1407
1408 /* unlink and store the original node */
1409 dev->deviation->orig_node = dev->target;
1410
1411 dev->deviation->deviate_size = 1;
1412 return EXIT_SUCCESS;
1413}
Pavol Vican85f12022016-03-05 16:30:35 +01001414
1415int
1416yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod, int line)
1417{
1418 struct unres_schema tmp_unres;
1419
1420 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1421 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1422 dev->deviation->deviate_size++;
1423 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
1424 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "not-supported");
1425 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1426 return EXIT_FAILURE;
1427 }
1428
1429 /* store a shallow copy of the original node */
1430 if (!dev->deviation->orig_node) {
1431 memset(&tmp_unres, 0, sizeof tmp_unres);
1432 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1433 /* just to be safe */
1434 if (tmp_unres.count) {
1435 LOGINT;
1436 return EXIT_FAILURE;
1437 }
1438 }
1439
1440 return EXIT_SUCCESS;
1441}
1442
1443int
1444yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1445{
1446 const char **stritem;
1447
1448 if (dev->deviate->units) {
1449 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "units", "deviate");
1450 free(value);
1451 goto error;
1452 }
1453
1454 /* check target node type */
1455 if (dev->target->nodetype == LYS_LEAFLIST) {
1456 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1457 } else if (dev->target->nodetype == LYS_LEAF) {
1458 stritem = &((struct lys_node_leaf *)dev->target)->units;
1459 } else {
1460 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1461 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"units\" property.");
1462 free(value);
1463 goto error;
1464 }
1465
1466 dev->deviate->units = lydict_insert_zc(ctx, value);
1467
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001468 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1469 /* check values */
1470 if (*stritem != dev->deviate->units) {
1471 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1472 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1473 goto error;
1474 }
1475 /* remove current units value of the target */
1476 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001477 } else {
1478 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1479 /* check that there is no current value */
1480 if (*stritem) {
1481 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1482 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1483 goto error;
1484 }
1485 } else { /* replace */
1486 if (!*stritem) {
1487 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1488 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1489 goto error;
1490 }
1491 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001492 /* remove current units value of the target ... */
1493 lydict_remove(ctx, *stritem);
1494
1495 /* ... and replace it with the value specified in deviation */
1496 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1497 }
1498
Pavol Vican85f12022016-03-05 16:30:35 +01001499 return EXIT_SUCCESS;
1500
1501error:
1502 return EXIT_FAILURE;
1503}
1504
1505int
1506yang_read_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_must, int line)
1507{
1508 uint8_t i;
1509
1510 /* check target node type */
1511 switch (dev->target->nodetype) {
1512 case LYS_LEAF:
1513 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1514 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1515 break;
1516 case LYS_CONTAINER:
1517 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1518 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1519 break;
1520 case LYS_LEAFLIST:
1521 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1522 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1523 break;
1524 case LYS_LIST:
1525 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1526 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1527 break;
1528 case LYS_ANYXML:
1529 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1530 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1531 break;
1532 default:
1533 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "must");
1534 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"must\" property.");
1535 goto error;
1536 }
1537
1538 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1539 /* reallocate the must array of the target */
1540 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1541 if (!dev->deviate->must) {
1542 LOGMEM;
1543 goto error;
1544 }
1545 *dev->trg_must = dev->deviate->must;
1546 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1547 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001548 } else {
1549 /* LY_DEVIATE_DEL */
1550 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1551 if (!dev->deviate->must) {
1552 LOGMEM;
1553 goto error;
1554 }
Pavol Vican85f12022016-03-05 16:30:35 +01001555 }
1556
1557 return EXIT_SUCCESS;
1558
1559error:
1560 return EXIT_FAILURE;
1561}
1562
1563int
1564yang_read_deviate_unique(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_uniq, int line)
1565{
1566 int i, j;
1567 struct lys_node_list *list;
1568
1569 /* check target node type */
1570 if (dev->target->nodetype != LYS_LIST) {
1571 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "unique");
1572 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"unique\" property.");
1573 goto error;
1574 }
1575
1576 list = (struct lys_node_list *)dev->target;
1577 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1578 /* reallocate the unique array of the target */
1579 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1580 if (!dev->deviate->unique) {
1581 LOGMEM;
1582 goto error;
1583 }
1584 list->unique = dev->deviate->unique;
1585 dev->deviate->unique = &list->unique[list->unique_size];
1586 dev->deviate->unique_size = c_uniq;
1587 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001588 } else {
1589 /* LY_DEVIATE_DEL */
1590 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1591 if (!dev->deviate->unique) {
1592 LOGMEM;
1593 goto error;
1594 }
Pavol Vican85f12022016-03-05 16:30:35 +01001595 }
1596
1597 return EXIT_SUCCESS;
1598
1599error:
1600 return EXIT_FAILURE;
1601}
1602
1603int
1604yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1605{
1606 int rc;
1607 struct lys_node_choice *choice;
1608 struct lys_node_leaf *leaf;
1609 struct lys_node *node;
1610
1611 if (dev->deviate->dflt) {
1612 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "default", "deviate");
1613 free(value);
1614 goto error;
1615 }
1616
1617 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1618
1619 if (dev->target->nodetype == LYS_CHOICE) {
1620 choice = (struct lys_node_choice *)dev->target;
1621
Pavol Vican85f12022016-03-05 16:30:35 +01001622 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1623 if (rc || !node) {
1624 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1625 goto error;
1626 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001627 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1628 if (!choice->dflt || (choice->dflt != node)) {
1629 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1630 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1631 goto error;
1632 }
1633 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001634 } else {
1635 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1636 /* check that there is no current value */
1637 if (choice->dflt) {
1638 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1639 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1640 goto error;
1641 }
1642 } else { /* replace*/
1643 if (!choice->dflt) {
1644 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1645 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1646 goto error;
1647 }
1648 }
1649
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001650 choice->dflt = node;
1651 if (!choice->dflt) {
1652 /* default branch not found */
1653 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1654 goto error;
1655 }
Pavol Vican85f12022016-03-05 16:30:35 +01001656 }
1657 } else if (dev->target->nodetype == LYS_LEAF) {
1658 leaf = (struct lys_node_leaf *)dev->target;
1659
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001660 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1661 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
1662 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1663 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1664 goto error;
1665 }
1666 /* remove value */
1667 lydict_remove(ctx, leaf->dflt);
1668 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001669 } else {
1670 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1671 /* check that there is no current value */
1672 if (leaf->dflt) {
1673 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1674 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1675 goto error;
1676 }
1677 } else { /* replace*/
1678 if (!leaf->dflt) {
1679 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1680 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1681 goto error;
1682 }
1683 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001684 /* remove value */
1685 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001686
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001687 /* set new value */
1688 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1689 }
Pavol Vican85f12022016-03-05 16:30:35 +01001690 } else {
1691 /* invalid target for default value */
1692 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1693 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"default\" property.");
1694 goto error;
1695 }
1696
1697 return EXIT_SUCCESS;
1698
1699error:
1700 return EXIT_FAILURE;
1701}
1702
1703int
1704yang_read_deviate_config(struct type_deviation *dev, uint8_t value, int line)
1705{
1706 if (dev->deviate->flags & LYS_CONFIG_MASK) {
1707 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "config", "deviate");
1708 goto error;
1709 }
1710
1711 /* for we deviate from RFC 6020 and allow config property even it is/is not
1712 * specified in the target explicitly since config property inherits. So we expect
1713 * that config is specified in every node. But for delete, we check that the value
1714 * is the same as here in deviation
1715 */
1716 dev->deviate->flags |= value;
1717
1718 /* add and replace are the same in this case */
1719 /* remove current config value of the target ... */
1720 dev->target->flags &= ~LYS_CONFIG_MASK;
1721
1722 /* ... and replace it with the value specified in deviation */
1723 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1724
1725 return EXIT_SUCCESS;
1726
1727error:
1728 return EXIT_FAILURE;
1729}
1730
1731int
1732yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value, int line)
1733{
1734 if (dev->deviate->flags & LYS_MAND_MASK) {
1735 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "mandatory", "deviate");
1736 goto error;
1737 }
1738
1739 /* check target node type */
1740 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
1741 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1742 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"mandatory\" property.");
1743 goto error;
1744 }
1745
1746 dev->deviate->flags |= value;
1747
1748 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1749 /* check that there is no current value */
1750 if (dev->target->flags & LYS_MAND_MASK) {
1751 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1752 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1753 goto error;
1754 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001755 } else { /* replace */
1756 if (!(dev->target->flags & LYS_MAND_MASK)) {
1757 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1758 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1759 goto error;
1760 }
Pavol Vican85f12022016-03-05 16:30:35 +01001761 }
1762
Pavol Vican85f12022016-03-05 16:30:35 +01001763 /* remove current mandatory value of the target ... */
1764 dev->target->flags &= ~LYS_MAND_MASK;
1765
1766 /* ... and replace it with the value specified in deviation */
1767 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1768
1769 return EXIT_SUCCESS;
1770
1771error:
1772 return EXIT_FAILURE;
1773}
1774
1775int
1776yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type, int line)
1777{
1778 uint32_t *ui32val;
1779
1780 /* check target node type */
1781 if (dev->target->nodetype == LYS_LEAFLIST) {
1782 if (type) {
1783 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1784 } else {
1785 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1786 }
1787 } else if (dev->target->nodetype == LYS_LIST) {
1788 if (type) {
1789 ui32val = &((struct lys_node_list *)dev->target)->max;
1790 } else {
1791 ui32val = &((struct lys_node_list *)dev->target)->min;
1792 }
1793 } else {
1794 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1795 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
1796 goto error;
1797 }
1798
1799 if (type) {
1800 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001801 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001802 } else {
1803 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001804 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001805 }
1806
1807 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1808 /* check that there is no current value */
1809 if (*ui32val) {
1810 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1811 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1812 goto error;
1813 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001814 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1815 /* unfortunately, there is no way to check reliably that there
1816 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001817 }
1818
1819 /* add (already checked) and replace */
1820 /* set new value specified in deviation */
1821 *ui32val = value;
1822
1823 return EXIT_SUCCESS;
1824
1825error:
1826 return EXIT_FAILURE;
1827}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001828
1829int
1830yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line)
1831{
1832 int i;
1833
1834 /* find must to delete, we are ok with just matching conditions */
1835 for (i = 0; i < *dev->trg_must_size; i++) {
1836 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1837 /* we have a match, free the must structure ... */
1838 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1839 /* ... and maintain the array */
1840 (*dev->trg_must_size)--;
1841 if (i != *dev->trg_must_size) {
1842 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1843 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1844 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1845 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1846 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1847 }
1848 if (!(*dev->trg_must_size)) {
1849 free(*dev->trg_must);
1850 *dev->trg_must = NULL;
1851 } else {
1852 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1853 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1854 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1855 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1856 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1857 }
1858
1859 i = -1; /* set match flag */
1860 break;
1861 }
1862 }
1863 if (i != -1) {
1864 /* no match found */
1865 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1866 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
1867 return EXIT_FAILURE;
1868 }
1869
1870 return EXIT_SUCCESS;
1871}
1872
1873int
1874yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line)
1875{
1876 struct lys_node_list *list;
1877 int i, j;
1878
1879 list = (struct lys_node_list *)dev->target;
1880 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL, line)) {
1881 dev->deviate->unique_size++;
1882 goto error;
1883 }
1884
1885 /* find unique structures to delete */
1886 for (i = 0; i < list->unique_size; i++) {
1887 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1888 continue;
1889 }
1890
1891 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1892 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1893 break;
1894 }
1895 }
1896
1897 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1898 /* we have a match, free the unique structure ... */
1899 for (j = 0; j < list->unique[i].expr_size; j++) {
1900 lydict_remove(module->ctx, list->unique[i].expr[j]);
1901 }
1902 free(list->unique[i].expr);
1903 /* ... and maintain the array */
1904 list->unique_size--;
1905 if (i != list->unique_size) {
1906 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1907 list->unique[i].expr = list->unique[list->unique_size].expr;
1908 }
1909
1910 if (!list->unique_size) {
1911 free(list->unique);
1912 list->unique = NULL;
1913 } else {
1914 list->unique[list->unique_size].expr_size = 0;
1915 list->unique[list->unique_size].expr = NULL;
1916 }
1917
1918 i = -1; /* set match flag */
1919 break;
1920 }
1921 }
1922 dev->deviate->unique_size++;
1923
1924 if (i != -1) {
1925 /* no match found */
1926 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, value, "unique");
1927 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1928 goto error;
1929 }
1930
1931 free(value);
1932 return EXIT_SUCCESS;
1933
1934error:
1935 free(value);
1936 return EXIT_FAILURE;
1937}
Pavol Vicane92421d2016-03-08 10:12:33 +01001938
1939int
1940yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres, int line)
1941{
1942 int i, rc;
1943
1944 if (dev->target->nodetype == LYS_LEAF) {
1945 for(i = 0; i < dev->deviation->deviate_size; ++i) {
1946 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
1947 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
1948 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);
1949 if (rc == -1) {
1950 return EXIT_FAILURE;
1951 } else if (rc == EXIT_FAILURE) {
1952 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->deviation->target_name);
1953 return EXIT_FAILURE;
1954 }
1955 break;
1956 }
1957 }
1958 }
1959 }
1960 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001961}
1962
1963int
1964yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
1965 char *rev, int inc_size, struct unres_schema *unres, int line)
1966{
1967 struct lys_include inc;
1968 struct lys_module *trg;
1969 int i;
Pavol Vican55870412016-03-10 12:36:21 +01001970 const char *str;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001971
Pavol Vican55870412016-03-10 12:36:21 +01001972 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001973 trg = (submodule) ? (struct lys_module *)submodule : module;
1974 inc.submodule = NULL;
1975 inc.external = 0;
1976 memcpy(inc.rev, rev, LY_REV_SIZE);
Pavol Vican55870412016-03-10 12:36:21 +01001977 if (lyp_check_include(module, submodule, str, line, &inc, unres)) {
Pavol Vican9b89dda2016-03-09 15:36:55 +01001978 goto error;
1979 }
1980 memcpy(&trg->inc[inc_size], &inc, sizeof inc);
1981
1982 /* check duplications in include submodules */
1983 for (i = 0; i < inc_size; ++i) {
1984 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size].submodule->name)) {
1985 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.",
1986 trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01001987 trg->inc[inc_size].submodule = NULL;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001988 goto error;
1989 }
1990 }
Pavol Vican55870412016-03-10 12:36:21 +01001991 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001992 return EXIT_SUCCESS;
1993
1994error:
Pavol Vican55870412016-03-10 12:36:21 +01001995 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001996 return EXIT_FAILURE;
1997}
Pavol Vicanf4717e62016-03-16 11:30:01 +01001998
1999int
2000yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value, int line)
2001{
2002 char *prefix;
2003 char *identif;
2004 const char *ns = NULL;
2005 int i;
2006
Pavol Vicanf4717e62016-03-16 11:30:01 +01002007 /* check to the same pointer */
2008 if (data_node != actual) {
2009 return EXIT_SUCCESS;
2010 }
2011
Pavol Vicana302aa62016-03-17 10:45:35 +01002012 prefix = strdup(value);
2013 if (!prefix) {
2014 LOGMEM;
2015 goto error;
2016 }
2017 /* find prefix anf identificator*/
2018 identif = strchr(prefix, ':');
2019 *identif = '\0';
2020 identif++;
2021
Pavol Vicanf4717e62016-03-16 11:30:01 +01002022 for(i = 0; i < module->imp_size; ++i) {
2023 if (!strcmp(module->imp[i].prefix, prefix)) {
2024 ns = module->imp[i].module->ns;
2025 break;
2026 }
2027 }
2028 if (ns && !strcmp(ns, LY_NSNACM)) {
2029 if (!strcmp(identif, "default-deny-write")) {
2030 data_node->nacm |= LYS_NACM_DENYW;
2031 } else if (!strcmp(identif, "default-deny-all")) {
2032 data_node->nacm |= LYS_NACM_DENYA;
2033 } else {
2034 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002035 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002036 }
2037 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002038 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002039 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002040
2041error:
2042 free(prefix);
2043 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002044}
2045
2046void
2047nacm_inherit(struct lys_module *module)
2048{
2049 struct lys_node *next, *elem;
2050
2051 LY_TREE_DFS_BEGIN(module->data, next, elem) {
2052 if (elem->parent) {
2053 switch (elem->nodetype) {
2054 case LYS_GROUPING:
2055 /* extension nacm not inherited*/
2056 break;
2057 case LYS_CHOICE:
2058 case LYS_ANYXML:
2059 case LYS_USES:
2060 if (elem->parent->nodetype != LYS_GROUPING) {
2061 elem->nacm |= elem->parent->nacm;
2062 }
2063 break;
2064 default:
2065 elem->nacm |= elem->parent->nacm;
2066 break;
2067 }
2068 }
2069 LY_TREE_DFS_END(module->data, next, elem);
2070 }
2071}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002072
2073void
2074store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2075{
2076 node->flags |= flags;
2077 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2078 /* get config flag from parent */
2079 if (node->parent) {
2080 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2081 } else {
2082 /* default config is true */
2083 node->flags |= LYS_CONFIG_W;
2084 }
2085 }
2086}