blob: 02ca5bb6c3b2f3a4c36e195a31f787186972df92 [file] [log] [blame]
Radek Krejci19a96102018-11-15 13:38:09 +01001/**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include "common.h"
16
17#include <ctype.h>
18#include <dirent.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <linux/limits.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <sys/stat.h>
25#include <sys/types.h>
26#include <unistd.h>
27
28#include "libyang.h"
29#include "context.h"
30#include "tree_schema_internal.h"
31#include "xpath.h"
32
33/**
34 * @brief Duplicate string into dictionary
35 * @param[in] CTX libyang context of the dictionary.
36 * @param[in] ORIG String to duplicate.
37 * @param[out] DUP Where to store the result.
38 */
39#define DUP_STRING(CTX, ORIG, DUP) if (ORIG) {DUP = lydict_insert(CTX, ORIG, 0);}
40
41#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, OPTIONS, ITER, FUNC, RET, GOTO) \
42 if (ARRAY_P) { \
43 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_SIZE(ARRAY_P), RET, GOTO); \
44 for (ITER = 0; ITER < LY_ARRAY_SIZE(ARRAY_P); ++ITER) { \
45 LY_ARRAY_INCREMENT(ARRAY_C); \
46 RET = FUNC(CTX, &(ARRAY_P)[ITER], OPTIONS, &(ARRAY_C)[ITER]); \
47 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
48 } \
49 }
50
51#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, OPTIONS, FUNC, RET, GOTO) \
52 if (MEMBER_P) { \
53 MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
54 LY_CHECK_ERR_GOTO(!(MEMBER_C), LOGMEM((CTX)->ctx); RET = LY_EMEM, GOTO); \
55 RET = FUNC(CTX, MEMBER_P, OPTIONS, MEMBER_C); \
56 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
57 }
58
59const char* ly_data_type2str[LY_DATA_TYPE_COUNT] = {"unknown", "binary", "bits", "boolean", "decimal64", "empty", "enumeration",
60 "identityref", "instance-identifier", "leafref", "string", "union", "8bit integer", "8bit unsigned integer", "16bit integer",
61 "16bit unsigned integer", "32bit integer", "32bit unsigned integer", "64bit integer", "64bit unsigned integer"
62};
63
64static struct lysc_ext_instance *
65lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
66{
67 /* TODO */
68 (void) ctx;
69 (void) orig;
70 return NULL;
71}
72
73static struct lysc_pattern*
74lysc_pattern_dup(struct lysc_pattern *orig)
75{
76 ++orig->refcount;
77 return orig;
78}
79
80static struct lysc_pattern**
81lysc_patterns_dup(struct ly_ctx *ctx, struct lysc_pattern **orig)
82{
83 struct lysc_pattern **dup;
84 unsigned int u;
85
86 LY_ARRAY_CREATE_RET(ctx, dup, LY_ARRAY_SIZE(orig), NULL);
87 LY_ARRAY_FOR(orig, u) {
88 dup[u] = lysc_pattern_dup(orig[u]);
89 LY_ARRAY_INCREMENT(dup);
90 }
91 return dup;
92}
93
94struct lysc_range*
95lysc_range_dup(struct ly_ctx *ctx, const struct lysc_range *orig)
96{
97 struct lysc_range *dup;
98 LY_ERR ret;
99
100 dup = calloc(1, sizeof *dup);
101 LY_CHECK_ERR_RET(!dup, LOGMEM(ctx), NULL);
102 if (orig->parts) {
103 LY_ARRAY_CREATE_GOTO(ctx, dup->parts, LY_ARRAY_SIZE(orig->parts), ret, cleanup);
104 LY_ARRAY_SIZE(dup->parts) = LY_ARRAY_SIZE(orig->parts);
105 memcpy(dup->parts, orig->parts, LY_ARRAY_SIZE(dup->parts) * sizeof *dup->parts);
106 }
107 DUP_STRING(ctx, orig->eapptag, dup->eapptag);
108 DUP_STRING(ctx, orig->emsg, dup->emsg);
109 dup->exts = lysc_ext_instance_dup(ctx, orig->exts);
110
111 return dup;
112cleanup:
113 free(dup);
114 (void) ret; /* set but not used due to the return type */
115 return NULL;
116}
117
118struct iff_stack {
119 int size;
120 int index; /* first empty item */
121 uint8_t *stack;
122};
123
124static LY_ERR
125iff_stack_push(struct iff_stack *stack, uint8_t value)
126{
127 if (stack->index == stack->size) {
128 stack->size += 4;
129 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
130 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
131 }
132 stack->stack[stack->index++] = value;
133 return LY_SUCCESS;
134}
135
136static uint8_t
137iff_stack_pop(struct iff_stack *stack)
138{
139 stack->index--;
140 return stack->stack[stack->index];
141}
142
143static void
144iff_stack_clean(struct iff_stack *stack)
145{
146 stack->size = 0;
147 free(stack->stack);
148}
149
150static void
151iff_setop(uint8_t *list, uint8_t op, int pos)
152{
153 uint8_t *item;
154 uint8_t mask = 3;
155
156 assert(pos >= 0);
157 assert(op <= 3); /* max 2 bits */
158
159 item = &list[pos / 4];
160 mask = mask << 2 * (pos % 4);
161 *item = (*item) & ~mask;
162 *item = (*item) | (op << 2 * (pos % 4));
163}
164
165#define LYS_IFF_LP 0x04 /* ( */
166#define LYS_IFF_RP 0x08 /* ) */
167
168static struct lysc_feature *
169lysc_feature_find(struct lysc_module *mod, const char *name, size_t len)
170{
171 size_t i;
172 struct lysc_feature *f;
173
174 for (i = 0; i < len; ++i) {
175 if (name[i] == ':') {
176 /* we have a prefixed feature */
177 mod = lysc_module_find_prefix(mod, name, i);
178 LY_CHECK_RET(!mod, NULL);
179
180 name = &name[i + 1];
181 len = len - i - 1;
182 }
183 }
184
185 /* we have the correct module, get the feature */
186 LY_ARRAY_FOR(mod->features, i) {
187 f = &mod->features[i];
188 if (!strncmp(f->name, name, len) && f->name[len] == '\0') {
189 return f;
190 }
191 }
192
193 return NULL;
194}
195
196static LY_ERR
197lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, int UNUSED(options), struct lysc_ext_instance *ext)
198{
199 const char *name;
200 unsigned int u;
201 const struct lys_module *mod;
202 struct lysp_ext *edef = NULL;
203
204 DUP_STRING(ctx->ctx, ext_p->argument, ext->argument);
205 ext->insubstmt = ext_p->insubstmt;
206 ext->insubstmt_index = ext_p->insubstmt_index;
207
208 /* get module where the extension definition should be placed */
209 for (u = 0; ext_p->name[u] != ':'; ++u);
210 mod = lys_module_find_prefix(ctx->mod, ext_p->name, u);
211 LY_CHECK_ERR_RET(!mod, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
212 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, ext_p->name),
213 LY_EVALID);
214 LY_CHECK_ERR_RET(!mod->parsed->extensions,
215 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
216 "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
217 ext_p->name, mod->parsed->name),
218 LY_EVALID);
219 name = &ext_p->name[u + 1];
220 /* find the extension definition there */
221 for (ext = NULL, u = 0; u < LY_ARRAY_SIZE(mod->parsed->extensions); ++u) {
222 if (!strcmp(name, mod->parsed->extensions[u].name)) {
223 edef = &mod->parsed->extensions[u];
224 break;
225 }
226 }
227 LY_CHECK_ERR_RET(!edef, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
228 "Extension definition of extension instance \"%s\" not found.", ext_p->name),
229 LY_EVALID);
230 /* TODO plugins */
231
232 return LY_SUCCESS;
233}
234
235static LY_ERR
236lys_compile_iffeature(struct lysc_ctx *ctx, const char **value, int UNUSED(options), struct lysc_iffeature *iff)
237{
238 const char *c = *value;
239 int r, rc = EXIT_FAILURE;
240 int i, j, last_not, checkversion = 0;
241 unsigned int f_size = 0, expr_size = 0, f_exp = 1;
242 uint8_t op;
243 struct iff_stack stack = {0, 0, NULL};
244 struct lysc_feature *f;
245
246 assert(c);
247
248 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
249 for (i = j = last_not = 0; c[i]; i++) {
250 if (c[i] == '(') {
251 j++;
252 checkversion = 1;
253 continue;
254 } else if (c[i] == ')') {
255 j--;
256 continue;
257 } else if (isspace(c[i])) {
258 checkversion = 1;
259 continue;
260 }
261
262 if (!strncmp(&c[i], "not", r = 3) || !strncmp(&c[i], "and", r = 3) || !strncmp(&c[i], "or", r = 2)) {
263 if (c[i + r] == '\0') {
264 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
265 "Invalid value \"%s\" of if-feature - unexpected end of expression.", *value);
266 return LY_EVALID;
267 } else if (!isspace(c[i + r])) {
268 /* feature name starting with the not/and/or */
269 last_not = 0;
270 f_size++;
271 } else if (c[i] == 'n') { /* not operation */
272 if (last_not) {
273 /* double not */
274 expr_size = expr_size - 2;
275 last_not = 0;
276 } else {
277 last_not = 1;
278 }
279 } else { /* and, or */
280 f_exp++;
281 /* not a not operation */
282 last_not = 0;
283 }
284 i += r;
285 } else {
286 f_size++;
287 last_not = 0;
288 }
289 expr_size++;
290
291 while (!isspace(c[i])) {
292 if (!c[i] || c[i] == ')') {
293 i--;
294 break;
295 }
296 i++;
297 }
298 }
299 if (j || f_exp != f_size) {
300 /* not matching count of ( and ) */
301 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
302 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", *value);
303 return LY_EVALID;
304 }
305
306 if (checkversion || expr_size > 1) {
307 /* check that we have 1.1 module */
308 if (ctx->mod->compiled->version != LYS_VERSION_1_1) {
309 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
310 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", *value);
311 return LY_EVALID;
312 }
313 }
314
315 /* allocate the memory */
316 LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
317 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
318 stack.stack = malloc(expr_size * sizeof *stack.stack);
319 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx), error);
320
321 stack.size = expr_size;
322 f_size--; expr_size--; /* used as indexes from now */
323
324 for (i--; i >= 0; i--) {
325 if (c[i] == ')') {
326 /* push it on stack */
327 iff_stack_push(&stack, LYS_IFF_RP);
328 continue;
329 } else if (c[i] == '(') {
330 /* pop from the stack into result all operators until ) */
331 while((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
332 iff_setop(iff->expr, op, expr_size--);
333 }
334 continue;
335 } else if (isspace(c[i])) {
336 continue;
337 }
338
339 /* end of operator or operand -> find beginning and get what is it */
340 j = i + 1;
341 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
342 i--;
343 }
344 i++; /* go back by one step */
345
346 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
347 if (stack.index && stack.stack[stack.index - 1] == LYS_IFF_NOT) {
348 /* double not */
349 iff_stack_pop(&stack);
350 } else {
351 /* not has the highest priority, so do not pop from the stack
352 * as in case of AND and OR */
353 iff_stack_push(&stack, LYS_IFF_NOT);
354 }
355 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
356 /* as for OR - pop from the stack all operators with the same or higher
357 * priority and store them to the result, then push the AND to the stack */
358 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
359 op = iff_stack_pop(&stack);
360 iff_setop(iff->expr, op, expr_size--);
361 }
362 iff_stack_push(&stack, LYS_IFF_AND);
363 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
364 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
365 op = iff_stack_pop(&stack);
366 iff_setop(iff->expr, op, expr_size--);
367 }
368 iff_stack_push(&stack, LYS_IFF_OR);
369 } else {
370 /* feature name, length is j - i */
371
372 /* add it to the expression */
373 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
374
375 /* now get the link to the feature definition */
376 f = lysc_feature_find(ctx->mod->compiled, &c[i], j - i);
377 LY_CHECK_ERR_GOTO(!f,
378 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
379 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", *value, j - i, &c[i]);
380 rc = LY_EVALID,
381 error)
382 iff->features[f_size] = f;
383 LY_ARRAY_INCREMENT(iff->features);
384 f_size--;
385 }
386 }
387 while (stack.index) {
388 op = iff_stack_pop(&stack);
389 iff_setop(iff->expr, op, expr_size--);
390 }
391
392 if (++expr_size || ++f_size) {
393 /* not all expected operators and operands found */
394 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
395 "Invalid value \"%s\" of if-feature - processing error.", *value);
396 rc = LY_EINT;
397 } else {
398 rc = LY_SUCCESS;
399 }
400
401error:
402 /* cleanup */
403 iff_stack_clean(&stack);
404
405 return rc;
406}
407
408static LY_ERR
409lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, int options, struct lysc_when *when)
410{
411 unsigned int u;
412 LY_ERR ret = LY_SUCCESS;
413
414 when->cond = lyxp_expr_parse(ctx->ctx, when_p->cond);
415 LY_CHECK_ERR_GOTO(!when->cond, ret = ly_errcode(ctx->ctx), done);
416 COMPILE_ARRAY_GOTO(ctx, when_p->exts, when->exts, options, u, lys_compile_ext, ret, done);
417
418done:
419 return ret;
420}
421
422static LY_ERR
423lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, int options, struct lysc_must *must)
424{
425 unsigned int u;
426 LY_ERR ret = LY_SUCCESS;
427
428 must->cond = lyxp_expr_parse(ctx->ctx, must_p->arg);
429 LY_CHECK_ERR_GOTO(!must->cond, ret = ly_errcode(ctx->ctx), done);
430
431 DUP_STRING(ctx->ctx, must_p->eapptag, must->eapptag);
432 DUP_STRING(ctx->ctx, must_p->emsg, must->emsg);
433 COMPILE_ARRAY_GOTO(ctx, must_p->exts, must->exts, options, u, lys_compile_ext, ret, done);
434
435done:
436 return ret;
437}
438
439static LY_ERR
440lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p, int options, struct lysc_import *imp)
441{
442 unsigned int u;
443 struct lys_module *mod = NULL;
444 struct lysc_module *comp;
445 LY_ERR ret = LY_SUCCESS;
446
447 DUP_STRING(ctx->ctx, imp_p->prefix, imp->prefix);
448 COMPILE_ARRAY_GOTO(ctx, imp_p->exts, imp->exts, options, u, lys_compile_ext, ret, done);
449 imp->module = imp_p->module;
450
451 /* make sure that we have both versions (lysp_ and lysc_) of the imported module. To import groupings or
452 * typedefs, the lysp_ is needed. To augment or deviate imported module, we need the lysc_ structure */
453 if (!imp->module->parsed) {
454 comp = imp->module->compiled;
455 /* try to get filepath from the compiled version */
456 if (comp->filepath) {
457 mod = (struct lys_module*)lys_parse_path(ctx->ctx, comp->filepath,
458 !strcmp(&comp->filepath[strlen(comp->filepath - 4)], ".yin") ? LYS_IN_YIN : LYS_IN_YANG);
459 if (mod != imp->module) {
460 LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
461 comp->filepath, comp->name);
462 mod = NULL;
463 }
464 }
465 if (!mod) {
466 if (lysp_load_module(ctx->ctx, comp->name, comp->revision, 0, 1, &mod)) {
467 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
468 comp->name, ctx->mod->compiled->name);
469 return LY_ENOTFOUND;
470 }
471 }
472 } else if (!imp->module->compiled) {
473 return lys_compile(imp->module, options);
474 }
475
476done:
477 return ret;
478}
479
480static LY_ERR
481lys_compile_identity(struct lysc_ctx *ctx, struct lysp_ident *ident_p, int options, struct lysc_ident *ident)
482{
483 unsigned int u;
484 LY_ERR ret = LY_SUCCESS;
485
486 DUP_STRING(ctx->ctx, ident_p->name, ident->name);
487 COMPILE_ARRAY_GOTO(ctx, ident_p->iffeatures, ident->iffeatures, options, u, lys_compile_iffeature, ret, done);
488 /* backlings (derived) can be added no sooner than when all the identities in the current module are present */
489 COMPILE_ARRAY_GOTO(ctx, ident_p->exts, ident->exts, options, u, lys_compile_ext, ret, done);
490 ident->flags = ident_p->flags;
491
492done:
493 return ret;
494}
495
Radek Krejcia3045382018-11-22 14:30:31 +0100496/**
497 * @brief Find and process the referenced base identities from another identity or identityref
498 *
499 * For bases in identity se backlinks to them from the base identities. For identityref, store
500 * the array of pointers to the base identities. So one of the ident or bases parameter must be set
501 * to distinguish these two use cases.
502 *
503 * @param[in] ctx Compile context, not only for logging but also to get the current module to resolve prefixes.
504 * @param[in] bases_p Array of names (including prefix if necessary) of base identities.
505 * @param[in] ident Referencing identity to work with.
506 * @param[in] bases Array of bases of identityref to fill in.
507 * @return LY_ERR value.
508 */
Radek Krejci19a96102018-11-15 13:38:09 +0100509static LY_ERR
Radek Krejci555cb5b2018-11-16 14:54:33 +0100510lys_compile_identity_bases(struct lysc_ctx *ctx, const char **bases_p, struct lysc_ident *ident, struct lysc_ident ***bases)
Radek Krejci19a96102018-11-15 13:38:09 +0100511{
Radek Krejci555cb5b2018-11-16 14:54:33 +0100512 unsigned int u, v;
Radek Krejci19a96102018-11-15 13:38:09 +0100513 const char *s, *name;
514 struct lysc_module *mod;
Radek Krejci555cb5b2018-11-16 14:54:33 +0100515 struct lysc_ident **idref;
516
517 assert(ident || bases);
518
519 if (LY_ARRAY_SIZE(bases_p) > 1 && ctx->mod->compiled->version < 2) {
520 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
521 "Multiple bases in %s are allowed only in YANG 1.1 modules.", ident ? "identity" : "identityref type");
522 return LY_EVALID;
523 }
524
525 for (u = 0; u < LY_ARRAY_SIZE(bases_p); ++u) {
526 s = strchr(bases_p[u], ':');
527 if (s) {
528 /* prefixed identity */
529 name = &s[1];
530 mod = lysc_module_find_prefix(ctx->mod->compiled, bases_p[u], s - bases_p[u]);
531 } else {
532 name = bases_p[u];
533 mod = ctx->mod->compiled;
534 }
535 if (!mod) {
536 if (ident) {
537 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
538 "Invalid prefix used for base (%s) of identity \"%s\".", bases_p[u], ident->name);
539 } else {
540 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
541 "Invalid prefix used for base (%s) of identityref.", bases_p[u]);
542 }
543 return LY_EVALID;
544 }
545 idref = NULL;
546 if (mod->identities) {
547 for (v = 0; v < LY_ARRAY_SIZE(mod->identities); ++v) {
548 if (!strcmp(name, mod->identities[v].name)) {
549 if (ident) {
550 /* we have match! store the backlink */
551 LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, idref, LY_EMEM);
552 *idref = ident;
553 } else {
554 /* we have match! store the found identity */
555 LY_ARRAY_NEW_RET(ctx->ctx, *bases, idref, LY_EMEM);
556 *idref = &mod->identities[v];
557 }
558 break;
559 }
560 }
561 }
562 if (!idref || !(*idref)) {
563 if (ident) {
564 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
565 "Unable to find base (%s) of identity \"%s\".", bases_p[u], ident->name);
566 } else {
567 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
568 "Unable to find base (%s) of identityref.", bases_p[u]);
569 }
570 return LY_EVALID;
571 }
572 }
573 return LY_SUCCESS;
574}
575
Radek Krejcia3045382018-11-22 14:30:31 +0100576/**
577 * @brief For the given array of identities, set the backlinks from all their base identities.
578 * @param[in] ctx Compile context, not only for logging but also to get the current module to resolve prefixes.
579 * @param[in] idents_p Array of identities definitions from the parsed schema structure.
580 * @param[in] idents Array of referencing identities to which the backlinks are supposed to be set.
581 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
582 */
Radek Krejci555cb5b2018-11-16 14:54:33 +0100583static LY_ERR
584lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
585{
586 unsigned int i;
Radek Krejci19a96102018-11-15 13:38:09 +0100587
588 for (i = 0; i < LY_ARRAY_SIZE(idents_p); ++i) {
589 if (!idents_p[i].bases) {
590 continue;
591 }
Radek Krejci555cb5b2018-11-16 14:54:33 +0100592 LY_CHECK_RET(lys_compile_identity_bases(ctx, idents_p[i].bases, &idents[i], NULL));
Radek Krejci19a96102018-11-15 13:38:09 +0100593 }
594 return LY_SUCCESS;
595}
596
Radek Krejcia3045382018-11-22 14:30:31 +0100597/**
598 * @brief Create compiled feature structure.
599 * @param[in] ctx Compile context.
600 * @param[in] feature_p Parsed feature definition to compile.
601 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
602 * @param[in,out] feature Compiled feature structure to fill.
603 * @return LY_ERR value.
604 */
Radek Krejci19a96102018-11-15 13:38:09 +0100605static LY_ERR
606lys_compile_feature(struct lysc_ctx *ctx, struct lysp_feature *feature_p, int options, struct lysc_feature *feature)
607{
608 unsigned int u, v;
609 LY_ERR ret = LY_SUCCESS;
610 struct lysc_feature **df;
611
612 DUP_STRING(ctx->ctx, feature_p->name, feature->name);
613 feature->flags = feature_p->flags;
614
615 COMPILE_ARRAY_GOTO(ctx, feature_p->exts, feature->exts, options, u, lys_compile_ext, ret, done);
616 COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, options, u, lys_compile_iffeature, ret, done);
617 if (feature->iffeatures) {
618 for (u = 0; u < LY_ARRAY_SIZE(feature->iffeatures); ++u) {
619 if (feature->iffeatures[u].features) {
620 for (v = 0; v < LY_ARRAY_SIZE(feature->iffeatures[u].features); ++v) {
621 /* add itself into the dependants list */
622 LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
623 *df = feature;
624 }
625 /* TODO check for circular dependency */
626 }
627 }
628 }
629done:
630 return ret;
631}
632
Radek Krejcia3045382018-11-22 14:30:31 +0100633/**
634 * @brief Validate and normalize numeric value from a range definition.
635 * @param[in] ctx Compile context.
636 * @param[in] basetype Base YANG built-in type of the node connected with the range restriction. Actually only LY_TYPE_DEC64 is important to
637 * allow processing of the fractions. The fraction point is extracted from the value which is then normalize according to given frdigits into
638 * valcopy to allow easy parsing and storing of the value. libyang stores decimal number without the decimal point which is always recovered from
639 * the known fraction-digits value. So, with fraction-digits 2, number 3.14 is stored as 314 and number 1 is stored as 100.
640 * @param[in] frdigits The fraction-digits of the type in case of LY_TYPE_DEC64.
641 * @param[in] value String value of the range boundary.
642 * @param[out] len Number of the processed bytes from the value. Processing stops on the first character which is not part of the number boundary.
643 * @param[out] valcopy NULL-terminated string with the numeric value to parse and store.
644 * @return LY_ERR value - LY_SUCCESS, LY_EMEM, LY_EVALID (no number) or LY_EINVAL (decimal64 not matching fraction-digits value).
645 */
Radek Krejci19a96102018-11-15 13:38:09 +0100646static LY_ERR
Radek Krejci6cba4292018-11-15 17:33:29 +0100647range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, uint8_t frdigits, const char *value, size_t *len, char **valcopy)
Radek Krejci19a96102018-11-15 13:38:09 +0100648{
Radek Krejci6cba4292018-11-15 17:33:29 +0100649 size_t fraction = 0, size;
650
Radek Krejci19a96102018-11-15 13:38:09 +0100651 *len = 0;
652
653 assert(value);
654 /* parse value */
655 if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
656 return LY_EVALID;
657 }
658
659 if ((value[*len] == '-') || (value[*len] == '+')) {
660 ++(*len);
661 }
662
663 while (isdigit(value[*len])) {
664 ++(*len);
665 }
666
667 if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
Radek Krejci6cba4292018-11-15 17:33:29 +0100668 if (basetype == LY_TYPE_DEC64) {
669 goto decimal;
670 } else {
671 *valcopy = strndup(value, *len);
672 return LY_SUCCESS;
673 }
Radek Krejci19a96102018-11-15 13:38:09 +0100674 }
675 fraction = *len;
676
677 ++(*len);
678 while (isdigit(value[*len])) {
679 ++(*len);
680 }
681
Radek Krejci6cba4292018-11-15 17:33:29 +0100682 if (basetype == LY_TYPE_DEC64) {
683decimal:
684 assert(frdigits);
685 if (*len - 1 - fraction > frdigits) {
686 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
687 "Range boundary \"%.*s\" of decimal64 type exceeds defined number (%u) of fraction digits.",
688 *len, value, frdigits);
689 return LY_EINVAL;
690 }
691 if (fraction) {
692 size = (*len) + (frdigits - ((*len) - 1 - fraction));
693 } else {
694 size = (*len) + frdigits + 1;
695 }
696 *valcopy = malloc(size * sizeof **valcopy);
Radek Krejci19a96102018-11-15 13:38:09 +0100697 LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
698
Radek Krejci6cba4292018-11-15 17:33:29 +0100699 (*valcopy)[size - 1] = '\0';
700 if (fraction) {
701 memcpy(&(*valcopy)[0], &value[0], fraction);
702 memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction));
703 memset(&(*valcopy)[(*len) - 1], '0', frdigits - ((*len) - 1 - fraction));
704 } else {
705 memcpy(&(*valcopy)[0], &value[0], *len);
706 memset(&(*valcopy)[*len], '0', frdigits);
707 }
Radek Krejci19a96102018-11-15 13:38:09 +0100708 }
709 return LY_SUCCESS;
710}
711
Radek Krejcia3045382018-11-22 14:30:31 +0100712/**
713 * @brief Check that values in range are in ascendant order.
714 * @param[in] unsigned_value Flag to note that we are working with unsigned values.
715 * @param[in] value Current value to check.
716 * @param[in] prev_value The last seen value.
717 * @return LY_SUCCESS or LY_EEXIST for invalid order.
718 */
Radek Krejci19a96102018-11-15 13:38:09 +0100719static LY_ERR
Radek Krejcia3045382018-11-22 14:30:31 +0100720range_part_check_ascendancy(int unsigned_value, int64_t value, int64_t prev_value)
Radek Krejci19a96102018-11-15 13:38:09 +0100721{
722 if (unsigned_value) {
723 if ((uint64_t)prev_value >= (uint64_t)value) {
724 return LY_EEXIST;
725 }
726 } else {
727 if (prev_value >= value) {
728 return LY_EEXIST;
729 }
730 }
731 return LY_SUCCESS;
732}
733
Radek Krejcia3045382018-11-22 14:30:31 +0100734/**
735 * @brief Set min/max value of the range part.
736 * @param[in] ctx Compile context.
737 * @param[in] part Range part structure to fill.
738 * @param[in] max Flag to distinguish if storing min or max value.
739 * @param[in] prev The last seen value to check that all values in range are specified in ascendant order.
740 * @param[in] basetype Type of the value to get know implicit min/max values and other checking rules.
741 * @param[in] first Flag for the first value of the range to avoid ascendancy order.
742 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
743 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
744 * @param[in,out] value Numeric range value to be stored, if not provided the type's min/max value is set.
745 * @return LY_ERR value - LY_SUCCESS, LY_EDENIED (value brokes type's boundaries), LY_EVALID (not a number),
746 * LY_EEXIST (value is smaller than the previous one), LY_EINVAL (decimal64 value does not corresponds with the
747 * frdigits value), LY_EMEM.
748 */
Radek Krejci19a96102018-11-15 13:38:09 +0100749static LY_ERR
750range_part_minmax(struct lysc_ctx *ctx, struct lysc_range_part *part, int max, int64_t prev, LY_DATA_TYPE basetype, int first, int length_restr,
Radek Krejci6cba4292018-11-15 17:33:29 +0100751 uint8_t frdigits, const char **value)
Radek Krejci19a96102018-11-15 13:38:09 +0100752{
753 LY_ERR ret = LY_SUCCESS;
754 char *valcopy = NULL;
755 size_t len;
756
757 if (value) {
Radek Krejci6cba4292018-11-15 17:33:29 +0100758 ret = range_part_check_value_syntax(ctx, basetype, frdigits, *value, &len, &valcopy);
Radek Krejci19a96102018-11-15 13:38:09 +0100759 LY_CHECK_GOTO(ret, error);
760 }
761
762 switch (basetype) {
763 case LY_TYPE_BINARY: /* length */
764 if (valcopy) {
765 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
766 } else if (max) {
767 part->max_u64 = UINT64_C(18446744073709551615);
768 } else {
769 part->min_u64 = UINT64_C(0);
770 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100771 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100772 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100773 }
774 break;
775 case LY_TYPE_DEC64: /* range */
776 if (valcopy) {
777 ret = ly_parse_int(valcopy, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
778 max ? &part->max_64 : &part->min_64);
779 } else if (max) {
780 part->max_64 = INT64_C(9223372036854775807);
781 } else {
782 part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
783 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100784 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100785 ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100786 }
787 break;
788 case LY_TYPE_INT8: /* range */
789 if (valcopy) {
790 ret = ly_parse_int(valcopy, INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
791 } else if (max) {
792 part->max_64 = INT64_C(127);
793 } else {
794 part->min_64 = INT64_C(-128);
795 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100796 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100797 ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100798 }
799 break;
800 case LY_TYPE_INT16: /* range */
801 if (valcopy) {
802 ret = ly_parse_int(valcopy, INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
803 } else if (max) {
804 part->max_64 = INT64_C(32767);
805 } else {
806 part->min_64 = INT64_C(-32768);
807 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100808 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100809 ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100810 }
811 break;
812 case LY_TYPE_INT32: /* range */
813 if (valcopy) {
814 ret = ly_parse_int(valcopy, INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
815 } else if (max) {
816 part->max_64 = INT64_C(2147483647);
817 } else {
818 part->min_64 = INT64_C(-2147483648);
819 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100820 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100821 ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100822 }
823 break;
824 case LY_TYPE_INT64: /* range */
825 if (valcopy) {
826 ret = ly_parse_int(valcopy, INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
827 max ? &part->max_64 : &part->min_64);
828 } else if (max) {
829 part->max_64 = INT64_C(9223372036854775807);
830 } else {
831 part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
832 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100833 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100834 ret = range_part_check_ascendancy(0, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100835 }
836 break;
837 case LY_TYPE_UINT8: /* range */
838 if (valcopy) {
839 ret = ly_parse_uint(valcopy, UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
840 } else if (max) {
841 part->max_u64 = UINT64_C(255);
842 } else {
843 part->min_u64 = UINT64_C(0);
844 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100845 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100846 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100847 }
848 break;
849 case LY_TYPE_UINT16: /* range */
850 if (valcopy) {
851 ret = ly_parse_uint(valcopy, UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
852 } else if (max) {
853 part->max_u64 = UINT64_C(65535);
854 } else {
855 part->min_u64 = UINT64_C(0);
856 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100857 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100858 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100859 }
860 break;
861 case LY_TYPE_UINT32: /* range */
862 if (valcopy) {
863 ret = ly_parse_uint(valcopy, UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
864 } else if (max) {
865 part->max_u64 = UINT64_C(4294967295);
866 } else {
867 part->min_u64 = UINT64_C(0);
868 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100869 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100870 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100871 }
872 break;
873 case LY_TYPE_UINT64: /* range */
874 if (valcopy) {
875 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
876 } else if (max) {
877 part->max_u64 = UINT64_C(18446744073709551615);
878 } else {
879 part->min_u64 = UINT64_C(0);
880 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100881 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100882 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100883 }
884 break;
885 case LY_TYPE_STRING: /* length */
886 if (valcopy) {
887 ret = ly_parse_uint(valcopy, UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
888 } else if (max) {
889 part->max_u64 = UINT64_C(18446744073709551615);
890 } else {
891 part->min_u64 = UINT64_C(0);
892 }
Radek Krejci6cba4292018-11-15 17:33:29 +0100893 if (!ret && !first) {
Radek Krejcia3045382018-11-22 14:30:31 +0100894 ret = range_part_check_ascendancy(1, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +0100895 }
896 break;
897 default:
898 LOGINT(ctx->ctx);
899 ret = LY_EINT;
900 }
901
902error:
903 if (ret == LY_EDENIED) {
904 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
905 "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
906 length_restr ? "length" : "range", valcopy ? valcopy : *value);
907 } else if (ret == LY_EVALID) {
908 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
909 "Invalid %s restriction - invalid value \"%s\".",
910 length_restr ? "length" : "range", valcopy ? valcopy : *value);
911 } else if (ret == LY_EEXIST) {
912 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
913 "Invalid %s restriction - values are not in ascending order (%s).",
Radek Krejci6cba4292018-11-15 17:33:29 +0100914 length_restr ? "length" : "range",
915 (valcopy && basetype != LY_TYPE_DEC64) ? valcopy : *value);
Radek Krejci19a96102018-11-15 13:38:09 +0100916 } else if (!ret && value) {
917 *value = *value + len;
918 }
919 free(valcopy);
920 return ret;
921}
922
Radek Krejcia3045382018-11-22 14:30:31 +0100923/**
924 * @brief Compile the parsed range restriction.
925 * @param[in] ctx Compile context.
926 * @param[in] range_p Parsed range structure to compile.
927 * @param[in] basetype Base YANG built-in type of the node with the range restriction.
928 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
929 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
930 * @param[in] base_range Range restriction of the type from which the current type is derived. The current
931 * range restriction must be more restrictive than the base_range.
932 * @param[in,out] range Pointer to the created current range structure.
933 * @return LY_ERR value.
934 */
Radek Krejci19a96102018-11-15 13:38:09 +0100935static LY_ERR
Radek Krejci6cba4292018-11-15 17:33:29 +0100936lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, int length_restr, uint8_t frdigits,
Radek Krejci19a96102018-11-15 13:38:09 +0100937 struct lysc_range *base_range, struct lysc_range **range)
938{
939 LY_ERR ret = LY_EVALID;
940 const char *expr;
941 struct lysc_range_part *parts = NULL, *part;
942 int range_expected = 0, uns;
943 unsigned int parts_done = 0, u, v;
944
945 assert(range);
946 assert(range_p);
947
948 expr = range_p->arg;
949 while(1) {
950 if (isspace(*expr)) {
951 ++expr;
952 } else if (*expr == '\0') {
953 if (range_expected) {
954 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
955 "Invalid %s restriction - unexpected end of the expression after \"..\" (%s).",
956 length_restr ? "length" : "range", range_p->arg);
957 goto cleanup;
958 } else if (!parts || parts_done == LY_ARRAY_SIZE(parts)) {
959 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
960 "Invalid %s restriction - unexpected end of the expression (%s).",
961 length_restr ? "length" : "range", range_p->arg);
962 goto cleanup;
963 }
964 parts_done++;
965 break;
966 } else if (!strncmp(expr, "min", 3)) {
967 if (parts) {
968 /* min cannot be used elsewhere than in the first part */
969 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
970 "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
971 expr - range_p->arg, range_p->arg);
972 goto cleanup;
973 }
974 expr += 3;
975
976 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
Radek Krejci6cba4292018-11-15 17:33:29 +0100977 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, frdigits, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +0100978 part->max_64 = part->min_64;
979 } else if (*expr == '|') {
980 if (!parts || range_expected) {
981 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
982 "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
983 goto cleanup;
984 }
985 expr++;
986 parts_done++;
987 /* process next part of the expression */
988 } else if (!strncmp(expr, "..", 2)) {
989 expr += 2;
990 while (isspace(*expr)) {
991 expr++;
992 }
993 if (!parts || LY_ARRAY_SIZE(parts) == parts_done) {
994 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
995 "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
996 goto cleanup;
997 }
998 /* continue expecting the upper boundary */
999 range_expected = 1;
1000 } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
1001 /* number */
1002 if (range_expected) {
1003 part = &parts[LY_ARRAY_SIZE(parts) - 1];
Radek Krejci6cba4292018-11-15 17:33:29 +01001004 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, &expr), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001005 range_expected = 0;
1006 } else {
1007 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1008 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
Radek Krejci6cba4292018-11-15 17:33:29 +01001009 basetype, parts_done ? 0 : 1, length_restr, frdigits, &expr), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001010 part->max_64 = part->min_64;
1011 }
1012
1013 /* continue with possible another expression part */
1014 } else if (!strncmp(expr, "max", 3)) {
1015 expr += 3;
1016 while (isspace(*expr)) {
1017 expr++;
1018 }
1019 if (*expr != '\0') {
1020 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
1021 length_restr ? "length" : "range", expr);
1022 goto cleanup;
1023 }
1024 if (range_expected) {
1025 part = &parts[LY_ARRAY_SIZE(parts) - 1];
Radek Krejci6cba4292018-11-15 17:33:29 +01001026 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001027 range_expected = 0;
1028 } else {
1029 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
1030 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_SIZE(parts) - 2].max_64 : 0,
Radek Krejci6cba4292018-11-15 17:33:29 +01001031 basetype, parts_done ? 0 : 1, length_restr, frdigits, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001032 part->min_64 = part->max_64;
1033 }
1034 } else {
1035 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
1036 length_restr ? "length" : "range", expr);
1037 goto cleanup;
1038 }
1039 }
1040
1041 /* check with the previous range/length restriction */
1042 if (base_range) {
1043 switch (basetype) {
1044 case LY_TYPE_BINARY:
1045 case LY_TYPE_UINT8:
1046 case LY_TYPE_UINT16:
1047 case LY_TYPE_UINT32:
1048 case LY_TYPE_UINT64:
1049 case LY_TYPE_STRING:
1050 uns = 1;
1051 break;
1052 case LY_TYPE_DEC64:
1053 case LY_TYPE_INT8:
1054 case LY_TYPE_INT16:
1055 case LY_TYPE_INT32:
1056 case LY_TYPE_INT64:
1057 uns = 0;
1058 break;
1059 default:
1060 LOGINT(ctx->ctx);
1061 ret = LY_EINT;
1062 goto cleanup;
1063 }
1064 for (u = v = 0; u < parts_done && v < LY_ARRAY_SIZE(base_range->parts); ++u) {
1065 if ((uns && parts[u].min_u64 < base_range->parts[v].min_u64) || (!uns && parts[u].min_64 < base_range->parts[v].min_64)) {
1066 goto baseerror;
1067 }
1068 /* current lower bound is not lower than the base */
1069 if (base_range->parts[v].min_64 == base_range->parts[v].max_64) {
1070 /* base has single value */
1071 if (base_range->parts[v].min_64 == parts[u].min_64) {
1072 /* both lower bounds are the same */
1073 if (parts[u].min_64 != parts[u].max_64) {
1074 /* current continues with a range */
1075 goto baseerror;
1076 } else {
1077 /* equal single values, move both forward */
1078 ++v;
1079 continue;
1080 }
1081 } else {
1082 /* base is single value lower than current range, so the
1083 * value from base range is removed in the current,
1084 * move only base and repeat checking */
1085 ++v;
1086 --u;
1087 continue;
1088 }
1089 } else {
1090 /* base is the range */
1091 if (parts[u].min_64 == parts[u].max_64) {
1092 /* current is a single value */
1093 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1094 /* current is behind the base range, so base range is omitted,
1095 * move the base and keep the current for further check */
1096 ++v;
1097 --u;
1098 } /* else it is within the base range, so move the current, but keep the base */
1099 continue;
1100 } else {
1101 /* both are ranges - check the higher bound, the lower was already checked */
1102 if ((uns && parts[u].max_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].max_64 > base_range->parts[v].max_64)) {
1103 /* higher bound is higher than the current higher bound */
1104 if ((uns && parts[u].min_u64 > base_range->parts[v].max_u64) || (!uns && parts[u].min_64 > base_range->parts[v].max_64)) {
1105 /* but the current lower bound is also higher, so the base range is omitted,
1106 * continue with the same current, but move the base */
1107 --u;
1108 ++v;
1109 continue;
1110 }
1111 /* current range starts within the base range but end behind it */
1112 goto baseerror;
1113 } else {
1114 /* current range is smaller than the base,
1115 * move current, but stay with the base */
1116 continue;
1117 }
1118 }
1119 }
1120 }
1121 if (u != parts_done) {
1122baseerror:
1123 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1124 "Invalid %s restriction - the derived restriction (%s) is not equally or more limiting.",
1125 length_restr ? "length" : "range", range_p->arg);
1126 goto cleanup;
1127 }
1128 }
1129
1130 if (!(*range)) {
1131 *range = calloc(1, sizeof **range);
1132 LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
1133 }
1134
1135 if (range_p->eapptag) {
1136 lydict_remove(ctx->ctx, (*range)->eapptag);
1137 (*range)->eapptag = lydict_insert(ctx->ctx, range_p->eapptag, 0);
1138 }
1139 if (range_p->emsg) {
1140 lydict_remove(ctx->ctx, (*range)->emsg);
1141 (*range)->emsg = lydict_insert(ctx->ctx, range_p->emsg, 0);
1142 }
1143 /* extensions are taken only from the last range by the caller */
1144
1145 (*range)->parts = parts;
1146 parts = NULL;
1147 ret = LY_SUCCESS;
1148cleanup:
1149 /* TODO clean up */
1150 LY_ARRAY_FREE(parts);
1151
1152 return ret;
1153}
1154
1155/**
1156 * @brief Checks pattern syntax.
1157 *
Radek Krejcia3045382018-11-22 14:30:31 +01001158 * @param[in] ctx Compile context.
Radek Krejci19a96102018-11-15 13:38:09 +01001159 * @param[in] pattern Pattern to check.
Radek Krejcia3045382018-11-22 14:30:31 +01001160 * @param[in,out] pcre_precomp Precompiled PCRE pattern. If NULL, the compiled information used to validate pattern are freed.
1161 * @return LY_ERR value - LY_SUCCESS, LY_EMEM, LY_EVALID.
Radek Krejci19a96102018-11-15 13:38:09 +01001162 */
1163static LY_ERR
1164lys_compile_type_pattern_check(struct lysc_ctx *ctx, const char *pattern, pcre **pcre_precomp)
1165{
1166 int idx, idx2, start, end, err_offset, count;
1167 char *perl_regex, *ptr;
1168 const char *err_msg, *orig_ptr;
1169 pcre *precomp;
1170#define URANGE_LEN 19
1171 char *ublock2urange[][2] = {
1172 {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
1173 {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
1174 {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
1175 {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
1176 {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
1177 {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
1178 {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
1179 {"Greek", "[\\x{0370}-\\x{03FF}]"},
1180 {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
1181 {"Armenian", "[\\x{0530}-\\x{058F}]"},
1182 {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
1183 {"Arabic", "[\\x{0600}-\\x{06FF}]"},
1184 {"Syriac", "[\\x{0700}-\\x{074F}]"},
1185 {"Thaana", "[\\x{0780}-\\x{07BF}]"},
1186 {"Devanagari", "[\\x{0900}-\\x{097F}]"},
1187 {"Bengali", "[\\x{0980}-\\x{09FF}]"},
1188 {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
1189 {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
1190 {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
1191 {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
1192 {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
1193 {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
1194 {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
1195 {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
1196 {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
1197 {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
1198 {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
1199 {"Myanmar", "[\\x{1000}-\\x{109F}]"},
1200 {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
1201 {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
1202 {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
1203 {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
1204 {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
1205 {"Ogham", "[\\x{1680}-\\x{169F}]"},
1206 {"Runic", "[\\x{16A0}-\\x{16FF}]"},
1207 {"Khmer", "[\\x{1780}-\\x{17FF}]"},
1208 {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
1209 {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
1210 {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
1211 {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
1212 {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
1213 {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
1214 {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
1215 {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
1216 {"NumberForms", "[\\x{2150}-\\x{218F}]"},
1217 {"Arrows", "[\\x{2190}-\\x{21FF}]"},
1218 {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
1219 {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
1220 {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
1221 {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
1222 {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
1223 {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
1224 {"BlockElements", "[\\x{2580}-\\x{259F}]"},
1225 {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
1226 {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
1227 {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
1228 {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
1229 {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
1230 {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
1231 {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
1232 {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
1233 {"Hiragana", "[\\x{3040}-\\x{309F}]"},
1234 {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
1235 {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
1236 {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
1237 {"Kanbun", "[\\x{3190}-\\x{319F}]"},
1238 {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
1239 {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
1240 {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
1241 {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
1242 {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
1243 {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
1244 {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
1245 {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
1246 {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
1247 {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
1248 {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
1249 {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
1250 {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
1251 {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
1252 {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
1253 {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
1254 {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
1255 {NULL, NULL}
1256 };
1257
1258 /* adjust the expression to a Perl equivalent
1259 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs */
1260
1261 /* we need to replace all "$" with "\$", count them now */
1262 for (count = 0, ptr = strpbrk(pattern, "^$"); ptr; ++count, ptr = strpbrk(ptr + 1, "^$"));
1263
1264 perl_regex = malloc((strlen(pattern) + 4 + count) * sizeof(char));
1265 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx->ctx), LY_EMEM);
1266 perl_regex[0] = '\0';
1267
1268 ptr = perl_regex;
1269
1270 if (strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
1271 /* we will add line-end anchoring */
1272 ptr[0] = '(';
1273 ++ptr;
1274 }
1275
1276 for (orig_ptr = pattern; orig_ptr[0]; ++orig_ptr) {
1277 if (orig_ptr[0] == '$') {
1278 ptr += sprintf(ptr, "\\$");
1279 } else if (orig_ptr[0] == '^') {
1280 ptr += sprintf(ptr, "\\^");
1281 } else {
1282 ptr[0] = orig_ptr[0];
1283 ++ptr;
1284 }
1285 }
1286
1287 if (strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
1288 ptr += sprintf(ptr, ")$");
1289 } else {
1290 ptr[0] = '\0';
1291 ++ptr;
1292 }
1293
1294 /* substitute Unicode Character Blocks with exact Character Ranges */
1295 while ((ptr = strstr(perl_regex, "\\p{Is"))) {
1296 start = ptr - perl_regex;
1297
1298 ptr = strchr(ptr, '}');
1299 if (!ptr) {
1300 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP,
1301 pattern, perl_regex + start + 2, "unterminated character property");
1302 free(perl_regex);
1303 return LY_EVALID;
1304 }
1305 end = (ptr - perl_regex) + 1;
1306
1307 /* need more space */
1308 if (end - start < URANGE_LEN) {
1309 perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (URANGE_LEN - (end - start)) + 1);
1310 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx->ctx); free(perl_regex), LY_EMEM);
1311 }
1312
1313 /* find our range */
1314 for (idx = 0; ublock2urange[idx][0]; ++idx) {
1315 if (!strncmp(perl_regex + start + 5, ublock2urange[idx][0], strlen(ublock2urange[idx][0]))) {
1316 break;
1317 }
1318 }
1319 if (!ublock2urange[idx][0]) {
1320 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP,
1321 pattern, perl_regex + start + 5, "unknown block name");
1322 free(perl_regex);
1323 return LY_EVALID;
1324 }
1325
1326 /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
1327 for (idx2 = 0, count = 0; idx2 < start; ++idx2) {
1328 if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
1329 ++count;
1330 }
1331 if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
1332 --count;
1333 }
1334 }
1335 if (count) {
1336 /* skip brackets */
1337 memmove(perl_regex + start + (URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
1338 memcpy(perl_regex + start, ublock2urange[idx][1] + 1, URANGE_LEN - 2);
1339 } else {
1340 memmove(perl_regex + start + URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
1341 memcpy(perl_regex + start, ublock2urange[idx][1], URANGE_LEN);
1342 }
1343 }
1344
1345 /* must return 0, already checked during parsing */
1346 precomp = pcre_compile(perl_regex, PCRE_UTF8 | PCRE_ANCHORED | PCRE_DOLLAR_ENDONLY | PCRE_NO_AUTO_CAPTURE,
1347 &err_msg, &err_offset, NULL);
1348 if (!precomp) {
1349 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_INREGEXP, pattern, perl_regex + err_offset, err_msg);
1350 free(perl_regex);
1351 return LY_EVALID;
1352 }
1353 free(perl_regex);
1354
1355 if (pcre_precomp) {
1356 *pcre_precomp = precomp;
1357 } else {
1358 free(precomp);
1359 }
1360
1361 return LY_SUCCESS;
1362
1363#undef URANGE_LEN
1364}
1365
Radek Krejcia3045382018-11-22 14:30:31 +01001366/**
1367 * @brief Compile parsed pattern restriction in conjunction with the patterns from base type.
1368 * @param[in] ctx Compile context.
1369 * @param[in] patterns_p Array of parsed patterns from the current type to compile.
1370 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
1371 * @param[in] base_patterns Compiled patterns from the type from which the current type is derived.
1372 * Patterns from the base type are inherited to have all the patterns that have to match at one place.
1373 * @param[out] patterns Pointer to the storage for the patterns of the current type.
1374 * @return LY_ERR LY_SUCCESS, LY_EMEM, LY_EVALID.
1375 */
Radek Krejci19a96102018-11-15 13:38:09 +01001376static LY_ERR
1377lys_compile_type_patterns(struct lysc_ctx *ctx, struct lysp_restr *patterns_p, int options,
1378 struct lysc_pattern **base_patterns, struct lysc_pattern ***patterns)
1379{
1380 struct lysc_pattern **pattern;
1381 unsigned int u, v;
1382 const char *err_msg;
1383 LY_ERR ret = LY_SUCCESS;
1384
1385 /* first, copy the patterns from the base type */
1386 if (base_patterns) {
1387 *patterns = lysc_patterns_dup(ctx->ctx, base_patterns);
1388 LY_CHECK_ERR_RET(!(*patterns), LOGMEM(ctx->ctx), LY_EMEM);
1389 }
1390
1391 LY_ARRAY_FOR(patterns_p, u) {
1392 LY_ARRAY_NEW_RET(ctx->ctx, (*patterns), pattern, LY_EMEM);
1393 *pattern = calloc(1, sizeof **pattern);
1394 ++(*pattern)->refcount;
1395
1396 ret = lys_compile_type_pattern_check(ctx, &patterns_p[u].arg[1], &(*pattern)->expr);
1397 LY_CHECK_RET(ret);
1398 (*pattern)->expr_extra = pcre_study((*pattern)->expr, 0, &err_msg);
1399 if (err_msg) {
1400 LOGWRN(ctx->ctx, "Studying pattern \"%s\" failed (%s).", pattern, err_msg);
1401 }
1402
1403 if (patterns_p[u].arg[0] == 0x15) {
1404 (*pattern)->inverted = 1;
1405 }
1406 DUP_STRING(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag);
1407 DUP_STRING(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg);
1408 COMPILE_ARRAY_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts,
1409 options, v, lys_compile_ext, ret, done);
1410 }
1411done:
1412 return ret;
1413}
1414
Radek Krejcia3045382018-11-22 14:30:31 +01001415/**
1416 * @brief map of the possible restrictions combination for the specific built-in type.
1417 */
Radek Krejci19a96102018-11-15 13:38:09 +01001418static uint16_t type_substmt_map[LY_DATA_TYPE_COUNT] = {
1419 0 /* LY_TYPE_UNKNOWN */,
1420 LYS_SET_LENGTH /* LY_TYPE_BINARY */,
1421 LYS_SET_BIT /* LY_TYPE_BITS */,
1422 0 /* LY_TYPE_BOOL */,
1423 LYS_SET_FRDIGITS | LYS_SET_RANGE /* LY_TYPE_DEC64 */,
1424 0 /* LY_TYPE_EMPTY */,
1425 LYS_SET_ENUM /* LY_TYPE_ENUM */,
1426 LYS_SET_BASE /* LY_TYPE_IDENT */,
1427 LYS_SET_REQINST /* LY_TYPE_INST */,
1428 LYS_SET_REQINST | LYS_SET_PATH /* LY_TYPE_LEAFREF */,
1429 LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
1430 LYS_SET_TYPE /* LY_TYPE_UNION */,
1431 LYS_SET_RANGE /* LY_TYPE_INT8 */,
1432 LYS_SET_RANGE /* LY_TYPE_UINT8 */,
1433 LYS_SET_RANGE /* LY_TYPE_INT16 */,
1434 LYS_SET_RANGE /* LY_TYPE_UINT16 */,
1435 LYS_SET_RANGE /* LY_TYPE_INT32 */,
1436 LYS_SET_RANGE /* LY_TYPE_UINT32 */,
1437 LYS_SET_RANGE /* LY_TYPE_INT64 */,
1438 LYS_SET_RANGE /* LY_TYPE_UINT64 */
1439};
1440
Radek Krejcia3045382018-11-22 14:30:31 +01001441/**
1442 * @brief Compile parsed type's enum structures (for enumeration and bits types).
1443 * @param[in] ctx Compile context.
1444 * @param[in] enums_p Array of the parsed enum structures to compile.
1445 * @param[in] basetype Base YANG built-in type from which the current type is derived. Only LY_TYPE_ENUM and LY_TYPE_BITS are expected.
1446 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
1447 * @param[in] base_enums Array of the compiled enums information from the (latest) base type to check if the current enums are compatible.
1448 * @param[out] enums Newly created array of the compiled enums information for the current type.
1449 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
1450 */
Radek Krejci19a96102018-11-15 13:38:09 +01001451static LY_ERR
1452lys_compile_type_enums(struct lysc_ctx *ctx, struct lysp_type_enum *enums_p, LY_DATA_TYPE basetype, int options,
1453 struct lysc_type_enum_item *base_enums, struct lysc_type_enum_item **enums)
1454{
1455 LY_ERR ret = LY_SUCCESS;
1456 unsigned int u, v, match;
1457 int32_t value = 0;
1458 uint32_t position = 0;
1459 struct lysc_type_enum_item *e, storage;
1460
1461 if (base_enums && ctx->mod->compiled->version < 2) {
1462 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "%s type can be subtyped only in YANG 1.1 modules.",
1463 basetype == LY_TYPE_ENUM ? "Enumeration" : "Bits");
1464 return LY_EVALID;
1465 }
1466
1467 LY_ARRAY_FOR(enums_p, u) {
1468 LY_ARRAY_NEW_RET(ctx->ctx, *enums, e, LY_EMEM);
1469 DUP_STRING(ctx->ctx, enums_p[u].name, e->name);
1470 if (base_enums) {
1471 /* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
1472 LY_ARRAY_FOR(base_enums, v) {
1473 if (!strcmp(e->name, base_enums[v].name)) {
1474 break;
1475 }
1476 }
1477 if (v == LY_ARRAY_SIZE(base_enums)) {
1478 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1479 "Invalid %s - derived type adds new item \"%s\".",
1480 basetype == LY_TYPE_ENUM ? "enumeration" : "bits", e->name);
1481 return LY_EVALID;
1482 }
1483 match = v;
1484 }
1485
1486 if (basetype == LY_TYPE_ENUM) {
1487 if (enums_p[u].flags & LYS_SET_VALUE) {
1488 e->value = (int32_t)enums_p[u].value;
1489 if (!u || e->value >= value) {
1490 value = e->value + 1;
1491 }
1492 /* check collision with other values */
1493 for (v = 0; v < LY_ARRAY_SIZE(*enums) - 1; ++v) {
1494 if (e->value == (*enums)[v].value) {
1495 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1496 "Invalid enumeration - value %d collide in items \"%s\" and \"%s\".",
1497 e->value, e->name, (*enums)[v].name);
1498 return LY_EVALID;
1499 }
1500 }
1501 } else if (base_enums) {
1502 /* inherit the assigned value */
1503 e->value = base_enums[match].value;
1504 if (!u || e->value >= value) {
1505 value = e->value + 1;
1506 }
1507 } else {
1508 /* assign value automatically */
1509 if (u && value == INT32_MIN) {
1510 /* counter overflow */
1511 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1512 "Invalid enumeration - it is not possible to auto-assign enum value for "
1513 "\"%s\" since the highest value is already 2147483647.", e->name);
1514 return LY_EVALID;
1515 }
1516 e->value = value++;
1517 }
1518 } else { /* LY_TYPE_BITS */
1519 if (enums_p[u].flags & LYS_SET_VALUE) {
1520 e->value = (int32_t)enums_p[u].value;
1521 if (!u || (uint32_t)e->value >= position) {
1522 position = (uint32_t)e->value + 1;
1523 }
1524 /* check collision with other values */
1525 for (v = 0; v < LY_ARRAY_SIZE(*enums) - 1; ++v) {
1526 if (e->value == (*enums)[v].value) {
1527 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1528 "Invalid bits - position %u collide in items \"%s\" and \"%s\".",
1529 (uint32_t)e->value, e->name, (*enums)[v].name);
1530 return LY_EVALID;
1531 }
1532 }
1533 } else if (base_enums) {
1534 /* inherit the assigned value */
1535 e->value = base_enums[match].value;
1536 if (!u || (uint32_t)e->value >= position) {
1537 position = (uint32_t)e->value + 1;
1538 }
1539 } else {
1540 /* assign value automatically */
1541 if (u && position == 0) {
1542 /* counter overflow */
1543 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1544 "Invalid bits - it is not possible to auto-assign bit position for "
1545 "\"%s\" since the highest value is already 4294967295.", e->name);
1546 return LY_EVALID;
1547 }
1548 e->value = position++;
1549 }
1550 }
1551
1552 if (base_enums) {
1553 /* the assigned values must not change from the derived type */
1554 if (e->value != base_enums[match].value) {
1555 if (basetype == LY_TYPE_ENUM) {
1556 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1557 "Invalid enumeration - value of the item \"%s\" has changed from %d to %d in the derived type.",
1558 e->name, base_enums[match].value, e->value);
1559 } else {
1560 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1561 "Invalid bits - position of the item \"%s\" has changed from %u to %u in the derived type.",
1562 e->name, (uint32_t)base_enums[match].value, (uint32_t)e->value);
1563 }
1564 return LY_EVALID;
1565 }
1566 }
1567
1568 COMPILE_ARRAY_GOTO(ctx, enums_p[u].iffeatures, e->iffeatures, options, v, lys_compile_iffeature, ret, done);
1569 COMPILE_ARRAY_GOTO(ctx, enums_p[u].exts, e->exts, options, v, lys_compile_ext, ret, done);
1570
1571 if (basetype == LY_TYPE_BITS) {
1572 /* keep bits ordered by position */
1573 for (v = u; v && (*enums)[v - 1].value > e->value; --v);
1574 if (v != u) {
1575 memcpy(&storage, e, sizeof *e);
1576 memmove(&(*enums)[v + 1], &(*enums)[v], (u - v) * sizeof **enums);
1577 memcpy(&(*enums)[v], &storage, sizeof storage);
1578 }
1579 }
1580 }
1581
1582done:
1583 return ret;
1584}
1585
Radek Krejcia3045382018-11-22 14:30:31 +01001586#define MOVE_PATH_PARENT(NODE, LIMIT_COND, TERM, ERR_MSG, ...) \
1587 for ((NODE) = (NODE)->parent; \
1588 (NODE) && !((NODE)->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_ACTION | LYS_NOTIF | LYS_ACTION)); \
1589 (NODE) = (NODE)->parent); \
1590 if (!(NODE) && (LIMIT_COND)) { /* we are going higher than top-level */ \
1591 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, ERR_MSG, ##__VA_ARGS__); \
1592 TERM; \
1593 }
1594
1595/**
1596 * @brief Validate the predicate(s) from the leafref path.
1597 * @param[in] ctx Compile context
1598 * @param[in, out] predicate Pointer to the predicate in the leafref path. The pointer is moved after the validated predicate(s).
1599 * Since there can be multiple adjacent predicates for lists with multiple keys, all such predicates are validated.
1600 * @param[in] context_node Predicate context node (where the predicate is placed).
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001601 * @param[in] path_context Schema where the path was defined to correct resolve of the prefixes.
Radek Krejcia3045382018-11-22 14:30:31 +01001602 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
1603 */
1604static LY_ERR
1605lys_compile_leafref_predicate_validate(struct lysc_ctx *ctx, const char **predicate,
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001606 const struct lysc_node *context_node, const struct lys_module *path_context)
Radek Krejcia3045382018-11-22 14:30:31 +01001607{
1608 LY_ERR ret = LY_EVALID;
1609 const struct lys_module *mod;
1610 const struct lysc_node *src_node, *dst_node;
1611 const char *path_key_expr, *pke_start, *src, *src_prefix, *dst, *dst_prefix;
1612 size_t src_len, src_prefix_len, dst_len, dst_prefix_len;
1613 unsigned int dest_parent_times;
1614 const char *start, *end, *pke_end;
1615 struct ly_set keys = {0};
1616 int i;
1617
1618 while (**predicate == '[') {
1619 start = (*predicate)++;
1620
1621 while (isspace(**predicate)) {
1622 ++(*predicate);
1623 }
1624 LY_CHECK_GOTO(lys_parse_nodeid(predicate, &src_prefix, &src_prefix_len, &src, &src_len), cleanup);
1625 while (isspace(**predicate)) {
1626 ++(*predicate);
1627 }
1628 if (**predicate != '=') {
1629 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1630 "Invalid leafref path predicate \"%.*s\" - missing \"=\".", *predicate - start + 1, *predicate);
1631 goto cleanup;
1632 }
1633 ++(*predicate);
1634 while (isspace(**predicate)) {
1635 ++(*predicate);
1636 }
1637
1638 if ((end = pke_end = strchr(*predicate, ']')) == NULL) {
1639 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1640 "Invalid leafref path predicate \"%s\" - missing predicate termination.", start);
1641 goto cleanup;
1642 }
1643 --pke_end;
1644 while (isspace(*pke_end)) {
1645 --pke_end;
1646 }
1647 /* localize path-key-expr */
1648 pke_start = path_key_expr = *predicate;
1649 /* move after the current predicate */
1650 *predicate = end + 1;
1651
1652 /* source (must be leaf or leaf-list) */
1653 if (src_prefix) {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001654 mod = lys_module_find_prefix(path_context, src_prefix, src_prefix_len);
Radek Krejcia3045382018-11-22 14:30:31 +01001655 } else {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001656 mod = path_context;
Radek Krejcia3045382018-11-22 14:30:31 +01001657 }
1658 src_node = lys_child(context_node, mod, src, src_len,
1659 mod->compiled->version < LYS_VERSION_1_1 ? LYS_LEAF : LYS_LEAF | LYS_LEAFLIST, LYS_GETNEXT_NOSTATECHECK);
1660 if (!src_node) {
1661 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1662 "Invalid leafref path predicate \"%.*s\" - key node \"%.*s\" from module \"%s\" not found.",
1663 *predicate - start, start, src_len, src, mod->compiled->name);
1664 goto cleanup;
1665 }
1666 /* TODO - check the src_node is really a key of the context_node */
1667
1668 /* check that there is only one predicate for the */
1669 i = ly_set_add(&keys, (void*)src_node, 0);
1670 LY_CHECK_GOTO(i == -1, cleanup);
1671 if (keys.count != (unsigned int)i + 1) {
1672 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1673 "Invalid leafref path predicate \"%.*s\" - multiple equality test for the key %s.",
1674 *predicate - start, start, src_node->name);
1675 goto cleanup;
1676 }
1677
1678 /* destination */
1679 dest_parent_times = 0;
1680 dst_node = context_node;
1681
1682 /* current-function-invocation *WSP "/" *WSP rel-path-keyexpr */
1683 if (strncmp(path_key_expr, "current()", 9)) {
1684 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1685 "Invalid leafref path predicate \"%.*s\" - missing current-function-invocation.",
1686 *predicate - start, start);
1687 goto cleanup;
1688 }
1689 path_key_expr += 9;
1690 while (isspace(*path_key_expr)) {
1691 ++path_key_expr;
1692 }
1693
1694 if (*path_key_expr != '/') {
1695 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1696 "Invalid leafref path predicate \"%.*s\" - missing \"/\" after current-function-invocation.",
1697 *predicate - start, start);
1698 goto cleanup;
1699 }
1700 ++path_key_expr;
1701 while (isspace(*path_key_expr)) {
1702 ++path_key_expr;
1703 }
1704
1705 /* rel-path-keyexpr:
1706 * 1*(".." *WSP "/" *WSP) *(node-identifier *WSP "/" *WSP) node-identifier */
1707 while (!strncmp(path_key_expr, "..", 2)) {
1708 ++dest_parent_times;
1709 path_key_expr += 2;
1710 while (isspace(*path_key_expr)) {
1711 ++path_key_expr;
1712 }
1713 if (*path_key_expr != '/') {
1714 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1715 "Invalid leafref path predicate \"%.*s\" - missing \"/\" in \"../\" rel-path-keyexpr pattern.",
1716 *predicate - start, start);
1717 goto cleanup;
1718 }
1719 ++path_key_expr;
1720 while (isspace(*path_key_expr)) {
1721 ++path_key_expr;
1722 }
1723
1724 /* path is supposed to be evaluated in data tree, so we have to skip
1725 * all schema nodes that cannot be instantiated in data tree */
1726 MOVE_PATH_PARENT(dst_node, !strncmp(path_key_expr, "..", 2), goto cleanup,
1727 "Invalid leafref path predicate \"%.*s\" - too many \"..\" in rel-path-keyexpr.",
1728 *predicate - start, start);
1729 }
1730 if (!dest_parent_times) {
1731 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1732 "Invalid leafref path predicate \"%.*s\" - at least one \"..\" is expected in rel-path-keyexpr.",
1733 *predicate - start, start);
1734 goto cleanup;
1735 }
1736 if (path_key_expr == pke_end) {
1737 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1738 "Invalid leafref path predicate \"%.*s\" - at least one node-identifier is expected in rel-path-keyexpr.",
1739 *predicate - start, start);
1740 goto cleanup;
1741 }
1742
1743 while(path_key_expr != pke_end) {
1744 if (lys_parse_nodeid(&path_key_expr, &dst_prefix, &dst_prefix_len, &dst, &dst_len)) {
1745 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1746 "Invalid node identifier in leafref path predicate - character %d (%.*s).",
1747 path_key_expr - start, *predicate - start, start);
1748 goto cleanup;
1749 }
1750
1751 if (dst_prefix) {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001752 mod = lys_module_find_prefix(path_context, dst_prefix, dst_prefix_len);
Radek Krejcia3045382018-11-22 14:30:31 +01001753 } else {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001754 mod = path_context;
Radek Krejcia3045382018-11-22 14:30:31 +01001755 }
1756 if (!mod) {
1757 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1758 "Invalid leafref path predicate \"%.*s\" - unable to find module of the node \"%.*s\" in rel-path_keyexpr.",
1759 *predicate - start, start, dst_len, dst);
1760 goto cleanup;
1761 }
1762
1763 dst_node = lys_child(dst_node, mod, dst, dst_len, 0, LYS_GETNEXT_NOSTATECHECK);
1764 if (!dst_node) {
1765 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1766 "Invalid leafref path predicate \"%.*s\" - unable to find node \"%.*s\" in the rel-path_keyexpr.",
1767 *predicate - start, start, path_key_expr - pke_start, pke_start);
1768 goto cleanup;
1769 }
1770 }
1771 if (!(dst_node->nodetype & (dst_node->module->compiled->version < LYS_VERSION_1_1 ? LYS_LEAF : LYS_LEAF | LYS_LEAFLIST))) {
1772 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1773 "Invalid leafref path predicate \"%.*s\" - rel-path_keyexpr \"%.*s\" refers %s.",
1774 *predicate - start, start, path_key_expr - pke_start, pke_start, lys_nodetype2str(dst_node->nodetype));
1775 goto cleanup;
1776 }
1777 }
1778
1779 ret = LY_SUCCESS;
1780cleanup:
1781 ly_set_erase(&keys, NULL);
1782 return ret;
1783}
1784
1785/**
1786 * @brief Parse path-arg (leafref). Get tokens of the path by repetitive calls of the function.
1787 *
1788 * path-arg = absolute-path / relative-path
1789 * absolute-path = 1*("/" (node-identifier *path-predicate))
1790 * relative-path = 1*(".." "/") descendant-path
1791 *
1792 * @param[in,out] path Path to parse.
1793 * @param[out] prefix Prefix of the token, NULL if there is not any.
1794 * @param[out] pref_len Length of the prefix, 0 if there is not any.
1795 * @param[out] name Name of the token.
1796 * @param[out] nam_len Length of the name.
1797 * @param[out] parent_times Number of leading ".." in the path. Must be 0 on the first call,
1798 * must not be changed between consecutive calls. -1 if the
1799 * path is absolute.
1800 * @param[out] has_predicate Flag to mark whether there is a predicate specified.
1801 * @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid character in the path.
1802 */
1803static LY_ERR
1804lys_path_token(const char **path, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len,
1805 int *parent_times, int *has_predicate)
1806{
1807 int par_times = 0;
1808
1809 assert(path && *path);
1810 assert(parent_times);
1811 assert(prefix);
1812 assert(prefix_len);
1813 assert(name);
1814 assert(name_len);
1815 assert(has_predicate);
1816
1817 *prefix = NULL;
1818 *prefix_len = 0;
1819 *name = NULL;
1820 *name_len = 0;
1821 *has_predicate = 0;
1822
1823 if (!*parent_times) {
1824 if (!strncmp(*path, "..", 2)) {
1825 *path += 2;
1826 ++par_times;
1827 while (!strncmp(*path, "/..", 3)) {
1828 *path += 3;
1829 ++par_times;
1830 }
1831 }
1832 if (par_times) {
1833 *parent_times = par_times;
1834 } else {
1835 *parent_times = -1;
1836 }
1837 }
1838
1839 if (**path != '/') {
1840 return LY_EINVAL;
1841 }
1842 /* skip '/' */
1843 ++(*path);
1844
1845 /* node-identifier ([prefix:]name) */
1846 LY_CHECK_RET(lys_parse_nodeid(path, prefix, prefix_len, name, name_len));
1847
1848 if ((**path == '/' && (*path)[1]) || !**path) {
1849 /* path continues by another token or this is the last token */
1850 return LY_SUCCESS;
1851 } else if ((*path)[0] != '[') {
1852 /* unexpected character */
1853 return LY_EINVAL;
1854 } else {
1855 /* predicate starting with [ */
1856 *has_predicate = 1;
1857 return LY_SUCCESS;
1858 }
1859}
1860
1861/**
1862 * @brief Validate the leafref path.
1863 * @param[in] ctx Compile context
1864 * @param[in] startnode Path context node (where the leafref path begins/is placed).
1865 * @param[in] path Leafref path to validate.
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001866 * @param[in] path_context Module where the path was defined to correct resolve of the prefixes.
Radek Krejcia3045382018-11-22 14:30:31 +01001867 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
1868 */
1869static LY_ERR
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001870lys_compile_leafref_validate(struct lysc_ctx *ctx, struct lysc_node *startnode, const char *path, struct lys_module *path_context)
Radek Krejcia3045382018-11-22 14:30:31 +01001871{
1872 const struct lysc_node *node = NULL, *parent = NULL;
1873 const struct lys_module *mod;
1874 const char *id, *prefix, *name;
1875 size_t prefix_len, name_len;
1876 int parent_times = 0, has_predicate;
1877 unsigned int iter, u;
1878 LY_ERR ret = LY_SUCCESS;
1879
1880 assert(ctx);
1881 assert(startnode);
1882 assert(path);
1883
1884 iter = 0;
1885 id = path;
1886 while(*id && (ret = lys_path_token(&id, &prefix, &prefix_len, &name, &name_len, &parent_times, &has_predicate)) == LY_SUCCESS) {
1887 if (!iter) { /* first iteration */
1888 /* precess ".." in relative paths */
1889 if (parent_times > 0) {
1890 /* move from the context node */
1891 for (u = 0, parent = startnode; u < (unsigned int)parent_times; u++) {
1892 /* path is supposed to be evaluated in data tree, so we have to skip
1893 * all schema nodes that cannot be instantiated in data tree */
1894 MOVE_PATH_PARENT(parent, u < (unsigned int)parent_times - 1, return LY_EVALID,
1895 "Invalid leafref path \"%s\" - too many \"..\" in the path.", path);
1896 }
1897 }
1898 }
1899
1900 if (prefix) {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001901 mod = lys_module_find_prefix(path_context, prefix, prefix_len);
Radek Krejcia3045382018-11-22 14:30:31 +01001902 } else {
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001903 mod = path_context;
Radek Krejcia3045382018-11-22 14:30:31 +01001904 }
1905 if (!mod) {
1906 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1907 "Invalid leafref path - unable to find module connected with the prefix of the node \"%.*s\".", id - path, path);
1908 return LY_EVALID;
1909 }
1910
1911 node = lys_child(parent, mod, name, name_len, 0, LYS_GETNEXT_NOSTATECHECK);
1912 if (!node) {
1913 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1914 "Invalid leafref path - unable to find \"%.*s\".", id - path, path);
1915 return LY_EVALID;
1916 }
1917 parent = node;
1918
1919 if (has_predicate) {
1920 /* we have predicate, so the current result must be list */
1921 if (node->nodetype != LYS_LIST) {
1922 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1923 "Invalid leafref path - node \"%.*s\" is expected to be a list, but it is %s.",
1924 id - path, path, lys_nodetype2str(node->nodetype));
1925 return LY_EVALID;
1926 }
1927
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001928 LY_CHECK_RET(lys_compile_leafref_predicate_validate(ctx, &id, node, path_context), LY_EVALID);
Radek Krejcia3045382018-11-22 14:30:31 +01001929 }
1930
1931 ++iter;
1932 }
1933 if (ret) {
1934 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
1935 "Invalid leafref path at character %d (%s).", id - path + 1, path);
1936 return LY_EVALID;
1937 }
1938
1939 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
1940 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
1941 "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
1942 path, lys_nodetype2str(node->nodetype));
1943 return LY_EVALID;
1944 }
1945
1946 /* check status */
1947 if (lysc_check_status(ctx, startnode->flags, startnode->module, startnode->name, node->flags, node->module, node->name)) {
1948 return LY_EVALID;
1949 }
1950
1951 return LY_SUCCESS;
1952}
1953
1954/**
1955 * @brief The core of the lys_compile_type() - compile information about the given type (from typedef or leaf/leaf-list).
1956 * @param[in] ctx Compile context.
1957 * @param[in] type_p Parsed type to compile.
1958 * @param[in] basetype Base YANG built-in type of the type to compile.
1959 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
1960 * @param[in] tpdfname Name of the type's typedef, serves as a flag - if it is leaf/leaf-list's type, it is NULL.
1961 * @param[in] base The latest base (compiled) type from which the current type is being derived.
1962 * @param[out] type Newly created type structure with the filled information about the type.
1963 * @return LY_ERR value.
1964 */
Radek Krejci19a96102018-11-15 13:38:09 +01001965static LY_ERR
Radek Krejci96a0bfd2018-11-22 15:25:06 +01001966lys_compile_type_(struct lysc_ctx *ctx, struct lysp_type *type_p, struct lys_module *module, LY_DATA_TYPE basetype, int options,
1967 const char *tpdfname, struct lysc_type *base, struct lysc_type **type)
Radek Krejcic5c27e52018-11-15 14:38:11 +01001968{
1969 LY_ERR ret = LY_SUCCESS;
1970 unsigned int u;
1971 struct lysc_type_bin *bin;
1972 struct lysc_type_num *num;
1973 struct lysc_type_str *str;
1974 struct lysc_type_bits *bits;
1975 struct lysc_type_enum *enumeration;
Radek Krejci6cba4292018-11-15 17:33:29 +01001976 struct lysc_type_dec *dec;
Radek Krejci555cb5b2018-11-16 14:54:33 +01001977 struct lysc_type_identityref *idref;
Radek Krejcic5c27e52018-11-15 14:38:11 +01001978
1979 switch (basetype) {
1980 case LY_TYPE_BINARY:
Radek Krejcic5c27e52018-11-15 14:38:11 +01001981 bin = (struct lysc_type_bin*)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001982
1983 /* RFC 7950 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejcic5c27e52018-11-15 14:38:11 +01001984 if (type_p->length) {
Radek Krejci6cba4292018-11-15 17:33:29 +01001985 ret = lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
Radek Krejcic5c27e52018-11-15 14:38:11 +01001986 base ? ((struct lysc_type_bin*)base)->length : NULL, &bin->length);
1987 LY_CHECK_RET(ret);
1988 if (!tpdfname) {
1989 COMPILE_ARRAY_GOTO(ctx, type_p->length->exts, bin->length->exts,
1990 options, u, lys_compile_ext, ret, done);
1991 }
1992 }
1993
1994 if (tpdfname) {
1995 type_p->compiled = *type;
1996 *type = calloc(1, sizeof(struct lysc_type_bin));
1997 }
1998 break;
1999 case LY_TYPE_BITS:
2000 /* RFC 7950 9.7 - bits */
2001 bits = (struct lysc_type_bits*)(*type);
2002 if (type_p->bits) {
2003 ret = lys_compile_type_enums(ctx, type_p->bits, basetype, options,
2004 base ? (struct lysc_type_enum_item*)((struct lysc_type_bits*)base)->bits : NULL,
2005 (struct lysc_type_enum_item**)&bits->bits);
2006 LY_CHECK_RET(ret);
2007 }
2008
Radek Krejci555cb5b2018-11-16 14:54:33 +01002009 if (!base && !type_p->flags) {
Radek Krejcic5c27e52018-11-15 14:38:11 +01002010 /* type derived from bits built-in type must contain at least one bit */
Radek Krejci6cba4292018-11-15 17:33:29 +01002011 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002012 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type ", tpdfname);
Radek Krejci6cba4292018-11-15 17:33:29 +01002013 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002014 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type", "");
Radek Krejci6cba4292018-11-15 17:33:29 +01002015 free(*type);
2016 *type = NULL;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002017 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002018 return LY_EVALID;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002019 }
2020
2021 if (tpdfname) {
2022 type_p->compiled = *type;
2023 *type = calloc(1, sizeof(struct lysc_type_bits));
2024 }
2025 break;
Radek Krejci6cba4292018-11-15 17:33:29 +01002026 case LY_TYPE_DEC64:
2027 dec = (struct lysc_type_dec*)(*type);
2028
2029 /* RFC 7950 9.3.4 - fraction-digits */
Radek Krejci555cb5b2018-11-16 14:54:33 +01002030 if (!base) {
Radek Krejci643c8242018-11-15 17:51:11 +01002031 if (!type_p->fraction_digits) {
2032 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002033 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type ", tpdfname);
Radek Krejci643c8242018-11-15 17:51:11 +01002034 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002035 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type", "");
Radek Krejci643c8242018-11-15 17:51:11 +01002036 free(*type);
2037 *type = NULL;
2038 }
2039 return LY_EVALID;
2040 }
2041 } else if (type_p->fraction_digits) {
2042 /* fraction digits is prohibited in types not directly derived from built-in decimal64 */
Radek Krejci6cba4292018-11-15 17:33:29 +01002043 if (tpdfname) {
Radek Krejci643c8242018-11-15 17:51:11 +01002044 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2045 "Invalid fraction-digits substatement for type \"%s\" not directly derived from decimal64 built-in type.",
Radek Krejci6cba4292018-11-15 17:33:29 +01002046 tpdfname);
2047 } else {
Radek Krejci643c8242018-11-15 17:51:11 +01002048 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2049 "Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.");
Radek Krejci6cba4292018-11-15 17:33:29 +01002050 free(*type);
2051 *type = NULL;
2052 }
2053 return LY_EVALID;
2054 }
2055 dec->fraction_digits = type_p->fraction_digits;
2056
2057 /* RFC 7950 9.2.4 - range */
2058 if (type_p->range) {
2059 ret = lys_compile_type_range(ctx, type_p->range, basetype, 0, dec->fraction_digits,
2060 base ? ((struct lysc_type_dec*)base)->range : NULL, &dec->range);
2061 LY_CHECK_RET(ret);
2062 if (!tpdfname) {
2063 COMPILE_ARRAY_GOTO(ctx, type_p->range->exts, dec->range->exts,
2064 options, u, lys_compile_ext, ret, done);
2065 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002066 }
2067
2068 if (tpdfname) {
2069 type_p->compiled = *type;
2070 *type = calloc(1, sizeof(struct lysc_type_dec));
2071 }
2072 break;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002073 case LY_TYPE_STRING:
Radek Krejcic5c27e52018-11-15 14:38:11 +01002074 str = (struct lysc_type_str*)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002075
2076 /* RFC 7950 9.4.4 - length */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002077 if (type_p->length) {
Radek Krejci6cba4292018-11-15 17:33:29 +01002078 ret = lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
Radek Krejcic5c27e52018-11-15 14:38:11 +01002079 base ? ((struct lysc_type_str*)base)->length : NULL, &str->length);
2080 LY_CHECK_RET(ret);
2081 if (!tpdfname) {
2082 COMPILE_ARRAY_GOTO(ctx, type_p->length->exts, str->length->exts,
2083 options, u, lys_compile_ext, ret, done);
2084 }
2085 } else if (base && ((struct lysc_type_str*)base)->length) {
2086 str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str*)base)->length);
2087 }
2088
2089 /* RFC 7950 9.4.5 - pattern */
2090 if (type_p->patterns) {
2091 ret = lys_compile_type_patterns(ctx, type_p->patterns, options,
2092 base ? ((struct lysc_type_str*)base)->patterns : NULL, &str->patterns);
2093 LY_CHECK_RET(ret);
2094 } else if (base && ((struct lysc_type_str*)base)->patterns) {
2095 str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str*)base)->patterns);
2096 }
2097
2098 if (tpdfname) {
2099 type_p->compiled = *type;
2100 *type = calloc(1, sizeof(struct lysc_type_str));
2101 }
2102 break;
2103 case LY_TYPE_ENUM:
Radek Krejcic5c27e52018-11-15 14:38:11 +01002104 enumeration = (struct lysc_type_enum*)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002105
2106 /* RFC 7950 9.6 - enum */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002107 if (type_p->enums) {
2108 ret = lys_compile_type_enums(ctx, type_p->enums, basetype, options,
2109 base ? ((struct lysc_type_enum*)base)->enums : NULL, &enumeration->enums);
2110 LY_CHECK_RET(ret);
2111 }
2112
Radek Krejci555cb5b2018-11-16 14:54:33 +01002113 if (!base && !type_p->flags) {
Radek Krejcic5c27e52018-11-15 14:38:11 +01002114 /* type derived from enumerations built-in type must contain at least one enum */
Radek Krejci6cba4292018-11-15 17:33:29 +01002115 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002116 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type ", tpdfname);
Radek Krejci6cba4292018-11-15 17:33:29 +01002117 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002118 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type", "");
Radek Krejci6cba4292018-11-15 17:33:29 +01002119 free(*type);
2120 *type = NULL;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002121 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002122 return LY_EVALID;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002123 }
2124
2125 if (tpdfname) {
2126 type_p->compiled = *type;
2127 *type = calloc(1, sizeof(struct lysc_type_enum));
2128 }
2129 break;
2130 case LY_TYPE_INT8:
2131 case LY_TYPE_UINT8:
2132 case LY_TYPE_INT16:
2133 case LY_TYPE_UINT16:
2134 case LY_TYPE_INT32:
2135 case LY_TYPE_UINT32:
2136 case LY_TYPE_INT64:
2137 case LY_TYPE_UINT64:
Radek Krejcic5c27e52018-11-15 14:38:11 +01002138 num = (struct lysc_type_num*)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002139
2140 /* RFC 6020 9.2.4 - range */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002141 if (type_p->range) {
Radek Krejci6cba4292018-11-15 17:33:29 +01002142 ret = lys_compile_type_range(ctx, type_p->range, basetype, 0, 0,
Radek Krejcic5c27e52018-11-15 14:38:11 +01002143 base ? ((struct lysc_type_num*)base)->range : NULL, &num->range);
2144 LY_CHECK_RET(ret);
2145 if (!tpdfname) {
2146 COMPILE_ARRAY_GOTO(ctx, type_p->range->exts, num->range->exts,
2147 options, u, lys_compile_ext, ret, done);
2148 }
2149 }
2150
2151 if (tpdfname) {
2152 type_p->compiled = *type;
2153 *type = calloc(1, sizeof(struct lysc_type_num));
2154 }
2155 break;
Radek Krejci555cb5b2018-11-16 14:54:33 +01002156 case LY_TYPE_IDENT:
2157 idref = (struct lysc_type_identityref*)(*type);
2158
2159 /* RFC 7950 9.10.2 - base */
2160 if (type_p->bases) {
2161 if (base) {
2162 /* only the directly derived identityrefs can contain base specification */
2163 if (tpdfname) {
2164 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2165 "Invalid base substatement for type \"%s\" not directly derived from identityref built-in type.",
2166 tpdfname);
2167 } else {
2168 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
2169 "Invalid base substatement for type not directly derived from identityref built-in type.");
2170 free(*type);
2171 *type = NULL;
2172 }
2173 return LY_EVALID;
2174 }
2175 ret = lys_compile_identity_bases(ctx, type_p->bases, NULL, &idref->bases);
2176 LY_CHECK_RET(ret);
2177 }
2178
2179 if (!base && !type_p->flags) {
2180 /* type derived from identityref built-in type must contain at least one base */
2181 if (tpdfname) {
2182 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type ", tpdfname);
2183 } else {
2184 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type", "");
2185 free(*type);
2186 *type = NULL;
2187 }
2188 return LY_EVALID;
2189 }
2190
2191 if (tpdfname) {
2192 type_p->compiled = *type;
2193 *type = calloc(1, sizeof(struct lysc_type_identityref));
2194 }
2195 break;
Radek Krejcia3045382018-11-22 14:30:31 +01002196 case LY_TYPE_LEAFREF:
2197 /* RFC 7950 9.9.3 - require-instance */
2198 if (type_p->flags & LYS_SET_REQINST) {
2199 ((struct lysc_type_leafref*)(*type))->require_instance = type_p->require_instance;
2200 } else {
2201 /* default is true */
2202 ((struct lysc_type_leafref*)(*type))->require_instance = 1;
2203 }
2204 if (type_p->path) {
2205 DUP_STRING(ctx->ctx, (void*)type_p->path, ((struct lysc_type_leafref*)(*type))->path);
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002206 ((struct lysc_type_leafref*)(*type))->path_context = module;
Radek Krejcia3045382018-11-22 14:30:31 +01002207 } else if (base) {
2208 DUP_STRING(ctx->ctx, ((struct lysc_type_leafref*)base)->path, ((struct lysc_type_leafref*)(*type))->path);
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002209 ((struct lysc_type_leafref*)(*type))->path_context = ((struct lysc_type_leafref*)base)->path_context;
Radek Krejcia3045382018-11-22 14:30:31 +01002210 } else if (tpdfname) {
2211 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type ", tpdfname);
2212 return LY_EVALID;
2213 } else {
2214 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type", "");
2215 free(*type);
2216 *type = NULL;
2217 return LY_EVALID;
2218 }
2219 if (tpdfname) {
2220 type_p->compiled = *type;
2221 *type = calloc(1, sizeof(struct lysc_type_leafref));
2222 }
2223 break;
Radek Krejci16c0f822018-11-16 10:46:10 +01002224 case LY_TYPE_INST:
2225 /* RFC 7950 9.9.3 - require-instance */
2226 if (type_p->flags & LYS_SET_REQINST) {
2227 ((struct lysc_type_instanceid*)(*type))->require_instance = type_p->require_instance;
2228 } else {
2229 /* default is true */
2230 ((struct lysc_type_instanceid*)(*type))->require_instance = 1;
2231 }
2232
2233 if (tpdfname) {
2234 type_p->compiled = *type;
2235 *type = calloc(1, sizeof(struct lysc_type_instanceid));
2236 }
2237 break;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002238 case LY_TYPE_BOOL:
2239 case LY_TYPE_EMPTY:
2240 case LY_TYPE_UNKNOWN: /* just to complete switch */
2241 break;
2242 }
2243 LY_CHECK_ERR_RET(!(*type), LOGMEM(ctx->ctx), LY_EMEM);
2244done:
2245 return ret;
2246}
2247
Radek Krejcia3045382018-11-22 14:30:31 +01002248/**
2249 * @brief Compile information about the leaf/leaf-list's type.
2250 * @param[in] ctx Compile context.
2251 * @param[in] leaf_p Parsed leaf with the type to compile.
2252 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
2253 * @param[out] type Newly created (or reused with increased refcount) type structure with the filled information about the type.
2254 * @return LY_ERR value.
2255 */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002256static LY_ERR
Radek Krejci19a96102018-11-15 13:38:09 +01002257lys_compile_type(struct lysc_ctx *ctx, struct lysp_node_leaf *leaf_p, int options, struct lysc_type **type)
2258{
2259 LY_ERR ret = LY_SUCCESS;
2260 unsigned int u;
2261 struct lysp_type *type_p = &leaf_p->type;
2262 struct type_context {
2263 const struct lysp_tpdf *tpdf;
2264 struct lysp_node *node;
2265 struct lysp_module *mod;
2266 } *tctx, *tctx_prev = NULL;
2267 LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002268 struct lysc_type *base = NULL, *prev_type;
Radek Krejci19a96102018-11-15 13:38:09 +01002269 struct ly_set tpdf_chain = {0};
Radek Krejci19a96102018-11-15 13:38:09 +01002270
2271 (*type) = NULL;
2272
2273 tctx = calloc(1, sizeof *tctx);
2274 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
2275 for (ret = lysp_type_find(type_p->name, (struct lysp_node*)leaf_p, ctx->mod->parsed,
2276 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod);
2277 ret == LY_SUCCESS;
2278 ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->mod,
2279 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod)) {
2280 if (basetype) {
2281 break;
2282 }
2283
2284 /* check status */
2285 ret = lysc_check_status(ctx, leaf_p->flags, ctx->mod->parsed, leaf_p->name,
2286 tctx->tpdf->flags, tctx->mod, tctx->node ? tctx->node->name : tctx->mod->name);
2287 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
2288
2289 if (tctx->tpdf->type.compiled) {
2290 /* it is not necessary to continue, the rest of the chain was already compiled */
2291 basetype = tctx->tpdf->type.compiled->basetype;
2292 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
2293 tctx = NULL;
2294 break;
2295 }
2296
2297 /* store information for the following processing */
2298 ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST);
2299
2300 /* prepare next loop */
2301 tctx_prev = tctx;
2302 tctx = calloc(1, sizeof *tctx);
2303 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
2304 }
2305 free(tctx);
2306
2307 /* allocate type according to the basetype */
2308 switch (basetype) {
2309 case LY_TYPE_BINARY:
2310 *type = calloc(1, sizeof(struct lysc_type_bin));
Radek Krejci19a96102018-11-15 13:38:09 +01002311 break;
2312 case LY_TYPE_BITS:
2313 *type = calloc(1, sizeof(struct lysc_type_bits));
Radek Krejci19a96102018-11-15 13:38:09 +01002314 break;
2315 case LY_TYPE_BOOL:
2316 case LY_TYPE_EMPTY:
2317 *type = calloc(1, sizeof(struct lysc_type));
2318 break;
2319 case LY_TYPE_DEC64:
2320 *type = calloc(1, sizeof(struct lysc_type_dec));
2321 break;
2322 case LY_TYPE_ENUM:
2323 *type = calloc(1, sizeof(struct lysc_type_enum));
Radek Krejci19a96102018-11-15 13:38:09 +01002324 break;
2325 case LY_TYPE_IDENT:
2326 *type = calloc(1, sizeof(struct lysc_type_identityref));
2327 break;
2328 case LY_TYPE_INST:
2329 *type = calloc(1, sizeof(struct lysc_type_instanceid));
2330 break;
2331 case LY_TYPE_LEAFREF:
2332 *type = calloc(1, sizeof(struct lysc_type_leafref));
2333 break;
2334 case LY_TYPE_STRING:
2335 *type = calloc(1, sizeof(struct lysc_type_str));
Radek Krejci19a96102018-11-15 13:38:09 +01002336 break;
2337 case LY_TYPE_UNION:
2338 *type = calloc(1, sizeof(struct lysc_type_union));
2339 break;
2340 case LY_TYPE_INT8:
2341 case LY_TYPE_UINT8:
2342 case LY_TYPE_INT16:
2343 case LY_TYPE_UINT16:
2344 case LY_TYPE_INT32:
2345 case LY_TYPE_UINT32:
2346 case LY_TYPE_INT64:
2347 case LY_TYPE_UINT64:
2348 *type = calloc(1, sizeof(struct lysc_type_num));
Radek Krejci19a96102018-11-15 13:38:09 +01002349 break;
2350 case LY_TYPE_UNKNOWN:
2351 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
2352 "Referenced type \"%s\" not found.", tctx_prev ? tctx_prev->tpdf->type.name : type_p->name);
2353 ret = LY_EVALID;
2354 goto cleanup;
2355 }
2356 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
2357 if (~type_substmt_map[basetype] & leaf_p->type.flags) {
2358 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type restrictions for %s type.",
2359 ly_data_type2str[basetype]);
2360 free(*type);
2361 (*type) = NULL;
2362 ret = LY_EVALID;
2363 goto cleanup;
2364 }
2365
2366 /* get restrictions from the referred typedefs */
2367 for (u = tpdf_chain.count - 1; u + 1 > 0; --u) {
2368 tctx = (struct type_context*)tpdf_chain.objs[u];
2369 if (~type_substmt_map[basetype] & tctx->tpdf->type.flags) {
2370 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type \"%s\" restriction(s) for %s type.",
2371 tctx->tpdf->name, ly_data_type2str[basetype]);
2372 ret = LY_EVALID;
2373 goto cleanup;
2374 } else if (tctx->tpdf->type.compiled) {
2375 base = tctx->tpdf->type.compiled;
2376 continue;
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002377 } else if ((u != tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002378 /* no change, just use the type information from the base */
2379 base = ((struct lysp_tpdf*)tctx->tpdf)->type.compiled = ((struct type_context*)tpdf_chain.objs[u + 1])->tpdf->type.compiled;
2380 ++base->refcount;
2381 continue;
2382 }
2383
2384 ++(*type)->refcount;
2385 (*type)->basetype = basetype;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002386 prev_type = *type;
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002387 ret = lys_compile_type_(ctx, &((struct lysp_tpdf*)tctx->tpdf)->type,
2388 basetype & (LY_TYPE_LEAFREF | LY_TYPE_UNION) ? lysp_find_module(ctx->ctx, tctx->mod) : NULL,
2389 basetype, options, tctx->tpdf->name, base, type);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002390 LY_CHECK_GOTO(ret, cleanup);
2391 base = prev_type;
Radek Krejci19a96102018-11-15 13:38:09 +01002392 }
2393
Radek Krejcic5c27e52018-11-15 14:38:11 +01002394 /* process the type definition in leaf */
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002395 if (leaf_p->type.flags || !base) {
Radek Krejcia3045382018-11-22 14:30:31 +01002396 /* get restrictions from the node itself */
Radek Krejci19a96102018-11-15 13:38:09 +01002397 (*type)->basetype = basetype;
2398 ++(*type)->refcount;
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002399 ret = lys_compile_type_(ctx, &leaf_p->type, ctx->mod, basetype, options, NULL, base, type);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002400 LY_CHECK_GOTO(ret, cleanup);
2401 } else {
Radek Krejci19a96102018-11-15 13:38:09 +01002402 /* no specific restriction in leaf's type definition, copy from the base */
2403 free(*type);
2404 (*type) = base;
2405 ++(*type)->refcount;
Radek Krejci19a96102018-11-15 13:38:09 +01002406 }
2407
2408 COMPILE_ARRAY_GOTO(ctx, type_p->exts, (*type)->exts, options, u, lys_compile_ext, ret, cleanup);
2409
2410cleanup:
2411 ly_set_erase(&tpdf_chain, free);
2412 return ret;
2413}
2414
2415static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent);
2416
Radek Krejcia3045382018-11-22 14:30:31 +01002417/**
2418 * @brief Compile parsed container node information.
2419 * @param[in] ctx Compile context
2420 * @param[in] node_p Parsed container node.
2421 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
2422 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2423 * is enriched with the container-specific information.
2424 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2425 */
Radek Krejci19a96102018-11-15 13:38:09 +01002426static LY_ERR
2427lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
2428{
2429 struct lysp_node_container *cont_p = (struct lysp_node_container*)node_p;
2430 struct lysc_node_container *cont = (struct lysc_node_container*)node;
2431 struct lysp_node *child_p;
2432 unsigned int u;
2433 LY_ERR ret = LY_SUCCESS;
2434
2435 COMPILE_MEMBER_GOTO(ctx, cont_p->when, cont->when, options, lys_compile_when, ret, done);
2436 COMPILE_ARRAY_GOTO(ctx, cont_p->iffeatures, cont->iffeatures, options, u, lys_compile_iffeature, ret, done);
2437
2438 LY_LIST_FOR(cont_p->child, child_p) {
2439 LY_CHECK_RET(lys_compile_node(ctx, child_p, options, node));
2440 }
2441
2442 COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, options, u, lys_compile_must, ret, done);
2443 //COMPILE_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, options, u, lys_compile_action, ret, done);
2444 //COMPILE_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, options, u, lys_compile_notif, ret, done);
2445
2446done:
2447 return ret;
2448}
2449
Radek Krejcia3045382018-11-22 14:30:31 +01002450/**
2451 * @brief Compile parsed leaf node information.
2452 * @param[in] ctx Compile context
2453 * @param[in] node_p Parsed leaf node.
2454 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
2455 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2456 * is enriched with the leaf-specific information.
2457 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2458 */
Radek Krejci19a96102018-11-15 13:38:09 +01002459static LY_ERR
2460lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *node)
2461{
2462 struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf*)node_p;
2463 struct lysc_node_leaf *leaf = (struct lysc_node_leaf*)node;
2464 unsigned int u;
2465 LY_ERR ret = LY_SUCCESS;
2466
2467 COMPILE_MEMBER_GOTO(ctx, leaf_p->when, leaf->when, options, lys_compile_when, ret, done);
2468 COMPILE_ARRAY_GOTO(ctx, leaf_p->iffeatures, leaf->iffeatures, options, u, lys_compile_iffeature, ret, done);
2469
2470 COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, options, u, lys_compile_must, ret, done);
2471 ret = lys_compile_type(ctx, leaf_p, options, &leaf->type);
2472 LY_CHECK_GOTO(ret, done);
2473
Radek Krejcia3045382018-11-22 14:30:31 +01002474 if (leaf->type->basetype == LY_TYPE_LEAFREF) {
2475 /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
2476 ly_set_add(&ctx->unres, leaf, 0);
2477 }
2478
Radek Krejci19a96102018-11-15 13:38:09 +01002479 DUP_STRING(ctx->ctx, leaf_p->units, leaf->units);
2480 DUP_STRING(ctx->ctx, leaf_p->dflt, leaf->dflt);
2481done:
2482 return ret;
2483}
2484
Radek Krejcia3045382018-11-22 14:30:31 +01002485/**
2486 * @brief Compile parsed schema node information.
2487 * @param[in] ctx Compile context
2488 * @param[in] node_p Parsed schema node.
2489 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
2490 * @param[in] parent Compiled parent node where the current node is supposed to be connected. It is
2491 * NULL for top-level nodes, in such a case the module where the node will be connected is taken from
2492 * the compile context.
2493 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2494 */
Radek Krejci19a96102018-11-15 13:38:09 +01002495static LY_ERR
2496lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *node_p, int options, struct lysc_node *parent)
2497{
2498 LY_ERR ret = LY_EVALID;
2499 struct lysc_node *node, **children;
2500 unsigned int u;
2501 LY_ERR (*node_compile_spec)(struct lysc_ctx*, struct lysp_node*, int, struct lysc_node*);
2502
2503 switch (node_p->nodetype) {
2504 case LYS_CONTAINER:
2505 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_container));
2506 node_compile_spec = lys_compile_node_container;
2507 break;
2508 case LYS_LEAF:
2509 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaf));
2510 node_compile_spec = lys_compile_node_leaf;
2511 break;
2512 case LYS_LIST:
2513 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_list));
2514 break;
2515 case LYS_LEAFLIST:
2516 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_leaflist));
2517 break;
Radek Krejci19a96102018-11-15 13:38:09 +01002518 case LYS_CHOICE:
2519 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_choice));
2520 break;
Radek Krejci19a96102018-11-15 13:38:09 +01002521 case LYS_ANYXML:
2522 case LYS_ANYDATA:
2523 node = (struct lysc_node*)calloc(1, sizeof(struct lysc_node_anydata));
2524 break;
2525 default:
2526 LOGINT(ctx->ctx);
2527 return LY_EINT;
2528 }
2529 LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
2530 node->nodetype = node_p->nodetype;
2531 node->module = ctx->mod;
2532 node->prev = node;
2533 node->flags = node_p->flags;
2534
2535 /* config */
2536 if (!(node->flags & LYS_CONFIG_MASK)) {
2537 /* config not explicitely set, inherit it from parent */
2538 if (parent) {
2539 node->flags |= parent->flags & LYS_CONFIG_MASK;
2540 } else {
2541 /* default is config true */
2542 node->flags |= LYS_CONFIG_W;
2543 }
2544 }
2545
2546 /* status - it is not inherited by specification, but it does not make sense to have
2547 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
2548 if (!(node->flags & LYS_STATUS_MASK)) {
2549 if (parent && (parent->flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT))) {
2550 LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
2551 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2552 node->flags |= parent->flags & LYS_STATUS_MASK;
2553 } else {
2554 node->flags |= LYS_STATUS_CURR;
2555 }
2556 } else if (parent) {
2557 /* check status compatibility with the parent */
2558 if ((parent->flags & LYS_STATUS_MASK) > (node->flags & LYS_STATUS_MASK)) {
2559 if (node->flags & LYS_STATUS_CURR) {
2560 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2561 "A \"current\" status is in conflict with the parent's \"%s\" status.",
2562 (parent->flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2563 } else { /* LYS_STATUS_DEPRC */
2564 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
2565 "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
2566 }
2567 goto error;
2568 }
2569 }
2570
2571 if (!(options & LYSC_OPT_FREE_SP)) {
2572 node->sp = node_p;
2573 }
2574 DUP_STRING(ctx->ctx, node_p->name, node->name);
2575 COMPILE_ARRAY_GOTO(ctx, node_p->exts, node->exts, options, u, lys_compile_ext, ret, error);
2576
2577 /* nodetype-specific part */
2578 LY_CHECK_GOTO(node_compile_spec(ctx, node_p, options, node), error);
2579
2580 /* insert into parent's children */
Radek Krejcia3045382018-11-22 14:30:31 +01002581 if (parent) {
2582 if (parent->nodetype == LYS_CHOICE) {
2583 /* TODO exception for cases */
2584 } else if ((children = lysc_node_children(parent))) {
2585 if (!(*children)) {
2586 /* first child */
2587 *children = node;
2588 } else {
2589 /* insert at the end of the parent's children list */
2590 (*children)->prev->next = node;
2591 node->prev = (*children)->prev;
2592 (*children)->prev = node;
2593 }
Radek Krejci19a96102018-11-15 13:38:09 +01002594 }
2595 } else {
2596 /* top-level element */
2597 if (!ctx->mod->compiled->data) {
2598 ctx->mod->compiled->data = node;
2599 } else {
2600 /* insert at the end of the module's top-level nodes list */
2601 ctx->mod->compiled->data->prev->next = node;
2602 node->prev = ctx->mod->compiled->data->prev;
2603 ctx->mod->compiled->data->prev = node;
2604 }
2605 }
2606
2607 return LY_SUCCESS;
2608
2609error:
2610 lysc_node_free(ctx->ctx, node);
2611 return ret;
2612}
2613
Radek Krejcia3045382018-11-22 14:30:31 +01002614/**
2615 * @brief Compile the given YANG module.
2616 * @param[in] mod Module structure where the parsed schema is expected and the compiled schema will be placed.
2617 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
2618 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2619 */
Radek Krejci19a96102018-11-15 13:38:09 +01002620LY_ERR
2621lys_compile(struct lys_module *mod, int options)
2622{
2623 struct lysc_ctx ctx = {0};
2624 struct lysc_module *mod_c;
Radek Krejcia3045382018-11-22 14:30:31 +01002625 struct lysc_type *type;
Radek Krejci19a96102018-11-15 13:38:09 +01002626 struct lysp_module *sp;
2627 struct lysp_node *node_p;
2628 unsigned int u;
2629 LY_ERR ret;
2630
2631 LY_CHECK_ARG_RET(NULL, mod, mod->parsed, mod->parsed->ctx, LY_EINVAL);
2632 sp = mod->parsed;
2633
2634 if (sp->submodule) {
2635 LOGERR(sp->ctx, LY_EINVAL, "Submodules (%s) are not supposed to be compiled, compile only the main modules.", sp->name);
2636 return LY_EINVAL;
2637 }
2638
2639 ctx.ctx = sp->ctx;
2640 ctx.mod = mod;
2641
2642 mod->compiled = mod_c = calloc(1, sizeof *mod_c);
2643 LY_CHECK_ERR_RET(!mod_c, LOGMEM(sp->ctx), LY_EMEM);
2644 mod_c->ctx = sp->ctx;
2645 mod_c->implemented = sp->implemented;
2646 mod_c->latest_revision = sp->latest_revision;
2647 mod_c->version = sp->version;
2648
2649 DUP_STRING(sp->ctx, sp->name, mod_c->name);
2650 DUP_STRING(sp->ctx, sp->ns, mod_c->ns);
2651 DUP_STRING(sp->ctx, sp->prefix, mod_c->prefix);
2652 if (sp->revs) {
2653 DUP_STRING(sp->ctx, sp->revs[0].date, mod_c->revision);
2654 }
2655 COMPILE_ARRAY_GOTO(&ctx, sp->imports, mod_c->imports, options, u, lys_compile_import, ret, error);
2656 COMPILE_ARRAY_GOTO(&ctx, sp->features, mod_c->features, options, u, lys_compile_feature, ret, error);
2657 COMPILE_ARRAY_GOTO(&ctx, sp->identities, mod_c->identities, options, u, lys_compile_identity, ret, error);
2658 if (sp->identities) {
2659 LY_CHECK_RET(lys_compile_identities_derived(&ctx, sp->identities, mod_c->identities));
2660 }
2661
2662 LY_LIST_FOR(sp->data, node_p) {
2663 ret = lys_compile_node(&ctx, node_p, options, NULL);
2664 LY_CHECK_GOTO(ret, error);
2665 }
2666 //COMPILE_ARRAY_GOTO(ctx, sp->rpcs, mod_c->rpcs, options, u, lys_compile_action, ret, error);
2667 //COMPILE_ARRAY_GOTO(ctx, sp->notifs, mod_c->notifs, options, u, lys_compile_notif, ret, error);
2668
2669 COMPILE_ARRAY_GOTO(&ctx, sp->exts, mod_c->exts, options, u, lys_compile_ext, ret, error);
2670
Radek Krejcia3045382018-11-22 14:30:31 +01002671 /* validate leafref's paths and when/must xpaths */
2672 for (u = 0; u < ctx.unres.count; ++u) {
2673 if (((struct lysc_node*)ctx.unres.objs[u])->nodetype == LYS_LEAF) {
2674 type = ((struct lysc_node_leaf*)ctx.unres.objs[u])->type;
2675 if (type->basetype == LY_TYPE_LEAFREF) {
2676 /* validate the path */
2677 ret = lys_compile_leafref_validate(&ctx, ((struct lysc_node*)ctx.unres.objs[u]),
Radek Krejci96a0bfd2018-11-22 15:25:06 +01002678 ((struct lysc_type_leafref*)type)->path, ((struct lysc_type_leafref*)type)->path_context);
Radek Krejcia3045382018-11-22 14:30:31 +01002679 LY_CHECK_GOTO(ret, error);
2680 }
2681 }
2682 }
2683 ly_set_erase(&ctx.unres, NULL);
2684
Radek Krejci19a96102018-11-15 13:38:09 +01002685 if (options & LYSC_OPT_FREE_SP) {
2686 lysp_module_free(mod->parsed);
2687 ((struct lys_module*)mod)->parsed = NULL;
2688 }
2689
2690 ((struct lys_module*)mod)->compiled = mod_c;
2691 return LY_SUCCESS;
2692
2693error:
Radek Krejcia3045382018-11-22 14:30:31 +01002694 ly_set_erase(&ctx.unres, NULL);
Radek Krejci19a96102018-11-15 13:38:09 +01002695 lysc_module_free(mod_c, NULL);
2696 ((struct lys_module*)mod)->compiled = NULL;
2697 return ret;
2698}