blob: 975893a39be0bde02dfa12c1126ba5ff394e5d80 [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 Vicanbedff692016-02-03 14:29:17 +0100244 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100245 }
246 return ret;
247}
248
249int
250yang_read_reference(struct lys_module *module, void *node, char *value, int type, int line)
251{
252 int ret;
253
254 if (!node) {
255 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100256 } else {
257 switch (type) {
258 case REVISION_KEYWORD:
259 ret = yang_check_string(module, &((struct lys_revision *) node)->ref, "reference", "revision", value, line);
260 break;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100261 case FEATURE_KEYWORD:
262 ret = yang_check_string(module, &((struct lys_feature *) node)->ref, "reference", "feature", value, line);
263 break;
264 case IDENTITY_KEYWORD:
265 ret = yang_check_string(module, &((struct lys_ident *) node)->ref, "reference", "identity", value, line);
266 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100267 case MUST_KEYWORD:
Pavol Vican235dbd42016-02-10 10:34:19 +0100268 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "must", value, line);
269 break;
270 case WHEN_KEYWORD:
271 ret = yang_check_string(module, &((struct lys_when *) node)->ref, "reference", "when", value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100272 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100273 case CONTAINER_KEYWORD:
274 ret = yang_check_string(module, &((struct lys_node_container *) node)->ref, "reference", "container", value, line);
275 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100276 case ANYXML_KEYWORD:
277 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "anyxml", value, line);
278 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100279 case CHOICE_KEYWORD:
280 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "choice", value, line);
281 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100282 case CASE_KEYWORD:
283 ret = yang_check_string(module, &((struct lys_node_anyxml *) node)->ref, "reference", "case", value, line);
284 break;
Pavol Vican12f53c32016-02-11 11:40:00 +0100285 case GROUPING_KEYWORD:
286 ret = yang_check_string(module, &((struct lys_node_grp *) node)->ref, "reference", "grouping", value, line);
287 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100288 case LEAF_KEYWORD:
289 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->ref, "reference", "leaf", value, line);
290 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100291 case LEAF_LIST_KEYWORD:
292 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->ref, "reference", "leaflist", value, line);
293 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100294 case LIST_KEYWORD:
295 ret = yang_check_string(module, &((struct lys_node_list *) node)->ref, "reference", "list", value, line);
296 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100297 case LENGTH_KEYWORD:
298 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "length", value, line);
299 break;
Pavol Vican1c203db2016-02-24 14:05:23 +0100300 case PATTERN_KEYWORD:
301 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "pattern", value, line);
302 break;
Pavol Vicanaff5c802016-02-24 15:56:45 +0100303 case RANGE_KEYWORD:
304 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "range", value, line);
305 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100306 case ENUM_KEYWORD:
307 ret = yang_check_string(module, &((struct lys_type_enum *) node)->ref, "reference", "enum", value, line);
308 break;
Pavol Vican9887c682016-02-29 11:32:01 +0100309 case BIT_KEYWORD:
310 ret = yang_check_string(module, &((struct lys_type_bit *) node)->ref, "reference", "bit", value, line);
311 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100312 case TYPEDEF_KEYWORD:
313 ret = yang_check_string(module, &((struct lys_tpdf *) node)->ref, "reference", "typedef", value, line);
314 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100315 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100316 }
317 return ret;
318}
Pavol Vicanbedff692016-02-03 14:29:17 +0100319
320void *
321yang_read_revision(struct lys_module *module, char *value)
322{
323 struct lys_revision *retval;
324
Pavol Vican1eeb1992016-02-09 11:10:45 +0100325 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100326
327 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100328 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100329 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
330 memcpy(module->rev[0].date, value, LY_REV_SIZE);
331 retval->dsc = module->rev[0].dsc;
332 retval->ref = module->rev[0].ref;
333 retval = module->rev;
334 retval->dsc = NULL;
335 retval->ref = NULL;
336 } else {
337 memcpy(retval->date, value, LY_REV_SIZE);
338 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100339 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100340 free(value);
341 return retval;
342}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100343
344int
Pavol Vicana1827962016-02-29 15:39:42 +0100345yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100346{
347 if (!*size % LY_ARRAY_SIZE) {
348 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
349 LOGMEM;
350 return EXIT_FAILURE;
351 } else {
352 memset(*node+*size,0,LY_ARRAY_SIZE*sizeof **node);
353 }
354 }
355 (*size)++;
356 return EXIT_SUCCESS;
357}
Pavol Vicane1354e92016-02-09 14:02:09 +0100358
359void *
360yang_read_feature(struct lys_module *module, char *value, int line)
361{
362 struct lys_feature *retval;
363
364 /* check uniqueness of feature's names */
365 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
366 goto error;
367 }
368 retval = &module->features[module->features_size];
369 retval->name = lydict_insert_zc(module->ctx, value);
370 retval->module = module;
371 module->features_size++;
372 return retval;
373
374error:
375 free(value);
376 return NULL;
377}
378
379int
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100380yang_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 +0100381{
382 const char *exp;
383 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100384 struct lys_feature *f;
385 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100386
387 if (!(exp = transform_schema2json(module, value, line))) {
388 free(value);
389 return EXIT_FAILURE;
390 }
391 free(value);
392
393 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100394 if (type == FEATURE_KEYWORD) {
395 f = (struct lys_feature *) ptr;
396 f->features[f->features_size] = f;
397 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
398 f->features_size++;
399 } else {
400 n = (struct lys_node *) ptr;
401 n->features[n->features_size] = (struct lys_feature *) n;
402 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
403 n->features_size++;
404 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100405
406 lydict_remove(module->ctx, exp);
407 if (ret == -1) {
408
409 return EXIT_FAILURE;
410 }
411 return EXIT_SUCCESS;
412}
413
414static int
415yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
416{
417 if (*flags & mask) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100418 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100419 return EXIT_FAILURE;
420 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100421 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100422 return EXIT_SUCCESS;
423 }
424}
425
426int
427yang_read_status(void *node, int value, int type, int line)
428{
429 int retval;
430
431 switch (type) {
432 case FEATURE_KEYWORD:
433 retval = yang_check_flags(&((struct lys_feature *) node)->flags, LYS_STATUS_MASK, "status", "feature", value, line);
434 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100435 case IDENTITY_KEYWORD:
Pavol Vicanbbdef532016-02-09 14:52:12 +0100436 retval = yang_check_flags(&((struct lys_ident *) node)->flags, LYS_STATUS_MASK, "status", "identity", value, line);
437 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100438 case CONTAINER_KEYWORD:
439 retval = yang_check_flags(&((struct lys_node_container *) node)->flags, LYS_STATUS_MASK, "status", "container", value, line);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100440 break;
441 case ANYXML_KEYWORD:
442 retval = yang_check_flags(&((struct lys_node_anyxml *) node)->flags, LYS_STATUS_MASK, "status", "anyxml", value, line);
443 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100444 case CHOICE_KEYWORD:
445 retval = yang_check_flags(&((struct lys_node_anyxml *) node)->flags, LYS_STATUS_MASK, "status", "choice", value, line);
446 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100447 case CASE_KEYWORD:
448 retval = yang_check_flags(&((struct lys_node_case *) node)->flags, LYS_STATUS_MASK, "status", "case", value, line);
449 break;
Pavol Vican12f53c32016-02-11 11:40:00 +0100450 case GROUPING_KEYWORD:
451 retval = yang_check_flags(&((struct lys_node_grp *) node)->flags, LYS_STATUS_MASK, "status", "grouping", value, line);
452 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100453 case LEAF_KEYWORD:
454 retval = yang_check_flags(&((struct lys_node_leaf *) node)->flags, LYS_STATUS_MASK, "status", "leaf", value, line);
455 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100456 case LEAF_LIST_KEYWORD:
457 retval = yang_check_flags(&((struct lys_node_leaflist *) node)->flags, LYS_STATUS_MASK, "status", "leaflist", value, line);
458 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100459 case LIST_KEYWORD:
460 retval = yang_check_flags(&((struct lys_node_list *) node)->flags, LYS_STATUS_MASK, "status", "list", value, line);
461 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100462 case ENUM_KEYWORD:
463 retval = yang_check_flags(&((struct lys_type_enum *) node)->flags, LYS_STATUS_MASK, "status", "enum", value, line);
Pavol Vican9887c682016-02-29 11:32:01 +0100464 break;
465 case BIT_KEYWORD:
466 retval = yang_check_flags(&((struct lys_type_bit *) node)->flags, LYS_STATUS_MASK, "status", "bit", value, line);
467 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100468 case TYPEDEF_KEYWORD:
469 retval = yang_check_flags(&((struct lys_tpdf *) node)->flags, LYS_STATUS_MASK, "status", "typedef", value, line);
470 break;
Pavol Vicane1354e92016-02-09 14:02:09 +0100471 }
472 return retval;
473}
Pavol Vicanbbdef532016-02-09 14:52:12 +0100474
475void *
476yang_read_identity(struct lys_module *module, char *value)
477{
478 struct lys_ident *ret;
479
480 ret = &module->ident[module->ident_size];
481 ret->name = lydict_insert_zc(module->ctx, value);
482 ret->module = module;
483 module->ident_size++;
484 return ret;
485}
486
487int
488yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
489{
490 const char *exp;
491
492 if (ident->base) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100493 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "base", "identity");
Pavol Vicanbbdef532016-02-09 14:52:12 +0100494 return EXIT_FAILURE;
495 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100496 exp = transform_schema2json(module, value, line);
497 free(value);
498 if (!exp) {
499 return EXIT_FAILURE;
500 }
501 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
502 lydict_remove(module->ctx, exp);
503 return EXIT_FAILURE;
504 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100505
506 /* hack - store some address due to detection of unresolved base*/
507 if (!ident->base) {
508 ident->base = (void *)1;
509 }
510
Pavol Vicanbbdef532016-02-09 14:52:12 +0100511 lydict_remove(module->ctx, exp);
512 return EXIT_SUCCESS;
513}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100514
515void *
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100516yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
517{
518 struct lys_restr *retval;
519
520 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100521 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100522 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100523 break;
524 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100525 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
526 break;
527 case LEAF_KEYWORD:
528 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100529 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100530 case LEAF_LIST_KEYWORD:
531 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
532 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100533 case LIST_KEYWORD:
534 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
535 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100536 }
537 retval->expr = transform_schema2json(module, value, line);
538 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
539 goto error;
540 }
541 free(value);
542 return retval;
543
544error:
545 free(value);
546 return NULL;
547}
548
549int
550yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, int type, int message, int line)
551{
552 int ret;
553 char *exp;
554
555 switch (type) {
556 case MUST_KEYWORD:
557 exp = "must";
558 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100559 case LENGTH_KEYWORD:
560 exp = "length";
561 break;
Pavol Vican1c203db2016-02-24 14:05:23 +0100562 case PATTERN_KEYWORD:
563 exp = "pattern";
564 break;
Pavol Vicanaff5c802016-02-24 15:56:45 +0100565 case RANGE_KEYWORD:
566 exp = "range";
567 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100568 }
569 if (message==ERROR_APP_TAG_KEYWORD) {
570 ret = yang_check_string(module, &save->eapptag, "error_app_tag", exp, value, line);
571 } else {
572 ret = yang_check_string(module, &save->emsg, "error_app_tag", exp, value, line);
573 }
574 return ret;
575}
Pavol Vicanb5687112016-02-09 22:35:59 +0100576
577int
578yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
579{
580 if (cont->presence) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100581 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100582 free(value);
583 return EXIT_FAILURE;
584 } else {
585 cont->presence = lydict_insert_zc(module->ctx, value);
586 return EXIT_SUCCESS;
587 }
588}
589
590int
591yang_read_config(void *node, int value, int type, int line)
592{
593 int ret;
594
595 switch (type) {
596 case CONTAINER_KEYWORD:
597 ret = yang_check_flags(&((struct lys_node_container *)node)->flags, LYS_CONFIG_MASK, "config", "container", value, line);
598 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100599 case ANYXML_KEYWORD:
600 ret = yang_check_flags(&((struct lys_node_anyxml *)node)->flags, LYS_CONFIG_MASK, "config", "anyxml", value, line);
601 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100602 case CHOICE_KEYWORD:
603 ret = yang_check_flags(&((struct lys_node_choice *)node)->flags, LYS_CONFIG_MASK, "config", "choice", value, line);
604 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100605 case LEAF_KEYWORD:
606 ret = yang_check_flags(&((struct lys_node_leaf *)node)->flags, LYS_CONFIG_MASK, "config", "leaf", value, line);
607 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100608 case LEAF_LIST_KEYWORD:
Pavol Vican5de33492016-02-22 14:03:24 +0100609 ret = yang_check_flags(&((struct lys_node_leaflist *)node)->flags, LYS_CONFIG_MASK, "config", "leaflist", value, line);
610 break;
611 case LIST_KEYWORD:
612 ret = yang_check_flags(&((struct lys_node_list *)node)->flags, LYS_CONFIG_MASK, "config", "list", value, line);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100613 break;
Pavol Vicanb5687112016-02-09 22:35:59 +0100614 }
615 return ret;
616}
Pavol Vican235dbd42016-02-10 10:34:19 +0100617
618void *
619yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
620{
621 struct lys_when *retval;
622
623 retval = calloc(1, sizeof *retval);
624 if (!retval) {
625 LOGMEM;
626 free(value);
627 return NULL;
628 }
629 retval->cond = transform_schema2json(module, value, line);
630 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
631 goto error;
632 }
633 switch (type) {
634 case CONTAINER_KEYWORD:
635 if (((struct lys_node_container *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100636 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100637 goto error;
638 }
639 ((struct lys_node_container *)node)->when = retval;
640 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100641 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100642 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100643 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100644 goto error;
645 }
646 ((struct lys_node_anyxml *)node)->when = retval;
647 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100648 case CHOICE_KEYWORD:
649 if (((struct lys_node_choice *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100650 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100651 goto error;
652 }
653 ((struct lys_node_choice *)node)->when = retval;
654 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100655 case CASE_KEYWORD:
656 if (((struct lys_node_case *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100657 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100658 goto error;
659 }
660 ((struct lys_node_case *)node)->when = retval;
661 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100662 case LEAF_KEYWORD:
663 if (((struct lys_node_leaf *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100664 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100665 goto error;
666 }
667 ((struct lys_node_leaf *)node)->when = retval;
668 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100669 case LEAF_LIST_KEYWORD:
670 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100671 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100672 goto error;
673 }
674 ((struct lys_node_leaflist *)node)->when = retval;
675 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100676 case LIST_KEYWORD:
677 if (((struct lys_node_list *)node)->when) {
678 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "list");
679 goto error;
680 }
681 ((struct lys_node_list *)node)->when = retval;
682 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100683 }
684 free(value);
685 return retval;
686
687error:
688 free(value);
689 lys_when_free(module->ctx, retval);
690 return NULL;
691}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100692
693void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100694yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100695{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100696 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100697
Pavol Vican7cadfe72016-02-11 12:33:34 +0100698 node = calloc(1, sizeof_struct);
699 if (!node) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100700 LOGMEM;
701 return NULL;
702 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100703 node->module = module;
704 node->name = lydict_insert_zc(module->ctx, value);
705 node->nodetype = nodetype;
706 node->prev = node;
707
708 /* insert the node into the schema tree */
709 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
710 lydict_remove(module->ctx, node->name);
711 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100712 return NULL;
713 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100714 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100715}
716
717int
718yang_read_mandatory(void *node, int value, int type, int line)
719{
720 int ret;
721
722 switch (type) {
723 case ANYXML_KEYWORD:
724 ret = yang_check_flags(&((struct lys_node_anyxml *)node)->flags, LYS_MAND_MASK, "mandatory", "anyxml", value, line);
725 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100726 case CHOICE_KEYWORD:
727 ret = yang_check_flags(&((struct lys_node_choice *)node)->flags, LYS_MAND_MASK, "mandatory", "choice", value, line);
728 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100729 case LEAF_KEYWORD:
730 ret = yang_check_flags(&((struct lys_node_leaf *)node)->flags, LYS_MAND_MASK, "mandatory", "leaf", value, line);
731 break;
732 }
733 return ret;
734}
735
736int
737yang_read_default(struct lys_module *module, void *node, char *value, int type, int line)
738{
739 int ret;
740
741 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100742 case LEAF_KEYWORD:
743 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, line);
744 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100745 case TYPEDEF_KEYWORD:
746 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, line);
747 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100748 }
749 return ret;
750}
751
752int
753yang_read_units(struct lys_module *module, void *node, char *value, int type, int line)
754{
755 int ret;
756
757 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100758 case LEAF_KEYWORD:
759 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, line);
760 break;
761 case LEAF_LIST_KEYWORD:
762 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, line);
763 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100764 case TYPEDEF_KEYWORD:
765 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, line);
766 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100767 }
768 return ret;
769}
Pavol Vican5de33492016-02-22 14:03:24 +0100770
771int
772yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres, int line)
773{
774 char *exp, *value;
775
776 exp = value = (char *) list->keys;
777 while ((value = strpbrk(value, " \t\n"))) {
778 list->keys_size++;
779 while (isspace(*value)) {
780 value++;
781 }
782 }
783 list->keys_size++;
784 list->keys = calloc(list->keys_size, sizeof *list->keys);
785 if (!list->keys) {
786 LOGMEM;
787 goto error;
788 }
789 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp, line) == -1) {
790 goto error;
791 }
792 free(exp);
793 return EXIT_SUCCESS;
794
795error:
796 free(exp);
797 return EXIT_FAILURE;
798}
799
800int
801yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
802{
803 uint8_t k;
804 int i, j;
805 char *value, *vaux;
806 struct lys_unique *unique;
807 struct type_ident *ident;
808
809 for(k=0; k<list->unique_size; k++) {
810 unique = &list->unique[k];
811 ident = (struct type_ident *)list->unique[k].expr;
812
813 /* count the number of unique leafs in the value */
814 vaux = value = ident->s;
815 while ((vaux = strpbrk(vaux, " \t\n"))) {
816 unique->expr_size++;
817 while (isspace(*vaux)) {
818 vaux++;
819 }
820 }
821 unique->expr_size++;
822 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
823 if (!unique->expr) {
824 LOGMEM;
825 goto error;
826 }
827
828 for (i = 0; i < unique->expr_size; i++) {
829 vaux = strpbrk(value, " \t\n");
830 if (!vaux) {
831 /* the last token, lydict_insert() will count its size on its own */
832 vaux = value;
833 }
834
835 /* store token into unique structure */
836 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
837
838 /* check that the expression does not repeat */
839 for (j = 0; j < i; j++) {
840 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
841 LOGVAL(LYE_INARG, ident->line, LY_VLOG_LYS, list, unique->expr[i], "unique");
842 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
843 goto error;
844 }
845 }
846
847 /* try to resolve leaf */
848 if (unres) {
849 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i], ident->line);
850 } else {
851 if (resolve_unique((struct lys_node *)list, value, 0, ident->line)) {
852 goto error;
853 }
854 }
855
856 /* move to next token */
857 value = vaux;
858 while(isspace(*value)) {
859 value++;
860 }
861 }
862 free(ident);
863 }
864 return EXIT_SUCCESS;
865
866error:
867 free(ident);
868 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100869}
870
Pavol Vican1ff0e222016-02-26 12:27:01 +0100871static int
872yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres, int line)
873{
874 const char *value, *tmp;
875 int rc, ret = EXIT_FAILURE;
876
877 value = tmp = type->info.lref.path;
878 /* store in the JSON format */
879 value = transform_schema2json(module, value, line);
880 if (!value) {
881 goto end;
882 }
883 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, line);
884 lydict_remove(module->ctx, value);
885
886 if (rc == -1) {
887 goto end;
888 }
889
890 ret = EXIT_SUCCESS;
891
892end:
893 lydict_remove(module->ctx, tmp);
894 return ret;
895}
896
Pavol Vican73e7c992016-02-24 12:18:05 +0100897int
898yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
899{
900 int i, rc;
901 int ret = -1;
902 const char *name, *value;
903 LY_DATA_TYPE base;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100904 struct yang_type *typ_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100905
Pavol Vican0df02b02016-03-01 10:28:50 +0100906 base = typ->type->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100907 value = transform_schema2json(module, typ->name, typ->line);
908 if (!value) {
909 goto error;
910 }
911
912 i = parse_identifier(value);
913 if (i < 1) {
914 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
915 lydict_remove(module->ctx, value);
916 goto error;
917 }
918 /* module name*/
919 name = value;
920 if (value[i]) {
921 typ->type->module_name = lydict_insert(module->ctx, value, i);
922 name += i;
923 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
924 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, name[0], name);
925 lydict_remove(module->ctx, value);
926 goto error;
927 }
928 ++name;
929 }
930
931 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
932 lydict_remove(module->ctx, value);
933 if (rc == -1) {
934 LOGVAL(LYE_INMOD, typ->line, LY_VLOG_NONE, NULL, typ->type->module_name);
935 goto error;
936
937 /* the type could not be resolved or it was resolved to an unresolved typedef*/
938 } else if (rc == EXIT_FAILURE) {
939 ret = EXIT_FAILURE;
940 goto error;
941 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100942 typ->type->base = typ->type->der->type.base;
943 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100944 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100945 }
946 switch (base) {
947 case LY_TYPE_STRING:
948 if (typ->type->base == LY_TYPE_BINARY) {
949 if (typ->type->info.str.pat_count) {
950 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100951 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100952 goto error;
953 }
954 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100955 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 +0100956 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
957 goto error;
958 }
959 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100960 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 +0100961 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
962 goto error;
963 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100964 } else {
965 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
966 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100967 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100968 break;
969 case LY_TYPE_DEC64:
970 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100971 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 +0100972 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
973 goto error;
974 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100975 /* mandatory sub-statement(s) check */
976 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
977 /* decimal64 type directly derived from built-in type requires fraction-digits */
978 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
979 goto error;
980 }
981 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
982 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
983 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits");
984 goto error;
985 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100986 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
987 if (typ->type->info.dec64.dig) {
988 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
989 typ->type->base = base;
990 goto error;
991 }
992 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100993 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 +0100994 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
995 goto error;
996 }
997 } else {
998 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
999 goto error;
1000 }
1001 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001002 case LY_TYPE_ENUM:
1003 if (typ->type->base != LY_TYPE_ENUM) {
1004 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1005 goto error;
1006 }
1007 if (!typ->type->der->type.der && !typ->type->info.enums.count) {
1008 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1009 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "enum", "type");
1010 goto error;
1011 }
1012 if (typ->type->der->type.der && typ->type->info.enums.count) {
1013 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
1014 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "enum");
1015 goto error;
1016 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001017 break;
1018 case LY_TYPE_LEAFREF:
1019 if (typ->type->base == LY_TYPE_IDENT && typ->flags & LYS_TYPE_BASE) {
1020 if (yang_read_identyref(module, typ->type, unres, typ->line)) {
1021 goto error;
1022 }
Pavol Vican191613a2016-02-26 16:21:32 +01001023 } else if (typ->type->base == LY_TYPE_LEAFREF) {
1024 if (typ->type->info.lref.path && !typ->type->der->type.der) {
1025 value = typ->type->info.lref.path;
1026 /* store in the JSON format */
1027 typ->type->info.lref.path = transform_schema2json(module, value, typ->line);
1028 lydict_remove(module->ctx, value);
1029 if (!typ->type->info.lref.path) {
1030 goto error;
1031 }
1032 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent, typ->line) == -1) {
1033 goto error;
1034 }
1035 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
1036 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "path", "type");
1037 goto error;
1038 } else {
1039 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "path");
1040 goto error;
1041 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001042 } else {
1043 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1044 goto error;
1045 }
1046 break;
1047 case LY_TYPE_IDENT:
1048 if (typ->type->der->type.der) {
1049 /* this is just a derived type with no base specified/required */
1050 break;
1051 } else {
1052 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "base", "type");
1053 goto error;
1054 }
1055 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001056 case LY_TYPE_UNION:
1057 if (typ->type->base != LY_TYPE_UNION) {
1058 typ->type->base = LY_TYPE_UNION;
1059 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1060 goto error;
1061 }
1062 if (!typ->type->info.uni.types) {
1063 if (typ->type->der->type.der) {
1064 /* this is just a derived type with no additional type specified/required */
1065 break;
1066 }
1067 LOGVAL(LYE_MISSSTMT2, typ->line, LY_VLOG_NONE, NULL, "type", "(union) type");
1068 goto error;
1069 }
1070 for (i = 0; i < typ->type->info.uni.count; i++) {
1071 typ_tmp = (struct yang_type *)typ->type->info.uni.types[i].der;
1072 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent, typ_tmp->line)) {
1073 goto error;
1074 }
1075 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
1076 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "empty", typ->name);
1077 goto error;
1078 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
1079 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "leafref", typ->name);
1080 goto error;
1081 }
1082 }
1083 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001084
1085 default:
1086 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1087 if (typ->type->base != base) {
1088 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
1089 goto error;
1090 }
1091 } else {
1092 LOGINT;
1093 goto error;
1094 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001095 }
1096 return EXIT_SUCCESS;
1097
1098error:
Pavol Vicana1827962016-02-29 15:39:42 +01001099 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +01001100 if (typ->type->module_name) {
1101 lydict_remove(module->ctx, typ->type->module_name);
1102 typ->type->module_name = NULL;
1103 }
1104 return ret;
1105}
1106
1107void *
1108yang_read_type(void *parent, struct yang_schema *yang, char *value, int type, int line)
1109{
1110 struct yang_type *typ;
1111 struct yang_schema *new, *tmp;
1112
1113 /* linear list */
1114 new = calloc(1, sizeof *new);
1115 if (!new) {
1116 LOGMEM;
1117 return NULL;
1118 }
1119 tmp = yang;
1120 while (tmp->next) {
1121 tmp = tmp->next;
1122 }
1123 tmp->next = new;
1124 typ = &new->type;
1125
1126 typ->flags = LY_YANG_STRUCTURE_FLAG;
1127 switch (type) {
1128 case LEAF_KEYWORD:
1129 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1130 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1131 typ->type = &((struct lys_node_leaf *)parent)->type;
1132 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001133 case UNION_KEYWORD:
1134 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1135 typ->type = (struct lys_type *)parent;
1136 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001137 case TYPEDEF_KEYWORD:
1138 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1139 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican73e7c992016-02-24 12:18:05 +01001140 }
1141 typ->name = value;
1142 typ->line = line;
1143 typ->parent = parent;
1144 return typ;
1145}
1146
1147void *
1148yang_read_length(struct lys_module *module, struct yang_type *typ, char *value, int line)
1149{
1150 struct lys_restr **length;
1151
1152 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
1153 length = &typ->type->info.str.length;
1154 typ->type->base = LY_TYPE_STRING;
1155 } else if (typ->type->base == LY_TYPE_BINARY) {
1156 length = &typ->type->info.binary.length;
1157 } else {
1158 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected length statement.");
1159 goto error;
1160 }
1161
1162 if (*length) {
1163 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "length", "type");
1164 }
1165 *length = calloc(1, sizeof **length);
1166 if (!*length) {
1167 LOGMEM;
1168 goto error;
1169 }
1170 (*length)->expr = lydict_insert_zc(module->ctx, value);
1171 return *length;
1172
1173error:
1174 free(value);
1175 return NULL;
1176
1177}
Pavol Vican1c203db2016-02-24 14:05:23 +01001178
1179void *
1180yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value, int line)
1181{
1182 pcre *precomp;
1183 int err_offset;
1184 const char *err_ptr;
1185
1186 /* check that the regex is valid */
1187 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
1188 if (!precomp) {
1189 LOGVAL(LYE_INREGEX, line, LY_VLOG_NONE, NULL, value, err_ptr);
1190 free(value);
1191 return NULL;
1192 }
1193 free(precomp);
1194
1195 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1196 typ->type->info.str.pat_count++;
1197 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1198}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001199
1200void *
1201yang_read_range(struct lys_module *module, struct yang_type *typ, char *value, int line)
1202{
1203 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
1204 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1205 goto error;
1206 }
1207 typ->type->base = LY_TYPE_DEC64;
1208 if (typ->type->info.dec64.range) {
1209 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
1210 goto error;
1211 }
1212 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1213 if (!typ->type->info.dec64.range) {
1214 LOGMEM;
1215 goto error;
1216 }
1217 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1218 return typ->type->info.dec64.range;
1219
1220error:
1221 free(value);
1222 return NULL;
1223}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001224
1225int
1226yang_read_fraction(struct yang_type *typ, uint32_t value, int line)
1227{
1228 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1229 typ->type->base = LY_TYPE_DEC64;
1230 } else {
1231 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
1232 goto error;
1233 }
1234 if (typ->type->info.dec64.dig) {
1235 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1236 goto error;
1237 }
1238 /* range check */
1239 if (value < 1 || value > 18) {
1240 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
1241 goto error;
1242 }
1243 typ->type->info.dec64.dig = value;
1244 return EXIT_SUCCESS;
1245
1246error:
1247 return EXIT_FAILURE;
1248}
Pavol Vican79a763d2016-02-25 15:41:27 +01001249
1250void *
1251yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value, int line)
1252{
1253 struct lys_type_enum *enm;
1254 int i;
1255
1256 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1257 enm->name = lydict_insert_zc(module->ctx, value);
1258
1259 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1260 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
1261 LOGVAL(LYE_ENUM_WS, line, LY_VLOG_NONE, NULL, enm->name);
1262 goto error;
1263 }
1264
1265 /* check the name uniqueness */
1266 for (i = 0; i < typ->type->info.enums.count; i++) {
1267 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
1268 LOGVAL(LYE_ENUM_DUPNAME, line, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1269 goto error;
1270 }
1271 }
1272
1273 typ->type->info.enums.count++;
1274 return enm;
1275
1276error:
1277 typ->type->info.enums.count++;
1278 return NULL;
1279}
1280
1281int
1282yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign, int line)
1283{
1284 int i, j;
1285
1286 if (!assign) {
1287 /* assign value automatically */
1288 if (*value > INT32_MAX) {
1289 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1290 goto error;
1291 }
1292 enm->value = *value;
1293 enm->flags |= LYS_AUTOASSIGNED;
1294 (*value)++;
1295 }
1296
1297 /* check that the value is unique */
1298 j = typ->type->info.enums.count-1;
1299 for (i = 0; i < j; i++) {
1300 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
1301 LOGVAL(LYE_ENUM_DUPVAL, line, LY_VLOG_NONE, NULL,
1302 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1303 goto error;
1304 }
1305 }
1306
1307 return EXIT_SUCCESS;
1308
1309error:
1310 return EXIT_FAILURE;
1311}
Pavol Vican9887c682016-02-29 11:32:01 +01001312
1313void *
1314yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value, int line)
1315{
1316 int i;
1317 struct lys_type_bit *bit;
1318
1319 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
1320 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, line, NULL, NULL)) {
1321 LOGVAL(LYE_PATH, 0, LY_VLOG_NONE, NULL);
1322 free(value);
1323 goto error;
1324 }
1325 bit->name = lydict_insert_zc(module->ctx, value);
1326
1327 /* check the name uniqueness */
1328 for (i = 0; i < typ->type->info.bits.count; i++) {
1329 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
1330 LOGVAL(LYE_BITS_DUPNAME, line, LY_VLOG_NONE, NULL, bit->name);
1331 typ->type->info.bits.count++;
1332 goto error;
1333 }
1334 }
1335 typ->type->info.bits.count++;
1336 return bit;
1337
1338error:
1339 return NULL;
1340}
1341
1342int
1343yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign, int line)
1344{
1345 int i,j;
1346 struct lys_type_bit bit_tmp;
1347
1348 if (!assign) {
1349 /* assign value automatically */
1350 if (*value > UINT32_MAX) {
1351 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
1352 goto error;
1353 }
1354 bit->pos = (uint32_t)*value;
1355 bit->flags |= LYS_AUTOASSIGNED;
1356 (*value)++;
1357 }
1358
1359 j = typ->type->info.bits.count - 1;
1360 /* check that the value is unique */
1361 for (i = 0; i < j; i++) {
1362 if (typ->type->info.bits.bit[i].pos == bit->pos) {
1363 LOGVAL(LYE_BITS_DUPVAL, line, LY_VLOG_NONE, NULL, bit->pos, bit->name);
1364 goto error;
1365 }
1366 }
1367
1368 /* keep them ordered by position */
1369 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1370 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001371 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1372 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1373 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001374 j--;
1375 }
1376
1377 return EXIT_SUCCESS;
1378
1379error:
1380 return EXIT_FAILURE;
1381}
Pavol Vican0df02b02016-03-01 10:28:50 +01001382
1383void *
1384yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value, int line)
1385{
1386 struct lys_tpdf *ret;
1387
1388 if (lyp_check_identifier(value, LY_IDENT_TYPE, line, module, parent)) {
1389 free(value);
1390 return NULL;
1391 }
1392 if (!parent) {
1393 ret = &module->tpdf[module->tpdf_size];
1394 ret->type.parent = NULL;
1395 module->tpdf_size++;
1396 }
1397
1398 ret->name = lydict_insert_zc(module->ctx, value);
1399 ret->module = module;
1400 return ret;
1401}