blob: fe4f728aa9fb23dd971279be5ddff77b6aafea13 [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{
111 int count, i;
112
113 /* check for circular import, store it if passed */
114 if (!module->ctx->models.parsing) {
115 count = 0;
116 } else {
117 for (count = 0; module->ctx->models.parsing[count]; ++count) {
118 if (value == module->ctx->models.parsing[count]) {
119 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
120 goto error;
121 }
122 }
123 }
124 ++count;
125 module->ctx->models.parsing =
126 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
127 if (!module->ctx->models.parsing) {
128 LOGMEM;
129 goto error;
130 }
131 module->ctx->models.parsing[count - 1] = value;
132 module->ctx->models.parsing[count] = NULL;
133
134 /* try to load the module */
135 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
136 if (!imp->module) {
137 /* whether to use a user callback is decided in the function */
138 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
139 }
140
141 /* remove the new module name now that its parsing is finished (even if failed) */
142 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
143 LOGINT;
144 }
145 --count;
146 if (count) {
147 module->ctx->models.parsing[count] = NULL;
148 } else {
149 free(module->ctx->models.parsing);
150 module->ctx->models.parsing = NULL;
151 }
152
153 /* check the result */
154 if (!imp->module) {
155 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
156 goto error;
157 }
158
159 module->imp_size++;
160
161 /* check duplicities in imported modules */
162 for (i = 0; i < module->imp_size - 1; i++) {
163 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100164 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Pavol Vican6eb14e82016-02-03 12:27:13 +0100165 goto error;
166 }
167 }
168
169 free(value);
170 return EXIT_SUCCESS;
171
172 error:
173
174 free(value);
175 return EXIT_FAILURE;
176}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100177
178int
179yang_read_description(struct lys_module *module, void *node, char *value, int type, int line)
180{
181 int ret;
182
183 if (!node) {
184 ret = yang_check_string(module, &module->dsc, "description", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100185 } else {
186 switch (type) {
187 case REVISION_KEYWORD:
188 ret = yang_check_string(module, &((struct lys_revision *) node)->dsc, "description", "revision", value, line);
189 break;
Pavol Vicane1354e92016-02-09 14:02:09 +0100190 case FEATURE_KEYWORD:
191 ret = yang_check_string(module, &((struct lys_feature *) node)->dsc, "description", "feature", value, line);
192 break;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100193 case IDENTITY_KEYWORD:
194 ret = yang_check_string(module, &((struct lys_ident *) node)->dsc, "description", "identity", value, line);
195 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100196 case MUST_KEYWORD:
197 ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "must", value, line);
198 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100199 case WHEN_KEYWORD:
200 ret = yang_check_string(module, &((struct lys_when *) node)->dsc, "description", "when" , value, line);
201 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100202 case CONTAINER_KEYWORD:
203 ret = yang_check_string(module, &((struct lys_node_container *) node)->dsc, "description", "container", value, line);
204 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100205 case ANYXML_KEYWORD:
206 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->dsc, "description", "anyxml", value, line);
207 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100208 case CHOICE_KEYWORD:
209 ret = yang_check_string(module, &((struct lys_node_choice *) node)->dsc, "description", "choice", value, line);
210 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100211 case CASE_KEYWORD:
212 ret = yang_check_string(module, &((struct lys_node_case *) node)->dsc, "description", "case", value, line);
213 break;
Pavol Vican12f53c32016-02-11 11:40:00 +0100214 case GROUPING_KEYWORD:
215 ret = yang_check_string(module, &((struct lys_node_grp *) node)->dsc, "description", "grouping", value, line);
216 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100217 case LEAF_KEYWORD:
218 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dsc, "description", "leaf", value, line);
219 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100220 case LEAF_LIST_KEYWORD:
221 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->dsc, "description", "leaflist", value, line);
222 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100223 case LIST_KEYWORD:
224 ret = yang_check_string(module, &((struct lys_node_list *) node)->dsc, "description", "list", value, line);
225 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100226 case LENGTH_KEYWORD:
227 ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "length", value, line);
228 break;
Pavol Vican1c203db2016-02-24 14:05:23 +0100229 case PATTERN_KEYWORD:
230 ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "pattern", value, line);
231 break;
Pavol Vicanaff5c802016-02-24 15:56:45 +0100232 case RANGE_KEYWORD:
233 ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "range", value, line);
234 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100235 case ENUM_KEYWORD:
236 ret = yang_check_string(module, &((struct lys_type_enum *) node)->dsc, "description", "enum", value, line);
237 break;
Pavol Vican9887c682016-02-29 11:32:01 +0100238 case BIT_KEYWORD:
239 ret = yang_check_string(module, &((struct lys_type_bit *) node)->dsc, "description", "bit", value, line);
240 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100241 case TYPEDEF_KEYWORD:
242 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dsc, "description", "typedef", value, line);
243 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100244 case USES_KEYWORD:
245 ret = yang_check_string(module, &((struct lys_node_uses *) node)->dsc, "description", "uses", value, line);
246 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100247 case REFINE_KEYWORD:
248 ret = yang_check_string(module, &((struct lys_refine *) node)->dsc, "description", "refine", value, line);
249 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100250 case AUGMENT_KEYWORD:
251 ret = yang_check_string(module, &((struct lys_node_augment *) node)->dsc, "description", "augment", value, line);
252 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +0100253 case RPC_KEYWORD:
254 ret = yang_check_string(module, &((struct lys_node_rpc *) node)->dsc, "description", "rpc", value, line);
255 break;
Pavol Vican41267fd2016-03-03 10:47:42 +0100256 case NOTIFICATION_KEYWORD:
257 ret = yang_check_string(module, &((struct lys_node_notif *) node)->dsc, "description", "notification", value, line);
258 break;
Pavol Vican220e5a12016-03-03 14:19:43 +0100259 case DEVIATION_KEYWORD:
260 ret = yang_check_string(module, &((struct lys_deviation *) node)->dsc, "description", "deviation", value, line);
261 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100262 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100263 }
264 return ret;
265}
266
267int
268yang_read_reference(struct lys_module *module, void *node, char *value, int type, int line)
269{
270 int ret;
271
272 if (!node) {
273 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100274 } else {
275 switch (type) {
276 case REVISION_KEYWORD:
277 ret = yang_check_string(module, &((struct lys_revision *) node)->ref, "reference", "revision", value, line);
278 break;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100279 case FEATURE_KEYWORD:
280 ret = yang_check_string(module, &((struct lys_feature *) node)->ref, "reference", "feature", value, line);
281 break;
282 case IDENTITY_KEYWORD:
283 ret = yang_check_string(module, &((struct lys_ident *) node)->ref, "reference", "identity", value, line);
284 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100285 case MUST_KEYWORD:
Pavol Vican235dbd42016-02-10 10:34:19 +0100286 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "must", value, line);
287 break;
288 case WHEN_KEYWORD:
289 ret = yang_check_string(module, &((struct lys_when *) node)->ref, "reference", "when", value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100290 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100291 case CONTAINER_KEYWORD:
292 ret = yang_check_string(module, &((struct lys_node_container *) node)->ref, "reference", "container", value, line);
293 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100294 case ANYXML_KEYWORD:
295 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "anyxml", value, line);
296 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100297 case CHOICE_KEYWORD:
298 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "choice", value, line);
299 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100300 case CASE_KEYWORD:
301 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "case", value, line);
302 break;
Pavol Vican12f53c32016-02-11 11:40:00 +0100303 case GROUPING_KEYWORD:
304 ret = yang_check_string(module, &((struct lys_node_grp *) node)->ref, "reference", "grouping", value, line);
305 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100306 case LEAF_KEYWORD:
307 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->ref, "reference", "leaf", value, line);
308 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100309 case LEAF_LIST_KEYWORD:
310 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->ref, "reference", "leaflist", value, line);
311 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100312 case LIST_KEYWORD:
313 ret = yang_check_string(module, &((struct lys_node_list *) node)->ref, "reference", "list", value, line);
314 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100315 case LENGTH_KEYWORD:
316 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "length", value, line);
317 break;
Pavol Vican1c203db2016-02-24 14:05:23 +0100318 case PATTERN_KEYWORD:
319 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "pattern", value, line);
320 break;
Pavol Vicanaff5c802016-02-24 15:56:45 +0100321 case RANGE_KEYWORD:
322 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "range", value, line);
323 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100324 case ENUM_KEYWORD:
325 ret = yang_check_string(module, &((struct lys_type_enum *) node)->ref, "reference", "enum", value, line);
326 break;
Pavol Vican9887c682016-02-29 11:32:01 +0100327 case BIT_KEYWORD:
328 ret = yang_check_string(module, &((struct lys_type_bit *) node)->ref, "reference", "bit", value, line);
329 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100330 case TYPEDEF_KEYWORD:
331 ret = yang_check_string(module, &((struct lys_tpdf *) node)->ref, "reference", "typedef", value, line);
332 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100333 case USES_KEYWORD:
334 ret = yang_check_string(module, &((struct lys_node_uses *) node)->ref, "reference", "uses", value, line);
335 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100336 case REFINE_KEYWORD:
337 ret = yang_check_string(module, &((struct lys_refine *) node)->ref, "reference", "refine", value, line);
338 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100339 case AUGMENT_KEYWORD:
340 ret = yang_check_string(module, &((struct lys_node_augment *) node)->ref, "reference", "augment", value, line);
341 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +0100342 case RPC_KEYWORD:
343 ret = yang_check_string(module, &((struct lys_node_rpc *) node)->ref, "reference", "rpc", value, line);
344 break;
Pavol Vican41267fd2016-03-03 10:47:42 +0100345 case NOTIFICATION_KEYWORD:
346 ret = yang_check_string(module, &((struct lys_node_notif *) node)->ref, "reference", "notification", value, line);
347 break;
Pavol Vican220e5a12016-03-03 14:19:43 +0100348 case DEVIATION_KEYWORD:
349 ret = yang_check_string(module, &((struct lys_deviation *) node)->ref, "reference", "deviation", value, line);
350 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100351 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100352 }
353 return ret;
354}
Pavol Vicanbedff692016-02-03 14:29:17 +0100355
356void *
357yang_read_revision(struct lys_module *module, char *value)
358{
359 struct lys_revision *retval;
360
Pavol Vican1eeb1992016-02-09 11:10:45 +0100361 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100362
363 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100364 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100365 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
366 memcpy(module->rev[0].date, value, LY_REV_SIZE);
367 retval->dsc = module->rev[0].dsc;
368 retval->ref = module->rev[0].ref;
369 retval = module->rev;
370 retval->dsc = NULL;
371 retval->ref = NULL;
372 } else {
373 memcpy(retval->date, value, LY_REV_SIZE);
374 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100375 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100376 free(value);
377 return retval;
378}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100379
380int
Pavol Vicana1827962016-02-29 15:39:42 +0100381yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100382{
383 if (!*size % LY_ARRAY_SIZE) {
384 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
385 LOGMEM;
386 return EXIT_FAILURE;
387 } else {
388 memset(*node+*size,0,LY_ARRAY_SIZE*sizeof **node);
389 }
390 }
391 (*size)++;
392 return EXIT_SUCCESS;
393}
Pavol Vicane1354e92016-02-09 14:02:09 +0100394
395void *
396yang_read_feature(struct lys_module *module, char *value, int line)
397{
398 struct lys_feature *retval;
399
400 /* check uniqueness of feature's names */
401 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
402 goto error;
403 }
404 retval = &module->features[module->features_size];
405 retval->name = lydict_insert_zc(module->ctx, value);
406 retval->module = module;
407 module->features_size++;
408 return retval;
409
410error:
411 free(value);
412 return NULL;
413}
414
415int
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100416yang_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 +0100417{
418 const char *exp;
419 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100420 struct lys_feature *f;
421 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100422
423 if (!(exp = transform_schema2json(module, value, line))) {
424 free(value);
425 return EXIT_FAILURE;
426 }
427 free(value);
428
429 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100430 if (type == FEATURE_KEYWORD) {
431 f = (struct lys_feature *) ptr;
432 f->features[f->features_size] = f;
433 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
434 f->features_size++;
435 } else {
436 n = (struct lys_node *) ptr;
437 n->features[n->features_size] = (struct lys_feature *) n;
438 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
439 n->features_size++;
440 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100441
442 lydict_remove(module->ctx, exp);
443 if (ret == -1) {
444
445 return EXIT_FAILURE;
446 }
447 return EXIT_SUCCESS;
448}
449
450static int
451yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
452{
453 if (*flags & mask) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100454 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100455 return EXIT_FAILURE;
456 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100457 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100458 return EXIT_SUCCESS;
459 }
460}
461
462int
463yang_read_status(void *node, int value, int type, int line)
464{
465 int retval;
466
467 switch (type) {
468 case FEATURE_KEYWORD:
469 retval = yang_check_flags(&((struct lys_feature *) node)->flags, LYS_STATUS_MASK, "status", "feature", value, line);
470 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100471 case IDENTITY_KEYWORD:
Pavol Vicanbbdef532016-02-09 14:52:12 +0100472 retval = yang_check_flags(&((struct lys_ident *) node)->flags, LYS_STATUS_MASK, "status", "identity", value, line);
473 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100474 case CONTAINER_KEYWORD:
475 retval = yang_check_flags(&((struct lys_node_container *) node)->flags, LYS_STATUS_MASK, "status", "container", value, line);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100476 break;
477 case ANYXML_KEYWORD:
478 retval = yang_check_flags(&((struct lys_node_anyxml *) node)->flags, LYS_STATUS_MASK, "status", "anyxml", value, line);
479 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100480 case CHOICE_KEYWORD:
481 retval = yang_check_flags(&((struct lys_node_anyxml *) node)->flags, LYS_STATUS_MASK, "status", "choice", value, line);
482 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100483 case CASE_KEYWORD:
484 retval = yang_check_flags(&((struct lys_node_case *) node)->flags, LYS_STATUS_MASK, "status", "case", value, line);
485 break;
Pavol Vican12f53c32016-02-11 11:40:00 +0100486 case GROUPING_KEYWORD:
487 retval = yang_check_flags(&((struct lys_node_grp *) node)->flags, LYS_STATUS_MASK, "status", "grouping", value, line);
488 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100489 case LEAF_KEYWORD:
490 retval = yang_check_flags(&((struct lys_node_leaf *) node)->flags, LYS_STATUS_MASK, "status", "leaf", value, line);
491 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100492 case LEAF_LIST_KEYWORD:
493 retval = yang_check_flags(&((struct lys_node_leaflist *) node)->flags, LYS_STATUS_MASK, "status", "leaflist", value, line);
494 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100495 case LIST_KEYWORD:
496 retval = yang_check_flags(&((struct lys_node_list *) node)->flags, LYS_STATUS_MASK, "status", "list", value, line);
497 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100498 case ENUM_KEYWORD:
499 retval = yang_check_flags(&((struct lys_type_enum *) node)->flags, LYS_STATUS_MASK, "status", "enum", value, line);
Pavol Vican9887c682016-02-29 11:32:01 +0100500 break;
501 case BIT_KEYWORD:
502 retval = yang_check_flags(&((struct lys_type_bit *) node)->flags, LYS_STATUS_MASK, "status", "bit", value, line);
503 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100504 case TYPEDEF_KEYWORD:
505 retval = yang_check_flags(&((struct lys_tpdf *) node)->flags, LYS_STATUS_MASK, "status", "typedef", value, line);
506 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100507 case USES_KEYWORD:
508 retval = yang_check_flags(&((struct lys_node_uses *) node)->flags, LYS_STATUS_MASK, "status", "uses", value, line);
509 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100510 case AUGMENT_KEYWORD:
511 retval = yang_check_flags(&((struct lys_node_augment *) node)->flags, LYS_STATUS_MASK, "status", "augment", value, line);
512 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +0100513 case RPC_KEYWORD:
514 retval = yang_check_flags(&((struct lys_node_rpc *) node)->flags, LYS_STATUS_MASK, "status", "rpc", value, line);
515 break;
Pavol Vican41267fd2016-03-03 10:47:42 +0100516 case NOTIFICATION_KEYWORD:
517 retval = yang_check_flags(&((struct lys_node_notif *) node)->flags, LYS_STATUS_MASK, "status", "notification", value, line);
518 break;
Pavol Vicane1354e92016-02-09 14:02:09 +0100519 }
520 return retval;
521}
Pavol Vicanbbdef532016-02-09 14:52:12 +0100522
523void *
524yang_read_identity(struct lys_module *module, char *value)
525{
526 struct lys_ident *ret;
527
528 ret = &module->ident[module->ident_size];
529 ret->name = lydict_insert_zc(module->ctx, value);
530 ret->module = module;
531 module->ident_size++;
532 return ret;
533}
534
535int
536yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
537{
538 const char *exp;
539
540 if (ident->base) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100541 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "base", "identity");
Pavol Vicanbbdef532016-02-09 14:52:12 +0100542 return EXIT_FAILURE;
543 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100544 exp = transform_schema2json(module, value, line);
545 free(value);
546 if (!exp) {
547 return EXIT_FAILURE;
548 }
549 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
550 lydict_remove(module->ctx, exp);
551 return EXIT_FAILURE;
552 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100553
554 /* hack - store some address due to detection of unresolved base*/
555 if (!ident->base) {
556 ident->base = (void *)1;
557 }
558
Pavol Vicanbbdef532016-02-09 14:52:12 +0100559 lydict_remove(module->ctx, exp);
560 return EXIT_SUCCESS;
561}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100562
563void *
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100564yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
565{
566 struct lys_restr *retval;
567
568 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100569 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100570 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100571 break;
572 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100573 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
574 break;
575 case LEAF_KEYWORD:
576 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100577 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100578 case LEAF_LIST_KEYWORD:
579 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
580 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100581 case LIST_KEYWORD:
582 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
583 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100584 case REFINE_KEYWORD:
585 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
586 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100587 case ADD_KEYWORD:
588 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
589 memset(retval, 0, sizeof *retval);
590 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100591 case DELETE_KEYWORD:
592 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
593 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100594 }
595 retval->expr = transform_schema2json(module, value, line);
596 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
597 goto error;
598 }
599 free(value);
600 return retval;
601
602error:
603 free(value);
604 return NULL;
605}
606
607int
608yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, int type, int message, int line)
609{
610 int ret;
611 char *exp;
612
613 switch (type) {
614 case MUST_KEYWORD:
615 exp = "must";
616 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100617 case LENGTH_KEYWORD:
618 exp = "length";
619 break;
Pavol Vican1c203db2016-02-24 14:05:23 +0100620 case PATTERN_KEYWORD:
621 exp = "pattern";
622 break;
Pavol Vicanaff5c802016-02-24 15:56:45 +0100623 case RANGE_KEYWORD:
624 exp = "range";
625 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100626 }
627 if (message==ERROR_APP_TAG_KEYWORD) {
628 ret = yang_check_string(module, &save->eapptag, "error_app_tag", exp, value, line);
629 } else {
630 ret = yang_check_string(module, &save->emsg, "error_app_tag", exp, value, line);
631 }
632 return ret;
633}
Pavol Vicanb5687112016-02-09 22:35:59 +0100634
635int
636yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
637{
638 if (cont->presence) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100639 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100640 free(value);
641 return EXIT_FAILURE;
642 } else {
643 cont->presence = lydict_insert_zc(module->ctx, value);
644 return EXIT_SUCCESS;
645 }
646}
647
648int
649yang_read_config(void *node, int value, int type, int line)
650{
651 int ret;
652
653 switch (type) {
654 case CONTAINER_KEYWORD:
655 ret = yang_check_flags(&((struct lys_node_container *)node)->flags, LYS_CONFIG_MASK, "config", "container", value, line);
656 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100657 case ANYXML_KEYWORD:
658 ret = yang_check_flags(&((struct lys_node_anyxml *)node)->flags, LYS_CONFIG_MASK, "config", "anyxml", value, line);
659 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100660 case CHOICE_KEYWORD:
661 ret = yang_check_flags(&((struct lys_node_choice *)node)->flags, LYS_CONFIG_MASK, "config", "choice", value, line);
662 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100663 case LEAF_KEYWORD:
664 ret = yang_check_flags(&((struct lys_node_leaf *)node)->flags, LYS_CONFIG_MASK, "config", "leaf", value, line);
665 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100666 case LEAF_LIST_KEYWORD:
Pavol Vican5de33492016-02-22 14:03:24 +0100667 ret = yang_check_flags(&((struct lys_node_leaflist *)node)->flags, LYS_CONFIG_MASK, "config", "leaflist", value, line);
668 break;
669 case LIST_KEYWORD:
670 ret = yang_check_flags(&((struct lys_node_list *)node)->flags, LYS_CONFIG_MASK, "config", "list", value, line);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100671 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100672 case REFINE_KEYWORD:
673 ret = yang_check_flags(&((struct lys_refine *)node)->flags, LYS_CONFIG_MASK, "config", "refine", value, line);
674 break;
Pavol Vicanb5687112016-02-09 22:35:59 +0100675 }
676 return ret;
677}
Pavol Vican235dbd42016-02-10 10:34:19 +0100678
679void *
680yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
681{
682 struct lys_when *retval;
683
684 retval = calloc(1, sizeof *retval);
685 if (!retval) {
686 LOGMEM;
687 free(value);
688 return NULL;
689 }
690 retval->cond = transform_schema2json(module, value, line);
691 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
692 goto error;
693 }
694 switch (type) {
695 case CONTAINER_KEYWORD:
696 if (((struct lys_node_container *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100697 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100698 goto error;
699 }
700 ((struct lys_node_container *)node)->when = retval;
701 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100702 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100703 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100704 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100705 goto error;
706 }
707 ((struct lys_node_anyxml *)node)->when = retval;
708 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100709 case CHOICE_KEYWORD:
710 if (((struct lys_node_choice *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100711 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100712 goto error;
713 }
714 ((struct lys_node_choice *)node)->when = retval;
715 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100716 case CASE_KEYWORD:
717 if (((struct lys_node_case *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100718 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100719 goto error;
720 }
721 ((struct lys_node_case *)node)->when = retval;
722 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100723 case LEAF_KEYWORD:
724 if (((struct lys_node_leaf *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100725 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100726 goto error;
727 }
728 ((struct lys_node_leaf *)node)->when = retval;
729 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100730 case LEAF_LIST_KEYWORD:
731 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100732 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100733 goto error;
734 }
735 ((struct lys_node_leaflist *)node)->when = retval;
736 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100737 case LIST_KEYWORD:
738 if (((struct lys_node_list *)node)->when) {
739 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "list");
740 goto error;
741 }
742 ((struct lys_node_list *)node)->when = retval;
743 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100744 case USES_KEYWORD:
745 if (((struct lys_node_uses *)node)->when) {
746 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "uses");
747 goto error;
748 }
749 ((struct lys_node_uses *)node)->when = retval;
750 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100751 case AUGMENT_KEYWORD:
752 if (((struct lys_node_augment *)node)->when) {
753 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "augment");
754 goto error;
755 }
756 ((struct lys_node_augment *)node)->when = retval;
757 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100758 }
759 free(value);
760 return retval;
761
762error:
763 free(value);
764 lys_when_free(module->ctx, retval);
765 return NULL;
766}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100767
768void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100769yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100770{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100771 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100772
Pavol Vican7cadfe72016-02-11 12:33:34 +0100773 node = calloc(1, sizeof_struct);
774 if (!node) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100775 LOGMEM;
776 return NULL;
777 }
Pavol Vican531a9132016-03-03 10:10:09 +0100778 if (value) {
779 node->name = lydict_insert_zc(module->ctx, value);
780 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100781 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100782 node->nodetype = nodetype;
783 node->prev = node;
784
785 /* insert the node into the schema tree */
786 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100787 if (value) {
788 lydict_remove(module->ctx, node->name);
789 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100790 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100791 return NULL;
792 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100793 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100794}
795
796int
797yang_read_mandatory(void *node, int value, int type, int line)
798{
799 int ret;
800
801 switch (type) {
802 case ANYXML_KEYWORD:
803 ret = yang_check_flags(&((struct lys_node_anyxml *)node)->flags, LYS_MAND_MASK, "mandatory", "anyxml", value, line);
804 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100805 case CHOICE_KEYWORD:
806 ret = yang_check_flags(&((struct lys_node_choice *)node)->flags, LYS_MAND_MASK, "mandatory", "choice", value, line);
807 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100808 case LEAF_KEYWORD:
809 ret = yang_check_flags(&((struct lys_node_leaf *)node)->flags, LYS_MAND_MASK, "mandatory", "leaf", value, line);
810 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100811 case REFINE_KEYWORD:
812 ret = yang_check_flags(&((struct lys_refine *)node)->flags, LYS_MAND_MASK, "mandatory", "refine", value, line);
813 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100814 }
815 return ret;
816}
817
818int
819yang_read_default(struct lys_module *module, void *node, char *value, int type, int line)
820{
821 int ret;
822
823 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100824 case LEAF_KEYWORD:
825 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, line);
826 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100827 case TYPEDEF_KEYWORD:
828 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, line);
829 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100830 }
831 return ret;
832}
833
834int
835yang_read_units(struct lys_module *module, void *node, char *value, int type, int line)
836{
837 int ret;
838
839 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100840 case LEAF_KEYWORD:
841 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, line);
842 break;
843 case LEAF_LIST_KEYWORD:
844 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, line);
845 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100846 case TYPEDEF_KEYWORD:
847 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, line);
848 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100849 }
850 return ret;
851}
Pavol Vican5de33492016-02-22 14:03:24 +0100852
853int
854yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres, int line)
855{
856 char *exp, *value;
857
858 exp = value = (char *) list->keys;
859 while ((value = strpbrk(value, " \t\n"))) {
860 list->keys_size++;
861 while (isspace(*value)) {
862 value++;
863 }
864 }
865 list->keys_size++;
866 list->keys = calloc(list->keys_size, sizeof *list->keys);
867 if (!list->keys) {
868 LOGMEM;
869 goto error;
870 }
871 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp, line) == -1) {
872 goto error;
873 }
874 free(exp);
875 return EXIT_SUCCESS;
876
877error:
878 free(exp);
879 return EXIT_FAILURE;
880}
881
882int
Pavol Vican85f12022016-03-05 16:30:35 +0100883yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres, int line)
884{
885 int i, j;
886 char *vaux;
887
888 /* count the number of unique leafs in the value */
889 vaux = value;
890 while ((vaux = strpbrk(vaux, " \t\n"))) {
891 unique->expr_size++;
892 while (isspace(*vaux)) {
893 vaux++;
894 }
895 }
896 unique->expr_size++;
897 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
898 if (!unique->expr) {
899 LOGMEM;
900 goto error;
901 }
902
903 for (i = 0; i < unique->expr_size; i++) {
904 vaux = strpbrk(value, " \t\n");
905 if (!vaux) {
906 /* the last token, lydict_insert() will count its size on its own */
907 vaux = value;
908 }
909
910 /* store token into unique structure */
911 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
912
913 /* check that the expression does not repeat */
914 for (j = 0; j < i; j++) {
915 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
916 LOGVAL(LYE_INARG, line, LY_VLOG_LYS, list, unique->expr[i], "unique");
917 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
918 goto error;
919 }
920 }
921 /* try to resolve leaf */
922 if (unres) {
923 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i], line);
924 } else {
925 if (resolve_unique((struct lys_node *)list, unique->expr[i], 0, line)) {
926 goto error;
927 }
928 }
929
930 /* move to next token */
931 value = vaux;
932 while(isspace(*value)) {
933 value++;
934 }
935 }
936
937 return EXIT_SUCCESS;
938
939error:
940 return EXIT_FAILURE;
941}
942
943int
Pavol Vican5de33492016-02-22 14:03:24 +0100944yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
945{
946 uint8_t k;
Pavol Vican5de33492016-02-22 14:03:24 +0100947 struct type_ident *ident;
948
949 for(k=0; k<list->unique_size; k++) {
Pavol Vican5de33492016-02-22 14:03:24 +0100950 ident = (struct type_ident *)list->unique[k].expr;
Pavol Vican85f12022016-03-05 16:30:35 +0100951 if (yang_fill_unique(module, list, &list->unique[k], ident->s, unres, ident->line)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100952 goto error;
953 }
Pavol Vican5de33492016-02-22 14:03:24 +0100954 free(ident);
955 }
956 return EXIT_SUCCESS;
957
958error:
959 free(ident);
960 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100961}
962
Pavol Vican1ff0e222016-02-26 12:27:01 +0100963static int
964yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres, int line)
965{
966 const char *value, *tmp;
967 int rc, ret = EXIT_FAILURE;
968
969 value = tmp = type->info.lref.path;
970 /* store in the JSON format */
971 value = transform_schema2json(module, value, line);
972 if (!value) {
973 goto end;
974 }
975 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, line);
976 lydict_remove(module->ctx, value);
977
978 if (rc == -1) {
979 goto end;
980 }
981
982 ret = EXIT_SUCCESS;
983
984end:
985 lydict_remove(module->ctx, tmp);
986 return ret;
987}
988
Pavol Vican73e7c992016-02-24 12:18:05 +0100989int
990yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
991{
992 int i, rc;
993 int ret = -1;
994 const char *name, *value;
995 LY_DATA_TYPE base;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100996 struct yang_type *typ_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100997
Pavol Vican0df02b02016-03-01 10:28:50 +0100998 base = typ->type->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100999 value = transform_schema2json(module, typ->name, typ->line);
1000 if (!value) {
1001 goto error;
1002 }
1003
1004 i = parse_identifier(value);
1005 if (i < 1) {
1006 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
1007 lydict_remove(module->ctx, value);
1008 goto error;
1009 }
1010 /* module name*/
1011 name = value;
1012 if (value[i]) {
1013 typ->type->module_name = lydict_insert(module->ctx, value, i);
1014 name += i;
1015 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
1016 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, name[0], name);
1017 lydict_remove(module->ctx, value);
1018 goto error;
1019 }
1020 ++name;
1021 }
1022
1023 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
1024 lydict_remove(module->ctx, value);
1025 if (rc == -1) {
1026 LOGVAL(LYE_INMOD, typ->line, LY_VLOG_NONE, NULL, typ->type->module_name);
1027 goto error;
1028
1029 /* the type could not be resolved or it was resolved to an unresolved typedef*/
1030 } else if (rc == EXIT_FAILURE) {
1031 ret = EXIT_FAILURE;
1032 goto error;
1033 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001034 typ->type->base = typ->type->der->type.base;
1035 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +01001036 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +01001037 }
1038 switch (base) {
1039 case LY_TYPE_STRING:
1040 if (typ->type->base == LY_TYPE_BINARY) {
1041 if (typ->type->info.str.pat_count) {
1042 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001043 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +01001044 goto error;
1045 }
1046 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001047 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 +01001048 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
1049 goto error;
1050 }
1051 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +01001052 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 +01001053 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
1054 goto error;
1055 }
Pavol Vicanaff5c802016-02-24 15:56:45 +01001056 } else {
1057 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1058 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001059 }
Pavol Vicanaff5c802016-02-24 15:56:45 +01001060 break;
1061 case LY_TYPE_DEC64:
1062 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +01001063 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 +01001064 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
1065 goto error;
1066 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001067 /* mandatory sub-statement(s) check */
1068 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
1069 /* decimal64 type directly derived from built-in type requires fraction-digits */
1070 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1071 goto error;
1072 }
1073 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
1074 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
1075 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits");
1076 goto error;
1077 }
Pavol Vicanaff5c802016-02-24 15:56:45 +01001078 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
1079 if (typ->type->info.dec64.dig) {
1080 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
1081 typ->type->base = base;
1082 goto error;
1083 }
1084 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001085 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 +01001086 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
1087 goto error;
1088 }
1089 } else {
1090 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1091 goto error;
1092 }
1093 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001094 case LY_TYPE_ENUM:
1095 if (typ->type->base != LY_TYPE_ENUM) {
1096 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1097 goto error;
1098 }
1099 if (!typ->type->der->type.der && !typ->type->info.enums.count) {
1100 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1101 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "enum", "type");
1102 goto error;
1103 }
1104 if (typ->type->der->type.der && typ->type->info.enums.count) {
1105 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
1106 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "enum");
1107 goto error;
1108 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001109 break;
1110 case LY_TYPE_LEAFREF:
1111 if (typ->type->base == LY_TYPE_IDENT && typ->flags & LYS_TYPE_BASE) {
1112 if (yang_read_identyref(module, typ->type, unres, typ->line)) {
1113 goto error;
1114 }
Pavol Vican191613a2016-02-26 16:21:32 +01001115 } else if (typ->type->base == LY_TYPE_LEAFREF) {
1116 if (typ->type->info.lref.path && !typ->type->der->type.der) {
1117 value = typ->type->info.lref.path;
1118 /* store in the JSON format */
1119 typ->type->info.lref.path = transform_schema2json(module, value, typ->line);
1120 lydict_remove(module->ctx, value);
1121 if (!typ->type->info.lref.path) {
1122 goto error;
1123 }
1124 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent, typ->line) == -1) {
1125 goto error;
1126 }
1127 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
1128 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "path", "type");
1129 goto error;
1130 } else {
1131 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "path");
1132 goto error;
1133 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001134 } else {
1135 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1136 goto error;
1137 }
1138 break;
1139 case LY_TYPE_IDENT:
1140 if (typ->type->der->type.der) {
1141 /* this is just a derived type with no base specified/required */
1142 break;
1143 } else {
1144 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "base", "type");
1145 goto error;
1146 }
1147 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001148 case LY_TYPE_UNION:
1149 if (typ->type->base != LY_TYPE_UNION) {
1150 typ->type->base = LY_TYPE_UNION;
1151 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1152 goto error;
1153 }
1154 if (!typ->type->info.uni.types) {
1155 if (typ->type->der->type.der) {
1156 /* this is just a derived type with no additional type specified/required */
1157 break;
1158 }
1159 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "type", "(union) type");
1160 goto error;
1161 }
1162 for (i = 0; i < typ->type->info.uni.count; i++) {
1163 typ_tmp = (struct yang_type *)typ->type->info.uni.types[i].der;
1164 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent, typ_tmp->line)) {
1165 goto error;
1166 }
1167 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
1168 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "empty", typ->name);
1169 goto error;
1170 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
1171 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "leafref", typ->name);
1172 goto error;
1173 }
1174 }
1175 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001176
1177 default:
1178 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1179 if (typ->type->base != base) {
1180 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1181 goto error;
1182 }
1183 } else {
1184 LOGINT;
1185 goto error;
1186 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001187 }
1188 return EXIT_SUCCESS;
1189
1190error:
Pavol Vicana1827962016-02-29 15:39:42 +01001191 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +01001192 if (typ->type->module_name) {
1193 lydict_remove(module->ctx, typ->type->module_name);
1194 typ->type->module_name = NULL;
1195 }
1196 return ret;
1197}
1198
1199void *
Pavol Vican4766aca2016-03-07 12:42:36 +01001200yang_read_type(struct lys_module *module, void *parent, char *value, int type, int line)
Pavol Vican73e7c992016-02-24 12:18:05 +01001201{
1202 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001203 struct type_deviation *dev;
1204 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001205
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001206 typ = calloc(1, sizeof *typ);
1207 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001208 LOGMEM;
1209 return NULL;
1210 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001211
1212 typ->flags = LY_YANG_STRUCTURE_FLAG;
1213 switch (type) {
1214 case LEAF_KEYWORD:
1215 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1216 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1217 typ->type = &((struct lys_node_leaf *)parent)->type;
1218 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001219 case LEAF_LIST_KEYWORD:
1220 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1221 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1222 typ->type = &((struct lys_node_leaflist *)parent)->type;
1223 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001224 case UNION_KEYWORD:
1225 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1226 typ->type = (struct lys_type *)parent;
1227 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001228 case TYPEDEF_KEYWORD:
1229 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1230 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001231 break;
1232 case REPLACE_KEYWORD:
1233 /* deviation replace type*/
1234 dev = (struct type_deviation *)parent;
1235 if (dev->deviate->type) {
1236 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "type", "deviation");
1237 goto error;
1238 }
1239 /* check target node type */
1240 if (dev->target->nodetype == LYS_LEAF) {
1241 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1242 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1243 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1244 } else {
1245 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "type");
1246 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"type\" property.");
1247 goto error;
1248 }
1249
1250 /* remove type and initialize it */
1251 lys_type_free(module->ctx, typ->type);
1252 tmp_parent = typ->type->parent;
1253 memset(typ->type, 0, sizeof *typ->type);
1254 typ->type->parent = tmp_parent;
1255
1256 /* replace it with the value specified in deviation */
1257 /* HACK for unres */
1258 typ->type->der = (struct lys_tpdf *)typ;
1259 dev->deviate->type = typ->type;
1260 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001261 }
1262 typ->name = value;
1263 typ->line = line;
Pavol Vican73e7c992016-02-24 12:18:05 +01001264 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001265
1266error:
1267 free(typ);
1268 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001269}
1270
1271void *
1272yang_read_length(struct lys_module *module, struct yang_type *typ, char *value, int line)
1273{
1274 struct lys_restr **length;
1275
1276 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
1277 length = &typ->type->info.str.length;
1278 typ->type->base = LY_TYPE_STRING;
1279 } else if (typ->type->base == LY_TYPE_BINARY) {
1280 length = &typ->type->info.binary.length;
1281 } else {
1282 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected length statement.");
1283 goto error;
1284 }
1285
1286 if (*length) {
1287 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "length", "type");
1288 }
1289 *length = calloc(1, sizeof **length);
1290 if (!*length) {
1291 LOGMEM;
1292 goto error;
1293 }
1294 (*length)->expr = lydict_insert_zc(module->ctx, value);
1295 return *length;
1296
1297error:
1298 free(value);
1299 return NULL;
1300
1301}
Pavol Vican1c203db2016-02-24 14:05:23 +01001302
1303void *
1304yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value, int line)
1305{
1306 pcre *precomp;
1307 int err_offset;
1308 const char *err_ptr;
1309
1310 /* check that the regex is valid */
1311 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1312 if (!precomp) {
1313 LOGVAL(LYE_INREGEX, line, LY_VLOG_NONE, NULL, value, err_ptr);
1314 free(value);
1315 return NULL;
1316 }
1317 free(precomp);
1318
1319 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1320 typ->type->info.str.pat_count++;
1321 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1322}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001323
1324void *
1325yang_read_range(struct lys_module *module, struct yang_type *typ, char *value, int line)
1326{
1327 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
1328 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1329 goto error;
1330 }
1331 typ->type->base = LY_TYPE_DEC64;
1332 if (typ->type->info.dec64.range) {
1333 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
1334 goto error;
1335 }
1336 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1337 if (!typ->type->info.dec64.range) {
1338 LOGMEM;
1339 goto error;
1340 }
1341 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1342 return typ->type->info.dec64.range;
1343
1344error:
1345 free(value);
1346 return NULL;
1347}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001348
1349int
1350yang_read_fraction(struct yang_type *typ, uint32_t value, int line)
1351{
1352 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1353 typ->type->base = LY_TYPE_DEC64;
1354 } else {
1355 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
1356 goto error;
1357 }
1358 if (typ->type->info.dec64.dig) {
1359 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1360 goto error;
1361 }
1362 /* range check */
1363 if (value < 1 || value > 18) {
1364 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
1365 goto error;
1366 }
1367 typ->type->info.dec64.dig = value;
1368 return EXIT_SUCCESS;
1369
1370error:
1371 return EXIT_FAILURE;
1372}
Pavol Vican79a763d2016-02-25 15:41:27 +01001373
1374void *
1375yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value, int line)
1376{
1377 struct lys_type_enum *enm;
1378 int i;
1379
1380 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1381 enm->name = lydict_insert_zc(module->ctx, value);
1382
1383 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1384 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
1385 LOGVAL(LYE_ENUM_WS, line, LY_VLOG_NONE, NULL, enm->name);
1386 goto error;
1387 }
1388
1389 /* check the name uniqueness */
1390 for (i = 0; i < typ->type->info.enums.count; i++) {
1391 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
1392 LOGVAL(LYE_ENUM_DUPNAME, line, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1393 goto error;
1394 }
1395 }
1396
1397 typ->type->info.enums.count++;
1398 return enm;
1399
1400error:
1401 typ->type->info.enums.count++;
1402 return NULL;
1403}
1404
1405int
1406yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign, int line)
1407{
1408 int i, j;
1409
1410 if (!assign) {
1411 /* assign value automatically */
1412 if (*value > INT32_MAX) {
1413 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1414 goto error;
1415 }
1416 enm->value = *value;
1417 enm->flags |= LYS_AUTOASSIGNED;
1418 (*value)++;
1419 }
1420
1421 /* check that the value is unique */
1422 j = typ->type->info.enums.count-1;
1423 for (i = 0; i < j; i++) {
1424 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
1425 LOGVAL(LYE_ENUM_DUPVAL, line, LY_VLOG_NONE, NULL,
1426 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1427 goto error;
1428 }
1429 }
1430
1431 return EXIT_SUCCESS;
1432
1433error:
1434 return EXIT_FAILURE;
1435}
Pavol Vican9887c682016-02-29 11:32:01 +01001436
1437void *
1438yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value, int line)
1439{
1440 int i;
1441 struct lys_type_bit *bit;
1442
1443 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
1444 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, line, NULL, NULL)) {
1445 LOGVAL(LYE_PATH, 0, LY_VLOG_NONE, NULL);
1446 free(value);
1447 goto error;
1448 }
1449 bit->name = lydict_insert_zc(module->ctx, value);
1450
1451 /* check the name uniqueness */
1452 for (i = 0; i < typ->type->info.bits.count; i++) {
1453 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
1454 LOGVAL(LYE_BITS_DUPNAME, line, LY_VLOG_NONE, NULL, bit->name);
1455 typ->type->info.bits.count++;
1456 goto error;
1457 }
1458 }
1459 typ->type->info.bits.count++;
1460 return bit;
1461
1462error:
1463 return NULL;
1464}
1465
1466int
1467yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign, int line)
1468{
1469 int i,j;
1470 struct lys_type_bit bit_tmp;
1471
1472 if (!assign) {
1473 /* assign value automatically */
1474 if (*value > UINT32_MAX) {
1475 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
1476 goto error;
1477 }
1478 bit->pos = (uint32_t)*value;
1479 bit->flags |= LYS_AUTOASSIGNED;
1480 (*value)++;
1481 }
1482
1483 j = typ->type->info.bits.count - 1;
1484 /* check that the value is unique */
1485 for (i = 0; i < j; i++) {
1486 if (typ->type->info.bits.bit[i].pos == bit->pos) {
1487 LOGVAL(LYE_BITS_DUPVAL, line, LY_VLOG_NONE, NULL, bit->pos, bit->name);
1488 goto error;
1489 }
1490 }
1491
1492 /* keep them ordered by position */
1493 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1494 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001495 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1496 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1497 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001498 j--;
1499 }
1500
1501 return EXIT_SUCCESS;
1502
1503error:
1504 return EXIT_FAILURE;
1505}
Pavol Vican0df02b02016-03-01 10:28:50 +01001506
1507void *
1508yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value, int line)
1509{
1510 struct lys_tpdf *ret;
1511
1512 if (lyp_check_identifier(value, LY_IDENT_TYPE, line, module, parent)) {
1513 free(value);
1514 return NULL;
1515 }
1516 if (!parent) {
1517 ret = &module->tpdf[module->tpdf_size];
1518 ret->type.parent = NULL;
1519 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001520 } else {
1521 switch (parent->nodetype) {
1522 case LYS_GROUPING:
1523 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001524 ((struct lys_node_grp *)parent)->tpdf_size++;
1525 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001526 case LYS_CONTAINER:
1527 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1528 ((struct lys_node_container *)parent)->tpdf_size++;
1529 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001530 case LYS_LIST:
1531 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1532 ((struct lys_node_list *)parent)->tpdf_size++;
1533 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001534 case LYS_RPC:
1535 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1536 ((struct lys_node_rpc *)parent)->tpdf_size++;
1537 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001538 case LYS_INPUT:
1539 case LYS_OUTPUT:
1540 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1541 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1542 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001543 case LYS_NOTIF:
1544 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1545 ((struct lys_node_notif *)parent)->tpdf_size++;
1546 break;
Pavol Vican21238f52016-03-01 12:39:52 +01001547 }
Pavol Vican535d50e2016-03-01 13:05:33 +01001548 ret->type.parent = (struct lys_tpdf *)parent;
Pavol Vican0df02b02016-03-01 10:28:50 +01001549 }
1550
1551 ret->name = lydict_insert_zc(module->ctx, value);
1552 ret->module = module;
1553 return ret;
1554}
Pavol Vican1003ead2016-03-02 12:24:52 +01001555
1556void *
1557yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value, int line)
1558{
1559 struct lys_refine *rfn;
1560
1561 rfn = &uses->refine[uses->refine_size];
1562 uses->refine_size++;
1563 rfn->target_name = transform_schema2json(module, value, line);
1564 free(value);
1565 if (!rfn->target_name) {
1566 return NULL;
1567 }
1568 return rfn;
1569}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001570
1571void *
1572yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value, int line)
1573{
1574 struct lys_node_augment *aug;
1575 uint16_t *size;
1576
1577 if (parent) {
1578 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1579 } else {
1580 aug = &module->augment[module->augment_size];
1581 }
1582 aug->nodetype = LYS_AUGMENT;
1583 aug->target_name = transform_schema2json(module, value, line);
1584 free(value);
1585 if (!aug->target_name) {
1586 return NULL;
1587 }
1588 aug->parent = parent;
1589 aug->module = module;
1590 if (parent) {
1591 ((struct lys_node_uses *)parent)->augment_size++;
1592 } else {
1593 module->augment_size++;
1594 }
1595 return aug;
1596}
Pavol Vican220e5a12016-03-03 14:19:43 +01001597
1598void *
1599yang_read_deviation(struct lys_module *module, char *value, int line)
1600{
1601 struct lys_node *dev_target = NULL;
1602 struct lys_deviation *dev;
1603 struct type_deviation *deviation = NULL;
1604 int i, j, rc;
1605
1606 deviation = calloc(1, sizeof *deviation);
1607 if (!deviation) {
1608 LOGMEM;
1609 goto error;
1610 }
1611
1612 dev = &module->deviation[module->deviation_size];
1613 dev->target_name = transform_schema2json(module, value, line);
1614 free(value);
1615 if (!dev->target_name) {
1616 goto error;
1617 }
1618
1619 /* resolve target node */
1620 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1621 if (rc || !dev_target) {
1622 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
1623 goto error;
1624 }
1625 if (dev_target->module == lys_module(module)) {
1626 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
1627 goto error;
1628 }
1629 /*save pointer to the deviation and deviated target*/
1630 deviation->deviation = dev;
1631 deviation->target = dev_target;
1632
1633 /* mark the target module as deviated */
1634 dev_target->module->deviated = 1;
1635
1636 /* copy our imports to the deviated module (deviations may need them to work) */
1637 for (i = 0; i < module->imp_size; ++i) {
1638 for (j = 0; j < dev_target->module->imp_size; ++j) {
1639 if (module->imp[i].module == dev_target->module->imp[j].module) {
1640 break;
1641 }
1642 }
1643
1644 if (j < dev_target->module->imp_size) {
1645 /* import is already there */
1646 continue;
1647 }
1648
1649 /* copy the import, mark it as external */
1650 ++dev_target->module->imp_size;
1651 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1652 if (!dev_target->module->imp) {
1653 LOGMEM;
1654 goto error;
1655 }
1656 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1657 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1658 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1659 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1660 }
1661
1662 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1663 for (i = 0; i < dev_target->module->imp_size; ++i) {
1664 if (dev_target->module->imp[i].module == module) {
1665 break;
1666 }
1667 }
1668
1669 if (i == dev_target->module->imp_size) {
1670 ++dev_target->module->imp_size;
1671 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1672 if (!dev_target->module->imp) {
1673 LOGMEM;
1674 goto error;
1675 }
1676 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1677 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1678 if (module->rev_size) {
1679 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1680 } else {
1681 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1682 }
1683 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1684 } else {
1685 /* it could have been added by another deviating module that imported this deviating module */
1686 dev_target->module->imp[i].external = 2;
1687 }
1688
1689
1690 return deviation;
1691
1692error:
1693 free(deviation);
1694 lydict_remove(module->ctx, dev->target_name);
1695 return NULL;
1696}
Pavol Vican4c90c642016-03-03 15:06:47 +01001697
1698int
1699yang_read_deviate_unsupported(struct type_deviation *dev, int line)
1700{
1701 int i;
1702
1703 if (dev->deviation->deviate_size) {
1704 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1705 return EXIT_FAILURE;
1706 }
1707 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1708
1709 /* you cannot remove a key leaf */
1710 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1711 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1712 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
1713 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1714 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1715 return EXIT_FAILURE;
1716 }
1717 }
1718 }
1719
1720 /* unlink and store the original node */
1721 dev->deviation->orig_node = dev->target;
1722
1723 dev->deviation->deviate_size = 1;
1724 return EXIT_SUCCESS;
1725}
Pavol Vican85f12022016-03-05 16:30:35 +01001726
1727int
1728yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod, int line)
1729{
1730 struct unres_schema tmp_unres;
1731
1732 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1733 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1734 dev->deviation->deviate_size++;
1735 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
1736 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "not-supported");
1737 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1738 return EXIT_FAILURE;
1739 }
1740
1741 /* store a shallow copy of the original node */
1742 if (!dev->deviation->orig_node) {
1743 memset(&tmp_unres, 0, sizeof tmp_unres);
1744 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1745 /* just to be safe */
1746 if (tmp_unres.count) {
1747 LOGINT;
1748 return EXIT_FAILURE;
1749 }
1750 }
1751
1752 return EXIT_SUCCESS;
1753}
1754
1755int
1756yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1757{
1758 const char **stritem;
1759
1760 if (dev->deviate->units) {
1761 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "units", "deviate");
1762 free(value);
1763 goto error;
1764 }
1765
1766 /* check target node type */
1767 if (dev->target->nodetype == LYS_LEAFLIST) {
1768 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1769 } else if (dev->target->nodetype == LYS_LEAF) {
1770 stritem = &((struct lys_node_leaf *)dev->target)->units;
1771 } else {
1772 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1773 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"units\" property.");
1774 free(value);
1775 goto error;
1776 }
1777
1778 dev->deviate->units = lydict_insert_zc(ctx, value);
1779
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001780 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1781 /* check values */
1782 if (*stritem != dev->deviate->units) {
1783 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1784 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1785 goto error;
1786 }
1787 /* remove current units value of the target */
1788 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001789 } else {
1790 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1791 /* check that there is no current value */
1792 if (*stritem) {
1793 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1794 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1795 goto error;
1796 }
1797 } else { /* replace */
1798 if (!*stritem) {
1799 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1800 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1801 goto error;
1802 }
1803 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001804 /* remove current units value of the target ... */
1805 lydict_remove(ctx, *stritem);
1806
1807 /* ... and replace it with the value specified in deviation */
1808 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1809 }
1810
Pavol Vican85f12022016-03-05 16:30:35 +01001811 return EXIT_SUCCESS;
1812
1813error:
1814 return EXIT_FAILURE;
1815}
1816
1817int
1818yang_read_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_must, int line)
1819{
1820 uint8_t i;
1821
1822 /* check target node type */
1823 switch (dev->target->nodetype) {
1824 case LYS_LEAF:
1825 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1826 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1827 break;
1828 case LYS_CONTAINER:
1829 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1830 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1831 break;
1832 case LYS_LEAFLIST:
1833 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1834 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1835 break;
1836 case LYS_LIST:
1837 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1838 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1839 break;
1840 case LYS_ANYXML:
1841 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1842 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1843 break;
1844 default:
1845 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "must");
1846 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"must\" property.");
1847 goto error;
1848 }
1849
1850 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1851 /* reallocate the must array of the target */
1852 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1853 if (!dev->deviate->must) {
1854 LOGMEM;
1855 goto error;
1856 }
1857 *dev->trg_must = dev->deviate->must;
1858 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1859 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001860 } else {
1861 /* LY_DEVIATE_DEL */
1862 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1863 if (!dev->deviate->must) {
1864 LOGMEM;
1865 goto error;
1866 }
Pavol Vican85f12022016-03-05 16:30:35 +01001867 }
1868
1869 return EXIT_SUCCESS;
1870
1871error:
1872 return EXIT_FAILURE;
1873}
1874
1875int
1876yang_read_deviate_unique(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_uniq, int line)
1877{
1878 int i, j;
1879 struct lys_node_list *list;
1880
1881 /* check target node type */
1882 if (dev->target->nodetype != LYS_LIST) {
1883 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "unique");
1884 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"unique\" property.");
1885 goto error;
1886 }
1887
1888 list = (struct lys_node_list *)dev->target;
1889 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1890 /* reallocate the unique array of the target */
1891 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1892 if (!dev->deviate->unique) {
1893 LOGMEM;
1894 goto error;
1895 }
1896 list->unique = dev->deviate->unique;
1897 dev->deviate->unique = &list->unique[list->unique_size];
1898 dev->deviate->unique_size = c_uniq;
1899 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001900 } else {
1901 /* LY_DEVIATE_DEL */
1902 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1903 if (!dev->deviate->unique) {
1904 LOGMEM;
1905 goto error;
1906 }
Pavol Vican85f12022016-03-05 16:30:35 +01001907 }
1908
1909 return EXIT_SUCCESS;
1910
1911error:
1912 return EXIT_FAILURE;
1913}
1914
1915int
1916yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1917{
1918 int rc;
1919 struct lys_node_choice *choice;
1920 struct lys_node_leaf *leaf;
1921 struct lys_node *node;
1922
1923 if (dev->deviate->dflt) {
1924 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "default", "deviate");
1925 free(value);
1926 goto error;
1927 }
1928
1929 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1930
1931 if (dev->target->nodetype == LYS_CHOICE) {
1932 choice = (struct lys_node_choice *)dev->target;
1933
Pavol Vican85f12022016-03-05 16:30:35 +01001934 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1935 if (rc || !node) {
1936 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1937 goto error;
1938 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001939 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1940 if (!choice->dflt || (choice->dflt != node)) {
1941 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1942 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1943 goto error;
1944 }
1945 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001946 } else {
1947 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1948 /* check that there is no current value */
1949 if (choice->dflt) {
1950 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1951 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1952 goto error;
1953 }
1954 } else { /* replace*/
1955 if (!choice->dflt) {
1956 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1957 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1958 goto error;
1959 }
1960 }
1961
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001962 choice->dflt = node;
1963 if (!choice->dflt) {
1964 /* default branch not found */
1965 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1966 goto error;
1967 }
Pavol Vican85f12022016-03-05 16:30:35 +01001968 }
1969 } else if (dev->target->nodetype == LYS_LEAF) {
1970 leaf = (struct lys_node_leaf *)dev->target;
1971
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001972 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1973 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
1974 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1975 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1976 goto error;
1977 }
1978 /* remove value */
1979 lydict_remove(ctx, leaf->dflt);
1980 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001981 } else {
1982 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1983 /* check that there is no current value */
1984 if (leaf->dflt) {
1985 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1986 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1987 goto error;
1988 }
1989 } else { /* replace*/
1990 if (!leaf->dflt) {
1991 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1992 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1993 goto error;
1994 }
1995 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001996 /* remove value */
1997 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001998
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001999 /* set new value */
2000 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
2001 }
Pavol Vican85f12022016-03-05 16:30:35 +01002002 } else {
2003 /* invalid target for default value */
2004 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
2005 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"default\" property.");
2006 goto error;
2007 }
2008
2009 return EXIT_SUCCESS;
2010
2011error:
2012 return EXIT_FAILURE;
2013}
2014
2015int
2016yang_read_deviate_config(struct type_deviation *dev, uint8_t value, int line)
2017{
2018 if (dev->deviate->flags & LYS_CONFIG_MASK) {
2019 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "config", "deviate");
2020 goto error;
2021 }
2022
2023 /* for we deviate from RFC 6020 and allow config property even it is/is not
2024 * specified in the target explicitly since config property inherits. So we expect
2025 * that config is specified in every node. But for delete, we check that the value
2026 * is the same as here in deviation
2027 */
2028 dev->deviate->flags |= value;
2029
2030 /* add and replace are the same in this case */
2031 /* remove current config value of the target ... */
2032 dev->target->flags &= ~LYS_CONFIG_MASK;
2033
2034 /* ... and replace it with the value specified in deviation */
2035 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2036
2037 return EXIT_SUCCESS;
2038
2039error:
2040 return EXIT_FAILURE;
2041}
2042
2043int
2044yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value, int line)
2045{
2046 if (dev->deviate->flags & LYS_MAND_MASK) {
2047 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "mandatory", "deviate");
2048 goto error;
2049 }
2050
2051 /* check target node type */
2052 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
2053 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
2054 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"mandatory\" property.");
2055 goto error;
2056 }
2057
2058 dev->deviate->flags |= value;
2059
2060 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2061 /* check that there is no current value */
2062 if (dev->target->flags & LYS_MAND_MASK) {
2063 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
2064 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
2065 goto error;
2066 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002067 } else { /* replace */
2068 if (!(dev->target->flags & LYS_MAND_MASK)) {
2069 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
2070 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
2071 goto error;
2072 }
Pavol Vican85f12022016-03-05 16:30:35 +01002073 }
2074
Pavol Vican85f12022016-03-05 16:30:35 +01002075 /* remove current mandatory value of the target ... */
2076 dev->target->flags &= ~LYS_MAND_MASK;
2077
2078 /* ... and replace it with the value specified in deviation */
2079 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2080
2081 return EXIT_SUCCESS;
2082
2083error:
2084 return EXIT_FAILURE;
2085}
2086
2087int
2088yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type, int line)
2089{
2090 uint32_t *ui32val;
2091
2092 /* check target node type */
2093 if (dev->target->nodetype == LYS_LEAFLIST) {
2094 if (type) {
2095 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
2096 } else {
2097 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
2098 }
2099 } else if (dev->target->nodetype == LYS_LIST) {
2100 if (type) {
2101 ui32val = &((struct lys_node_list *)dev->target)->max;
2102 } else {
2103 ui32val = &((struct lys_node_list *)dev->target)->min;
2104 }
2105 } else {
2106 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2107 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
2108 goto error;
2109 }
2110
2111 if (type) {
2112 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002113 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002114 } else {
2115 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002116 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01002117 }
2118
2119 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2120 /* check that there is no current value */
2121 if (*ui32val) {
2122 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2123 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
2124 goto error;
2125 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002126 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2127 /* unfortunately, there is no way to check reliably that there
2128 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002129 }
2130
2131 /* add (already checked) and replace */
2132 /* set new value specified in deviation */
2133 *ui32val = value;
2134
2135 return EXIT_SUCCESS;
2136
2137error:
2138 return EXIT_FAILURE;
2139}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002140
2141int
2142yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line)
2143{
2144 int i;
2145
2146 /* find must to delete, we are ok with just matching conditions */
2147 for (i = 0; i < *dev->trg_must_size; i++) {
2148 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2149 /* we have a match, free the must structure ... */
2150 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2151 /* ... and maintain the array */
2152 (*dev->trg_must_size)--;
2153 if (i != *dev->trg_must_size) {
2154 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2155 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2156 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2157 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2158 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2159 }
2160 if (!(*dev->trg_must_size)) {
2161 free(*dev->trg_must);
2162 *dev->trg_must = NULL;
2163 } else {
2164 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2165 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2166 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2167 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2168 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2169 }
2170
2171 i = -1; /* set match flag */
2172 break;
2173 }
2174 }
2175 if (i != -1) {
2176 /* no match found */
2177 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2178 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
2179 return EXIT_FAILURE;
2180 }
2181
2182 return EXIT_SUCCESS;
2183}
2184
2185int
2186yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line)
2187{
2188 struct lys_node_list *list;
2189 int i, j;
2190
2191 list = (struct lys_node_list *)dev->target;
2192 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL, line)) {
2193 dev->deviate->unique_size++;
2194 goto error;
2195 }
2196
2197 /* find unique structures to delete */
2198 for (i = 0; i < list->unique_size; i++) {
2199 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2200 continue;
2201 }
2202
2203 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2204 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2205 break;
2206 }
2207 }
2208
2209 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2210 /* we have a match, free the unique structure ... */
2211 for (j = 0; j < list->unique[i].expr_size; j++) {
2212 lydict_remove(module->ctx, list->unique[i].expr[j]);
2213 }
2214 free(list->unique[i].expr);
2215 /* ... and maintain the array */
2216 list->unique_size--;
2217 if (i != list->unique_size) {
2218 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2219 list->unique[i].expr = list->unique[list->unique_size].expr;
2220 }
2221
2222 if (!list->unique_size) {
2223 free(list->unique);
2224 list->unique = NULL;
2225 } else {
2226 list->unique[list->unique_size].expr_size = 0;
2227 list->unique[list->unique_size].expr = NULL;
2228 }
2229
2230 i = -1; /* set match flag */
2231 break;
2232 }
2233 }
2234 dev->deviate->unique_size++;
2235
2236 if (i != -1) {
2237 /* no match found */
2238 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, value, "unique");
2239 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
2240 goto error;
2241 }
2242
2243 free(value);
2244 return EXIT_SUCCESS;
2245
2246error:
2247 free(value);
2248 return EXIT_FAILURE;
2249}