Coverage Report

Created: 2025-11-11 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libyang/src/schema_compile_node.c
Line
Count
Source
1
/**
2
 * @file schema_compile_node.c
3
 * @author Radek Krejci <rkrejci@cesnet.cz>
4
 * @brief Schema compilation of common nodes.
5
 *
6
 * Copyright (c) 2015 - 2020 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
#define _GNU_SOURCE /* asprintf, strdup */
16
#include <sys/cdefs.h>
17
18
#include "schema_compile_node.h"
19
20
#include <assert.h>
21
#include <ctype.h>
22
#include <stddef.h>
23
#include <stdint.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "common.h"
29
#include "compat.h"
30
#include "dict.h"
31
#include "log.h"
32
#include "plugins.h"
33
#include "plugins_exts_compile.h"
34
#include "plugins_internal.h"
35
#include "plugins_types.h"
36
#include "schema_compile.h"
37
#include "schema_compile_amend.h"
38
#include "schema_features.h"
39
#include "set.h"
40
#include "tree.h"
41
#include "tree_data.h"
42
#include "tree_edit.h"
43
#include "tree_schema.h"
44
#include "tree_schema_internal.h"
45
#include "xpath.h"
46
47
static struct lysc_ext_instance *
48
lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
49
0
{
50
    /* TODO - extensions, increase refcount */
51
0
    (void) ctx;
52
0
    (void) orig;
53
0
    return NULL;
54
0
}
55
56
/**
57
 * @brief Add/replace a leaf default value in unres.
58
 * Can also be used for a single leaf-list default value.
59
 *
60
 * @param[in] ctx Compile context.
61
 * @param[in] leaf Leaf with the default value.
62
 * @param[in] dflt Default value to use.
63
 * @return LY_ERR value.
64
 */
65
static LY_ERR
66
lysc_unres_leaf_dflt_add(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt)
67
0
{
68
0
    struct lysc_unres_dflt *r = NULL;
69
0
    uint32_t i;
70
71
0
    if (ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING)) {
72
0
        return LY_SUCCESS;
73
0
    }
74
75
0
    for (i = 0; i < ctx->unres->dflts.count; ++i) {
76
0
        if (((struct lysc_unres_dflt *)ctx->unres->dflts.objs[i])->leaf == leaf) {
77
            /* just replace the default */
78
0
            r = ctx->unres->dflts.objs[i];
79
0
            lysp_qname_free(ctx->ctx, r->dflt);
80
0
            free(r->dflt);
81
0
            break;
82
0
        }
83
0
    }
84
0
    if (!r) {
85
        /* add new unres item */
86
0
        r = calloc(1, sizeof *r);
87
0
        LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
88
0
        r->leaf = leaf;
89
90
0
        LY_CHECK_RET(ly_set_add(&ctx->unres->dflts, r, 1, NULL));
91
0
    }
92
93
0
    r->dflt = malloc(sizeof *r->dflt);
94
0
    LY_CHECK_GOTO(!r->dflt, error);
95
0
    LY_CHECK_GOTO(lysp_qname_dup(ctx->ctx, r->dflt, dflt), error);
96
97
0
    return LY_SUCCESS;
98
99
0
error:
100
0
    free(r->dflt);
101
0
    LOGMEM(ctx->ctx);
102
0
    return LY_EMEM;
103
0
}
104
105
/**
106
 * @brief Add/replace a leaf-list default value(s) in unres.
107
 *
108
 * @param[in] ctx Compile context.
109
 * @param[in] llist Leaf-list with the default value.
110
 * @param[in] dflts Sized array of the default values.
111
 * @return LY_ERR value.
112
 */
113
static LY_ERR
114
lysc_unres_llist_dflts_add(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflts)
115
0
{
116
0
    struct lysc_unres_dflt *r = NULL;
117
0
    uint32_t i;
118
119
0
    if (ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING)) {
120
0
        return LY_SUCCESS;
121
0
    }
122
123
0
    for (i = 0; i < ctx->unres->dflts.count; ++i) {
124
0
        if (((struct lysc_unres_dflt *)ctx->unres->dflts.objs[i])->llist == llist) {
125
            /* just replace the defaults */
126
0
            r = ctx->unres->dflts.objs[i];
127
0
            lysp_qname_free(ctx->ctx, r->dflt);
128
0
            free(r->dflt);
129
0
            r->dflt = NULL;
130
0
            FREE_ARRAY(ctx->ctx, r->dflts, lysp_qname_free);
131
0
            r->dflts = NULL;
132
0
            break;
133
0
        }
134
0
    }
135
0
    if (!r) {
136
0
        r = calloc(1, sizeof *r);
137
0
        LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
138
0
        r->llist = llist;
139
140
0
        LY_CHECK_RET(ly_set_add(&ctx->unres->dflts, r, 1, NULL));
141
0
    }
142
143
0
    DUP_ARRAY(ctx->ctx, dflts, r->dflts, lysp_qname_dup);
144
145
0
    return LY_SUCCESS;
146
0
}
147
148
/**
149
 * @brief Duplicate the compiled pattern structure.
150
 *
151
 * Instead of duplicating memory, the reference counter in the @p orig is increased.
152
 *
153
 * @param[in] orig The pattern structure to duplicate.
154
 * @return The duplicated structure to use.
155
 */
156
static struct lysc_pattern *
157
lysc_pattern_dup(struct lysc_pattern *orig)
158
0
{
159
0
    ++orig->refcount;
160
0
    return orig;
161
0
}
162
163
/**
164
 * @brief Duplicate the array of compiled patterns.
165
 *
166
 * The sized array itself is duplicated, but the pattern structures are just shadowed by increasing their reference counter.
167
 *
168
 * @param[in] ctx Libyang context for logging.
169
 * @param[in] orig The patterns sized array to duplicate.
170
 * @return New sized array as a copy of @p orig.
171
 * @return NULL in case of memory allocation error.
172
 */
173
static struct lysc_pattern **
174
lysc_patterns_dup(struct ly_ctx *ctx, struct lysc_pattern **orig)
175
0
{
176
0
    struct lysc_pattern **dup = NULL;
177
0
    LY_ARRAY_COUNT_TYPE u;
178
179
0
    assert(orig);
180
181
0
    LY_ARRAY_CREATE_RET(ctx, dup, LY_ARRAY_COUNT(orig), NULL);
182
0
    LY_ARRAY_FOR(orig, u) {
183
0
        dup[u] = lysc_pattern_dup(orig[u]);
184
0
        LY_ARRAY_INCREMENT(dup);
185
0
    }
186
0
    return dup;
187
0
}
188
189
/**
190
 * @brief Duplicate compiled range structure.
191
 *
192
 * @param[in] ctx Libyang context for logging.
193
 * @param[in] orig The range structure to be duplicated.
194
 * @return New compiled range structure as a copy of @p orig.
195
 * @return NULL in case of memory allocation error.
196
 */
197
static struct lysc_range *
198
lysc_range_dup(struct ly_ctx *ctx, const struct lysc_range *orig)
199
0
{
200
0
    struct lysc_range *dup;
201
0
    LY_ERR ret;
202
203
0
    assert(orig);
204
205
0
    dup = calloc(1, sizeof *dup);
206
0
    LY_CHECK_ERR_RET(!dup, LOGMEM(ctx), NULL);
207
0
    if (orig->parts) {
208
0
        LY_ARRAY_CREATE_GOTO(ctx, dup->parts, LY_ARRAY_COUNT(orig->parts), ret, cleanup);
209
0
        (*((LY_ARRAY_COUNT_TYPE *)(dup->parts) - 1)) = LY_ARRAY_COUNT(orig->parts);
210
0
        memcpy(dup->parts, orig->parts, LY_ARRAY_COUNT(dup->parts) * sizeof *dup->parts);
211
0
    }
212
0
    DUP_STRING_GOTO(ctx, orig->eapptag, dup->eapptag, ret, cleanup);
213
0
    DUP_STRING_GOTO(ctx, orig->emsg, dup->emsg, ret, cleanup);
214
0
    dup->exts = lysc_ext_instance_dup(ctx, orig->exts);
215
216
0
    return dup;
217
0
cleanup:
218
0
    free(dup);
219
0
    (void) ret; /* set but not used due to the return type */
220
0
    return NULL;
221
0
}
222
223
/**
224
 * @brief Compile information from the when statement
225
 *
226
 * @param[in] ctx Compile context.
227
 * @param[in] when_p Parsed when structure.
228
 * @param[in] flags Flags of the parsed node with the when statement.
229
 * @param[in] ctx_node Context node for the when statement.
230
 * @param[out] when Pointer where to store pointer to the created compiled when structure.
231
 * @return LY_ERR value.
232
 */
233
static LY_ERR
234
lys_compile_when_(struct lysc_ctx *ctx, struct lysp_when *when_p, uint16_t flags, const struct lysc_node *ctx_node,
235
        struct lysc_when **when)
236
0
{
237
0
    LY_ERR ret = LY_SUCCESS;
238
0
    LY_VALUE_FORMAT format;
239
240
0
    *when = calloc(1, sizeof **when);
241
0
    LY_CHECK_ERR_RET(!(*when), LOGMEM(ctx->ctx), LY_EMEM);
242
0
    (*when)->refcount = 1;
243
0
    LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, when_p->cond, 0, 1, &(*when)->cond));
244
0
    LY_CHECK_RET(lyplg_type_prefix_data_new(ctx->ctx, when_p->cond, strlen(when_p->cond),
245
0
            LY_VALUE_SCHEMA, ctx->pmod, &format, (void **)&(*when)->prefixes));
246
0
    (*when)->context = (struct lysc_node *)ctx_node;
247
0
    DUP_STRING_GOTO(ctx->ctx, when_p->dsc, (*when)->dsc, ret, done);
248
0
    DUP_STRING_GOTO(ctx->ctx, when_p->ref, (*when)->ref, ret, done);
249
0
    COMPILE_EXTS_GOTO(ctx, when_p->exts, (*when)->exts, (*when), ret, done);
250
0
    (*when)->flags = flags & LYS_STATUS_MASK;
251
252
0
done:
253
0
    return ret;
254
0
}
255
256
LY_ERR
257
lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, uint16_t flags, const struct lysc_node *ctx_node,
258
        struct lysc_node *node, struct lysc_when **when_c)
259
0
{
260
0
    struct lysc_when **new_when, ***node_when;
261
262
0
    assert(when_p);
263
264
    /* get the when array */
265
0
    node_when = lysc_node_when_p(node);
266
267
    /* create new when pointer */
268
0
    LY_ARRAY_NEW_RET(ctx->ctx, *node_when, new_when, LY_EMEM);
269
0
    if (!when_c || !(*when_c)) {
270
        /* compile when */
271
0
        LY_CHECK_RET(lys_compile_when_(ctx, when_p, flags, ctx_node, new_when));
272
273
        /* remember the compiled when for sharing */
274
0
        if (when_c) {
275
0
            *when_c = *new_when;
276
0
        }
277
0
    } else {
278
        /* use the previously compiled when */
279
0
        ++(*when_c)->refcount;
280
0
        *new_when = *when_c;
281
0
    }
282
283
0
    if (!(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
284
        /* do not check "when" semantics in a grouping, but repeat the check for different node because
285
         * of dummy node check */
286
0
        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, node, 0, NULL));
287
0
    }
288
289
0
    return LY_SUCCESS;
290
0
}
291
292
/**
293
 * @brief Compile information from the must statement
294
 * @param[in] ctx Compile context.
295
 * @param[in] must_p The parsed must statement structure.
296
 * @param[in,out] must Prepared (empty) compiled must structure to fill.
297
 * @return LY_ERR value.
298
 */
299
static LY_ERR
300
lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, struct lysc_must *must)
301
0
{
302
0
    LY_ERR ret = LY_SUCCESS;
303
0
    LY_VALUE_FORMAT format;
304
305
0
    LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, must_p->arg.str, 0, 1, &must->cond));
306
0
    LY_CHECK_RET(lyplg_type_prefix_data_new(ctx->ctx, must_p->arg.str, strlen(must_p->arg.str),
307
0
            LY_VALUE_SCHEMA, must_p->arg.mod, &format, (void **)&must->prefixes));
308
0
    DUP_STRING_GOTO(ctx->ctx, must_p->eapptag, must->eapptag, ret, done);
309
0
    DUP_STRING_GOTO(ctx->ctx, must_p->emsg, must->emsg, ret, done);
310
0
    DUP_STRING_GOTO(ctx->ctx, must_p->dsc, must->dsc, ret, done);
311
0
    DUP_STRING_GOTO(ctx->ctx, must_p->ref, must->ref, ret, done);
312
0
    COMPILE_EXTS_GOTO(ctx, must_p->exts, must->exts, must, ret, done);
313
314
0
done:
315
0
    return ret;
316
0
}
317
318
/**
319
 * @brief Validate and normalize numeric value from a range definition.
320
 * @param[in] ctx Compile context.
321
 * @param[in] basetype Base YANG built-in type of the node connected with the range restriction. Actually only LY_TYPE_DEC64 is important to
322
 * allow processing of the fractions. The fraction point is extracted from the value which is then normalize according to given frdigits into
323
 * valcopy to allow easy parsing and storing of the value. libyang stores decimal number without the decimal point which is always recovered from
324
 * the known fraction-digits value. So, with fraction-digits 2, number 3.14 is stored as 314 and number 1 is stored as 100.
325
 * @param[in] frdigits The fraction-digits of the type in case of LY_TYPE_DEC64.
326
 * @param[in] value String value of the range boundary.
327
 * @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.
328
 * @param[out] valcopy NULL-terminated string with the numeric value to parse and store.
329
 * @return LY_ERR value - LY_SUCCESS, LY_EMEM, LY_EVALID (no number) or LY_EINVAL (decimal64 not matching fraction-digits value).
330
 */
331
static LY_ERR
332
range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, uint8_t frdigits, const char *value,
333
        size_t *len, char **valcopy)
334
0
{
335
0
    size_t fraction = 0, size;
336
337
0
    *len = 0;
338
339
0
    assert(value);
340
    /* parse value */
341
0
    if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
342
0
        return LY_EVALID;
343
0
    }
344
345
0
    if ((value[*len] == '-') || (value[*len] == '+')) {
346
0
        ++(*len);
347
0
    }
348
349
0
    while (isdigit(value[*len])) {
350
0
        ++(*len);
351
0
    }
352
353
0
    if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
354
0
        if (basetype == LY_TYPE_DEC64) {
355
0
            goto decimal;
356
0
        } else {
357
0
            *valcopy = strndup(value, *len);
358
0
            return LY_SUCCESS;
359
0
        }
360
0
    }
361
0
    fraction = *len;
362
363
0
    ++(*len);
364
0
    while (isdigit(value[*len])) {
365
0
        ++(*len);
366
0
    }
367
368
0
    if (basetype == LY_TYPE_DEC64) {
369
0
decimal:
370
0
        assert(frdigits);
371
0
        if (fraction && (*len - 1 - fraction > frdigits)) {
372
0
            LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
373
0
                    "Range boundary \"%.*s\" of decimal64 type exceeds defined number (%u) of fraction digits.",
374
0
                    (int)(*len), value, frdigits);
375
0
            return LY_EINVAL;
376
0
        }
377
0
        if (fraction) {
378
0
            size = (*len) + (frdigits - ((*len) - 1 - fraction));
379
0
        } else {
380
0
            size = (*len) + frdigits + 1;
381
0
        }
382
0
        *valcopy = malloc(size * sizeof **valcopy);
383
0
        LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
384
385
0
        (*valcopy)[size - 1] = '\0';
386
0
        if (fraction) {
387
0
            memcpy(&(*valcopy)[0], &value[0], fraction);
388
0
            memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction));
389
0
            memset(&(*valcopy)[(*len) - 1], '0', frdigits - ((*len) - 1 - fraction));
390
0
        } else {
391
0
            memcpy(&(*valcopy)[0], &value[0], *len);
392
0
            memset(&(*valcopy)[*len], '0', frdigits);
393
0
        }
394
0
    }
395
0
    return LY_SUCCESS;
396
0
}
397
398
/**
399
 * @brief Check that values in range are in ascendant order.
400
 * @param[in] unsigned_value Flag to note that we are working with unsigned values.
401
 * @param[in] max Flag to distinguish if checking min or max value. min value must be strictly higher than previous,
402
 * max can be also equal.
403
 * @param[in] value Current value to check.
404
 * @param[in] prev_value The last seen value.
405
 * @return LY_SUCCESS or LY_EEXIST for invalid order.
406
 */
407
static LY_ERR
408
range_part_check_ascendancy(ly_bool unsigned_value, ly_bool max, int64_t value, int64_t prev_value)
409
0
{
410
0
    if (unsigned_value) {
411
0
        if ((max && ((uint64_t)prev_value > (uint64_t)value)) || (!max && ((uint64_t)prev_value >= (uint64_t)value))) {
412
0
            return LY_EEXIST;
413
0
        }
414
0
    } else {
415
0
        if ((max && (prev_value > value)) || (!max && (prev_value >= value))) {
416
0
            return LY_EEXIST;
417
0
        }
418
0
    }
419
0
    return LY_SUCCESS;
420
0
}
421
422
/**
423
 * @brief Set min/max value of the range part.
424
 * @param[in] ctx Compile context.
425
 * @param[in] part Range part structure to fill.
426
 * @param[in] max Flag to distinguish if storing min or max value.
427
 * @param[in] prev The last seen value to check that all values in range are specified in ascendant order.
428
 * @param[in] basetype Type of the value to get know implicit min/max values and other checking rules.
429
 * @param[in] first Flag for the first value of the range to avoid ascendancy order.
430
 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
431
 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
432
 * @param[in] base_range Range from the type from which the current type is derived (if not built-in) to get type's min and max values.
433
 * @param[in,out] value Numeric range value to be stored, if not provided the type's min/max value is set.
434
 * @return LY_ERR value - LY_SUCCESS, LY_EDENIED (value brokes type's boundaries), LY_EVALID (not a number),
435
 * LY_EEXIST (value is smaller than the previous one), LY_EINVAL (decimal64 value does not corresponds with the
436
 * frdigits value), LY_EMEM.
437
 */
438
static LY_ERR
439
range_part_minmax(struct lysc_ctx *ctx, struct lysc_range_part *part, ly_bool max, int64_t prev, LY_DATA_TYPE basetype,
440
        ly_bool first, ly_bool length_restr, uint8_t frdigits, struct lysc_range *base_range, const char **value)
441
0
{
442
0
    LY_ERR ret = LY_SUCCESS;
443
0
    char *valcopy = NULL;
444
0
    size_t len = 0;
445
446
0
    if (value) {
447
0
        ret = range_part_check_value_syntax(ctx, basetype, frdigits, *value, &len, &valcopy);
448
0
        LY_CHECK_GOTO(ret, finalize);
449
0
    }
450
0
    if (!valcopy && base_range) {
451
0
        if (max) {
452
0
            part->max_64 = base_range->parts[LY_ARRAY_COUNT(base_range->parts) - 1].max_64;
453
0
        } else {
454
0
            part->min_64 = base_range->parts[0].min_64;
455
0
        }
456
0
        if (!first) {
457
0
            ret = range_part_check_ascendancy(basetype <= LY_TYPE_STRING ? 1 : 0, max, max ? part->max_64 : part->min_64, prev);
458
0
        }
459
0
        goto finalize;
460
0
    }
461
462
0
    switch (basetype) {
463
0
    case LY_TYPE_INT8: /* range */
464
0
        if (valcopy) {
465
0
            ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-128), INT64_C(127), LY_BASE_DEC, max ? &part->max_64 : &part->min_64);
466
0
        } else if (max) {
467
0
            part->max_64 = INT64_C(127);
468
0
        } else {
469
0
            part->min_64 = INT64_C(-128);
470
0
        }
471
0
        if (!ret && !first) {
472
0
            ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
473
0
        }
474
0
        break;
475
0
    case LY_TYPE_INT16: /* range */
476
0
        if (valcopy) {
477
0
            ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-32768), INT64_C(32767), LY_BASE_DEC,
478
0
                    max ? &part->max_64 : &part->min_64);
479
0
        } else if (max) {
480
0
            part->max_64 = INT64_C(32767);
481
0
        } else {
482
0
            part->min_64 = INT64_C(-32768);
483
0
        }
484
0
        if (!ret && !first) {
485
0
            ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
486
0
        }
487
0
        break;
488
0
    case LY_TYPE_INT32: /* range */
489
0
        if (valcopy) {
490
0
            ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-2147483648), INT64_C(2147483647), LY_BASE_DEC,
491
0
                    max ? &part->max_64 : &part->min_64);
492
0
        } else if (max) {
493
0
            part->max_64 = INT64_C(2147483647);
494
0
        } else {
495
0
            part->min_64 = INT64_C(-2147483648);
496
0
        }
497
0
        if (!ret && !first) {
498
0
            ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
499
0
        }
500
0
        break;
501
0
    case LY_TYPE_INT64: /* range */
502
0
    case LY_TYPE_DEC64: /* range */
503
0
        if (valcopy) {
504
0
            ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807),
505
0
                    LY_BASE_DEC, max ? &part->max_64 : &part->min_64);
506
0
        } else if (max) {
507
0
            part->max_64 = INT64_C(9223372036854775807);
508
0
        } else {
509
0
            part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
510
0
        }
511
0
        if (!ret && !first) {
512
0
            ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
513
0
        }
514
0
        break;
515
0
    case LY_TYPE_UINT8: /* range */
516
0
        if (valcopy) {
517
0
            ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(255), LY_BASE_DEC, max ? &part->max_u64 : &part->min_u64);
518
0
        } else if (max) {
519
0
            part->max_u64 = UINT64_C(255);
520
0
        } else {
521
0
            part->min_u64 = UINT64_C(0);
522
0
        }
523
0
        if (!ret && !first) {
524
0
            ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
525
0
        }
526
0
        break;
527
0
    case LY_TYPE_UINT16: /* range */
528
0
        if (valcopy) {
529
0
            ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(65535), LY_BASE_DEC, max ? &part->max_u64 : &part->min_u64);
530
0
        } else if (max) {
531
0
            part->max_u64 = UINT64_C(65535);
532
0
        } else {
533
0
            part->min_u64 = UINT64_C(0);
534
0
        }
535
0
        if (!ret && !first) {
536
0
            ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
537
0
        }
538
0
        break;
539
0
    case LY_TYPE_UINT32: /* range */
540
0
        if (valcopy) {
541
0
            ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(4294967295), LY_BASE_DEC,
542
0
                    max ? &part->max_u64 : &part->min_u64);
543
0
        } else if (max) {
544
0
            part->max_u64 = UINT64_C(4294967295);
545
0
        } else {
546
0
            part->min_u64 = UINT64_C(0);
547
0
        }
548
0
        if (!ret && !first) {
549
0
            ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
550
0
        }
551
0
        break;
552
0
    case LY_TYPE_UINT64: /* range */
553
0
    case LY_TYPE_STRING: /* length */
554
0
    case LY_TYPE_BINARY: /* length */
555
0
        if (valcopy) {
556
0
            ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(18446744073709551615), LY_BASE_DEC,
557
0
                    max ? &part->max_u64 : &part->min_u64);
558
0
        } else if (max) {
559
0
            part->max_u64 = UINT64_C(18446744073709551615);
560
0
        } else {
561
0
            part->min_u64 = UINT64_C(0);
562
0
        }
563
0
        if (!ret && !first) {
564
0
            ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
565
0
        }
566
0
        break;
567
0
    default:
568
0
        LOGINT(ctx->ctx);
569
0
        ret = LY_EINT;
570
0
    }
571
572
0
finalize:
573
0
    if (ret == LY_EDENIED) {
574
0
        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
575
0
                "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
576
0
                length_restr ? "length" : "range", valcopy ? valcopy : *value);
577
0
    } else if (ret == LY_EVALID) {
578
0
        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
579
0
                "Invalid %s restriction - invalid value \"%s\".",
580
0
                length_restr ? "length" : "range", valcopy ? valcopy : *value);
581
0
    } else if (ret == LY_EEXIST) {
582
0
        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
583
0
                "Invalid %s restriction - values are not in ascending order (%s).",
584
0
                length_restr ? "length" : "range",
585
0
                (valcopy && basetype != LY_TYPE_DEC64) ? valcopy : value ? *value : max ? "max" : "min");
586
0
    } else if (!ret && value) {
587
0
        *value = *value + len;
588
0
    }
589
0
    free(valcopy);
590
0
    return ret;
591
0
}
592
593
/**
594
 * @brief Compile the parsed range restriction.
595
 * @param[in] ctx Compile context.
596
 * @param[in] range_p Parsed range structure to compile.
597
 * @param[in] basetype Base YANG built-in type of the node with the range restriction.
598
 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
599
 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
600
 * @param[in] base_range Range restriction of the type from which the current type is derived. The current
601
 * range restriction must be more restrictive than the base_range.
602
 * @param[in,out] range Pointer to the created current range structure.
603
 * @return LY_ERR value.
604
 */
605
static LY_ERR
606
lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, ly_bool length_restr,
607
        uint8_t frdigits, struct lysc_range *base_range, struct lysc_range **range)
608
0
{
609
0
    LY_ERR ret = LY_SUCCESS;
610
0
    const char *expr;
611
0
    struct lysc_range_part *parts = NULL, *part;
612
0
    ly_bool range_expected = 0, uns;
613
0
    LY_ARRAY_COUNT_TYPE parts_done = 0, u, v;
614
615
0
    assert(range);
616
0
    assert(range_p);
617
618
0
    expr = range_p->arg.str;
619
0
    while (1) {
620
0
        if (isspace(*expr)) {
621
0
            ++expr;
622
0
        } else if (*expr == '\0') {
623
0
            if (range_expected) {
624
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
625
0
                        "Invalid %s restriction - unexpected end of the expression after \"..\" (%s).",
626
0
                        length_restr ? "length" : "range", range_p->arg);
627
0
                ret = LY_EVALID;
628
0
                goto cleanup;
629
0
            } else if (!parts || (parts_done == LY_ARRAY_COUNT(parts))) {
630
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
631
0
                        "Invalid %s restriction - unexpected end of the expression (%s).",
632
0
                        length_restr ? "length" : "range", range_p->arg);
633
0
                ret = LY_EVALID;
634
0
                goto cleanup;
635
0
            }
636
0
            parts_done++;
637
0
            break;
638
0
        } else if (!strncmp(expr, "min", ly_strlen_const("min"))) {
639
0
            if (parts) {
640
                /* min cannot be used elsewhere than in the first part */
641
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
642
0
                        "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
643
0
                        (int)(expr - range_p->arg.str), range_p->arg.str);
644
0
                ret = LY_EVALID;
645
0
                goto cleanup;
646
0
            }
647
0
            expr += ly_strlen_const("min");
648
649
0
            LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
650
0
            LY_CHECK_GOTO(ret = range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, frdigits, base_range, NULL), cleanup);
651
0
            part->max_64 = part->min_64;
652
0
        } else if (*expr == '|') {
653
0
            if (!parts || range_expected) {
654
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
655
0
                        "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
656
0
                ret = LY_EVALID;
657
0
                goto cleanup;
658
0
            }
659
0
            expr++;
660
0
            parts_done++;
661
            /* process next part of the expression */
662
0
        } else if (!strncmp(expr, "..", 2)) {
663
0
            expr += 2;
664
0
            while (isspace(*expr)) {
665
0
                expr++;
666
0
            }
667
0
            if (!parts || (LY_ARRAY_COUNT(parts) == parts_done)) {
668
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
669
0
                        "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
670
0
                ret = LY_EVALID;
671
0
                goto cleanup;
672
0
            }
673
            /* continue expecting the upper boundary */
674
0
            range_expected = 1;
675
0
        } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
676
            /* number */
677
0
            if (range_expected) {
678
0
                part = &parts[LY_ARRAY_COUNT(parts) - 1];
679
0
                LY_CHECK_GOTO(ret = range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, NULL, &expr), cleanup);
680
0
                range_expected = 0;
681
0
            } else {
682
0
                LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
683
0
                LY_CHECK_GOTO(ret = range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_COUNT(parts) - 2].max_64 : 0,
684
0
                        basetype, parts_done ? 0 : 1, length_restr, frdigits, NULL, &expr), cleanup);
685
0
                part->max_64 = part->min_64;
686
0
            }
687
688
            /* continue with possible another expression part */
689
0
        } else if (!strncmp(expr, "max", ly_strlen_const("max"))) {
690
0
            expr += ly_strlen_const("max");
691
0
            while (isspace(*expr)) {
692
0
                expr++;
693
0
            }
694
0
            if (*expr != '\0') {
695
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
696
0
                        length_restr ? "length" : "range", expr);
697
0
                ret = LY_EVALID;
698
0
                goto cleanup;
699
0
            }
700
0
            if (range_expected) {
701
0
                part = &parts[LY_ARRAY_COUNT(parts) - 1];
702
0
                LY_CHECK_GOTO(ret = range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, base_range, NULL), cleanup);
703
0
                range_expected = 0;
704
0
            } else {
705
0
                LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
706
0
                LY_CHECK_GOTO(ret = range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_COUNT(parts) - 2].max_64 : 0,
707
0
                        basetype, parts_done ? 0 : 1, length_restr, frdigits, base_range, NULL), cleanup);
708
0
                part->min_64 = part->max_64;
709
0
            }
710
0
        } else {
711
0
            LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
712
0
                    length_restr ? "length" : "range", expr);
713
0
            ret = LY_EVALID;
714
0
            goto cleanup;
715
0
        }
716
0
    }
717
718
    /* check with the previous range/length restriction */
719
0
    if (base_range) {
720
0
        switch (basetype) {
721
0
        case LY_TYPE_BINARY:
722
0
        case LY_TYPE_UINT8:
723
0
        case LY_TYPE_UINT16:
724
0
        case LY_TYPE_UINT32:
725
0
        case LY_TYPE_UINT64:
726
0
        case LY_TYPE_STRING:
727
0
            uns = 1;
728
0
            break;
729
0
        case LY_TYPE_DEC64:
730
0
        case LY_TYPE_INT8:
731
0
        case LY_TYPE_INT16:
732
0
        case LY_TYPE_INT32:
733
0
        case LY_TYPE_INT64:
734
0
            uns = 0;
735
0
            break;
736
0
        default:
737
0
            LOGINT(ctx->ctx);
738
0
            ret = LY_EINT;
739
0
            goto cleanup;
740
0
        }
741
0
        for (u = v = 0; u < parts_done && v < LY_ARRAY_COUNT(base_range->parts); ++u) {
742
0
            if ((uns && (parts[u].min_u64 < base_range->parts[v].min_u64)) || (!uns && (parts[u].min_64 < base_range->parts[v].min_64))) {
743
0
                goto baseerror;
744
0
            }
745
            /* current lower bound is not lower than the base */
746
0
            if (base_range->parts[v].min_64 == base_range->parts[v].max_64) {
747
                /* base has single value */
748
0
                if (base_range->parts[v].min_64 == parts[u].min_64) {
749
                    /* both lower bounds are the same */
750
0
                    if (parts[u].min_64 != parts[u].max_64) {
751
                        /* current continues with a range */
752
0
                        goto baseerror;
753
0
                    } else {
754
                        /* equal single values, move both forward */
755
0
                        ++v;
756
0
                        continue;
757
0
                    }
758
0
                } else {
759
                    /* base is single value lower than current range, so the
760
                     * value from base range is removed in the current,
761
                     * move only base and repeat checking */
762
0
                    ++v;
763
0
                    --u;
764
0
                    continue;
765
0
                }
766
0
            } else {
767
                /* base is the range */
768
0
                if (parts[u].min_64 == parts[u].max_64) {
769
                    /* current is a single value */
770
0
                    if ((uns && (parts[u].max_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].max_64 > base_range->parts[v].max_64))) {
771
                        /* current is behind the base range, so base range is omitted,
772
                         * move the base and keep the current for further check */
773
0
                        ++v;
774
0
                        --u;
775
0
                    } /* else it is within the base range, so move the current, but keep the base */
776
0
                    continue;
777
0
                } else {
778
                    /* both are ranges - check the higher bound, the lower was already checked */
779
0
                    if ((uns && (parts[u].max_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].max_64 > base_range->parts[v].max_64))) {
780
                        /* higher bound is higher than the current higher bound */
781
0
                        if ((uns && (parts[u].min_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].min_64 > base_range->parts[v].max_64))) {
782
                            /* but the current lower bound is also higher, so the base range is omitted,
783
                             * continue with the same current, but move the base */
784
0
                            --u;
785
0
                            ++v;
786
0
                            continue;
787
0
                        }
788
                        /* current range starts within the base range but end behind it */
789
0
                        goto baseerror;
790
0
                    } else {
791
                        /* current range is smaller than the base,
792
                         * move current, but stay with the base */
793
0
                        continue;
794
0
                    }
795
0
                }
796
0
            }
797
0
        }
798
0
        if (u != parts_done) {
799
0
baseerror:
800
0
            LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
801
0
                    "Invalid %s restriction - the derived restriction (%s) is not equally or more limiting.",
802
0
                    length_restr ? "length" : "range", range_p->arg);
803
0
            ret = LY_EVALID;
804
0
            goto cleanup;
805
0
        }
806
0
    }
807
808
0
    if (!(*range)) {
809
0
        *range = calloc(1, sizeof **range);
810
0
        LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
811
0
    }
812
813
    /* we rewrite the following values as the types chain is being processed */
814
0
    if (range_p->eapptag) {
815
0
        lydict_remove(ctx->ctx, (*range)->eapptag);
816
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->eapptag, 0, &(*range)->eapptag), cleanup);
817
0
    }
818
0
    if (range_p->emsg) {
819
0
        lydict_remove(ctx->ctx, (*range)->emsg);
820
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->emsg, 0, &(*range)->emsg), cleanup);
821
0
    }
822
0
    if (range_p->dsc) {
823
0
        lydict_remove(ctx->ctx, (*range)->dsc);
824
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->dsc, 0, &(*range)->dsc), cleanup);
825
0
    }
826
0
    if (range_p->ref) {
827
0
        lydict_remove(ctx->ctx, (*range)->ref);
828
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->ref, 0, &(*range)->ref), cleanup);
829
0
    }
830
    /* extensions are taken only from the last range by the caller */
831
832
0
    (*range)->parts = parts;
833
0
    parts = NULL;
834
0
cleanup:
835
0
    LY_ARRAY_FREE(parts);
836
837
0
    return ret;
838
0
}
839
840
LY_ERR
841
lys_compile_type_pattern_check(struct ly_ctx *ctx, const char *pattern, pcre2_code **code)
842
0
{
843
0
    size_t idx, idx2, start, end, size, brack;
844
0
    char *perl_regex, *ptr;
845
0
    int err_code, compile_opts;
846
0
    const char *orig_ptr;
847
0
    PCRE2_SIZE err_offset;
848
0
    pcre2_code *code_local;
849
850
0
#define URANGE_LEN 19
851
0
    char *ublock2urange[][2] = {
852
0
        {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
853
0
        {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
854
0
        {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
855
0
        {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
856
0
        {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
857
0
        {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
858
0
        {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
859
0
        {"Greek", "[\\x{0370}-\\x{03FF}]"},
860
0
        {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
861
0
        {"Armenian", "[\\x{0530}-\\x{058F}]"},
862
0
        {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
863
0
        {"Arabic", "[\\x{0600}-\\x{06FF}]"},
864
0
        {"Syriac", "[\\x{0700}-\\x{074F}]"},
865
0
        {"Thaana", "[\\x{0780}-\\x{07BF}]"},
866
0
        {"Devanagari", "[\\x{0900}-\\x{097F}]"},
867
0
        {"Bengali", "[\\x{0980}-\\x{09FF}]"},
868
0
        {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
869
0
        {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
870
0
        {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
871
0
        {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
872
0
        {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
873
0
        {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
874
0
        {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
875
0
        {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
876
0
        {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
877
0
        {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
878
0
        {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
879
0
        {"Myanmar", "[\\x{1000}-\\x{109F}]"},
880
0
        {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
881
0
        {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
882
0
        {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
883
0
        {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
884
0
        {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
885
0
        {"Ogham", "[\\x{1680}-\\x{169F}]"},
886
0
        {"Runic", "[\\x{16A0}-\\x{16FF}]"},
887
0
        {"Khmer", "[\\x{1780}-\\x{17FF}]"},
888
0
        {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
889
0
        {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
890
0
        {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
891
0
        {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
892
0
        {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
893
0
        {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
894
0
        {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
895
0
        {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
896
0
        {"NumberForms", "[\\x{2150}-\\x{218F}]"},
897
0
        {"Arrows", "[\\x{2190}-\\x{21FF}]"},
898
0
        {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
899
0
        {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
900
0
        {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
901
0
        {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
902
0
        {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
903
0
        {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
904
0
        {"BlockElements", "[\\x{2580}-\\x{259F}]"},
905
0
        {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
906
0
        {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
907
0
        {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
908
0
        {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
909
0
        {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
910
0
        {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
911
0
        {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
912
0
        {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
913
0
        {"Hiragana", "[\\x{3040}-\\x{309F}]"},
914
0
        {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
915
0
        {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
916
0
        {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
917
0
        {"Kanbun", "[\\x{3190}-\\x{319F}]"},
918
0
        {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
919
0
        {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
920
0
        {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
921
0
        {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
922
0
        {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
923
0
        {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
924
0
        {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
925
0
        {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
926
0
        {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
927
0
        {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
928
0
        {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
929
0
        {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
930
0
        {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
931
0
        {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
932
0
        {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
933
0
        {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
934
0
        {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
935
0
        {"Specials", "[\\x{FEFF}|\\x{FFF0}-\\x{FFFD}]"},
936
0
        {NULL, NULL}
937
0
    };
938
939
    /* adjust the expression to a Perl equivalent
940
     * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs */
941
942
    /* allocate space for the transformed pattern */
943
0
    size = strlen(pattern) + 1;
944
0
    compile_opts = PCRE2_UTF | PCRE2_ANCHORED | PCRE2_DOLLAR_ENDONLY | PCRE2_NO_AUTO_CAPTURE;
945
0
#ifdef PCRE2_ENDANCHORED
946
0
    compile_opts |= PCRE2_ENDANCHORED;
947
#else
948
    /* add space for trailing $ anchor */
949
    size++;
950
#endif
951
0
    perl_regex = malloc(size);
952
0
    LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx), LY_EMEM);
953
0
    perl_regex[0] = '\0';
954
955
    /* we need to replace all "$" and "^" (that are not in "[]") with "\$" and "\^" */
956
0
    brack = 0;
957
0
    idx = 0;
958
0
    orig_ptr = pattern;
959
0
    while (orig_ptr[0]) {
960
0
        switch (orig_ptr[0]) {
961
0
        case '$':
962
0
        case '^':
963
0
            if (!brack) {
964
                /* make space for the extra character */
965
0
                ++size;
966
0
                perl_regex = ly_realloc(perl_regex, size);
967
0
                LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx), LY_EMEM);
968
969
                /* print escape slash */
970
0
                perl_regex[idx] = '\\';
971
0
                ++idx;
972
0
            }
973
0
            break;
974
0
        case '[':
975
            /* must not be escaped */
976
0
            if ((orig_ptr == pattern) || (orig_ptr[-1] != '\\')) {
977
0
                ++brack;
978
0
            }
979
0
            break;
980
0
        case ']':
981
0
            if ((orig_ptr == pattern) || (orig_ptr[-1] != '\\')) {
982
                /* pattern was checked and compiled already */
983
0
                assert(brack);
984
0
                --brack;
985
0
            }
986
0
            break;
987
0
        default:
988
0
            break;
989
0
        }
990
991
        /* copy char */
992
0
        perl_regex[idx] = orig_ptr[0];
993
994
0
        ++idx;
995
0
        ++orig_ptr;
996
0
    }
997
#ifndef PCRE2_ENDANCHORED
998
    /* anchor match to end of subject */
999
    perl_regex[idx++] = '$';
1000
#endif
1001
0
    perl_regex[idx] = '\0';
1002
1003
    /* substitute Unicode Character Blocks with exact Character Ranges */
1004
0
    while ((ptr = strstr(perl_regex, "\\p{Is"))) {
1005
0
        start = ptr - perl_regex;
1006
1007
0
        ptr = strchr(ptr, '}');
1008
0
        if (!ptr) {
1009
0
            LOGVAL(ctx, LY_VCODE_INREGEXP, pattern, perl_regex + start + 2, "unterminated character property");
1010
0
            free(perl_regex);
1011
0
            return LY_EVALID;
1012
0
        }
1013
0
        end = (ptr - perl_regex) + 1;
1014
1015
        /* need more space */
1016
0
        if (end - start < URANGE_LEN) {
1017
0
            perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (URANGE_LEN - (end - start)) + 1);
1018
0
            LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx); free(perl_regex), LY_EMEM);
1019
0
        }
1020
1021
        /* find our range */
1022
0
        for (idx = 0; ublock2urange[idx][0]; ++idx) {
1023
0
            if (!strncmp(perl_regex + start + ly_strlen_const("\\p{Is"),
1024
0
                    ublock2urange[idx][0], strlen(ublock2urange[idx][0]))) {
1025
0
                break;
1026
0
            }
1027
0
        }
1028
0
        if (!ublock2urange[idx][0]) {
1029
0
            LOGVAL(ctx, LY_VCODE_INREGEXP, pattern, perl_regex + start + 5, "unknown block name");
1030
0
            free(perl_regex);
1031
0
            return LY_EVALID;
1032
0
        }
1033
1034
        /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
1035
0
        for (idx2 = 0, idx = 0; idx2 < start; ++idx2) {
1036
0
            if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
1037
0
                ++idx;
1038
0
            }
1039
0
            if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
1040
0
                --idx;
1041
0
            }
1042
0
        }
1043
0
        if (idx) {
1044
            /* skip brackets */
1045
0
            memmove(perl_regex + start + (URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
1046
0
            memcpy(perl_regex + start, ublock2urange[idx][1] + 1, URANGE_LEN - 2);
1047
0
        } else {
1048
0
            memmove(perl_regex + start + URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
1049
0
            memcpy(perl_regex + start, ublock2urange[idx][1], URANGE_LEN);
1050
0
        }
1051
0
    }
1052
1053
    /* must return 0, already checked during parsing */
1054
0
    code_local = pcre2_compile((PCRE2_SPTR)perl_regex, PCRE2_ZERO_TERMINATED, compile_opts,
1055
0
            &err_code, &err_offset, NULL);
1056
0
    if (!code_local) {
1057
0
        PCRE2_UCHAR err_msg[LY_PCRE2_MSG_LIMIT] = {0};
1058
0
        pcre2_get_error_message(err_code, err_msg, LY_PCRE2_MSG_LIMIT);
1059
0
        LOGVAL(ctx, LY_VCODE_INREGEXP, pattern, perl_regex + err_offset, err_msg);
1060
0
        free(perl_regex);
1061
0
        return LY_EVALID;
1062
0
    }
1063
0
    free(perl_regex);
1064
1065
0
    if (code) {
1066
0
        *code = code_local;
1067
0
    } else {
1068
0
        free(code_local);
1069
0
    }
1070
1071
0
    return LY_SUCCESS;
1072
1073
0
#undef URANGE_LEN
1074
0
}
1075
1076
/**
1077
 * @brief Compile parsed pattern restriction in conjunction with the patterns from base type.
1078
 * @param[in] ctx Compile context.
1079
 * @param[in] patterns_p Array of parsed patterns from the current type to compile.
1080
 * @param[in] base_patterns Compiled patterns from the type from which the current type is derived.
1081
 * Patterns from the base type are inherited to have all the patterns that have to match at one place.
1082
 * @param[out] patterns Pointer to the storage for the patterns of the current type.
1083
 * @return LY_ERR LY_SUCCESS, LY_EMEM, LY_EVALID.
1084
 */
1085
static LY_ERR
1086
lys_compile_type_patterns(struct lysc_ctx *ctx, struct lysp_restr *patterns_p,
1087
        struct lysc_pattern **base_patterns, struct lysc_pattern ***patterns)
1088
0
{
1089
0
    struct lysc_pattern **pattern;
1090
0
    LY_ARRAY_COUNT_TYPE u;
1091
0
    LY_ERR ret = LY_SUCCESS;
1092
1093
    /* first, copy the patterns from the base type */
1094
0
    if (base_patterns) {
1095
0
        *patterns = lysc_patterns_dup(ctx->ctx, base_patterns);
1096
0
        LY_CHECK_ERR_RET(!(*patterns), LOGMEM(ctx->ctx), LY_EMEM);
1097
0
    }
1098
1099
0
    LY_ARRAY_FOR(patterns_p, u) {
1100
0
        LY_ARRAY_NEW_RET(ctx->ctx, (*patterns), pattern, LY_EMEM);
1101
0
        *pattern = calloc(1, sizeof **pattern);
1102
0
        ++(*pattern)->refcount;
1103
1104
0
        ret = lys_compile_type_pattern_check(ctx->ctx, &patterns_p[u].arg.str[1], &(*pattern)->code);
1105
0
        LY_CHECK_RET(ret);
1106
1107
0
        if (patterns_p[u].arg.str[0] == LYSP_RESTR_PATTERN_NACK) {
1108
0
            (*pattern)->inverted = 1;
1109
0
        }
1110
0
        DUP_STRING_GOTO(ctx->ctx, &patterns_p[u].arg.str[1], (*pattern)->expr, ret, done);
1111
0
        DUP_STRING_GOTO(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag, ret, done);
1112
0
        DUP_STRING_GOTO(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg, ret, done);
1113
0
        DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done);
1114
0
        DUP_STRING_GOTO(ctx->ctx, patterns_p[u].ref, (*pattern)->ref, ret, done);
1115
0
        COMPILE_EXTS_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts, (*pattern), ret, done);
1116
0
    }
1117
0
done:
1118
0
    return ret;
1119
0
}
1120
1121
/**
1122
 * @brief map of the possible restrictions combination for the specific built-in type.
1123
 */
1124
static uint16_t type_substmt_map[LY_DATA_TYPE_COUNT] = {
1125
    0 /* LY_TYPE_UNKNOWN */,
1126
    LYS_SET_LENGTH /* LY_TYPE_BINARY */,
1127
    LYS_SET_RANGE /* LY_TYPE_UINT8 */,
1128
    LYS_SET_RANGE /* LY_TYPE_UINT16 */,
1129
    LYS_SET_RANGE /* LY_TYPE_UINT32 */,
1130
    LYS_SET_RANGE /* LY_TYPE_UINT64 */,
1131
    LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
1132
    LYS_SET_BIT /* LY_TYPE_BITS */,
1133
    0 /* LY_TYPE_BOOL */,
1134
    LYS_SET_FRDIGITS | LYS_SET_RANGE /* LY_TYPE_DEC64 */,
1135
    0 /* LY_TYPE_EMPTY */,
1136
    LYS_SET_ENUM /* LY_TYPE_ENUM */,
1137
    LYS_SET_BASE /* LY_TYPE_IDENT */,
1138
    LYS_SET_REQINST /* LY_TYPE_INST */,
1139
    LYS_SET_REQINST | LYS_SET_PATH /* LY_TYPE_LEAFREF */,
1140
    LYS_SET_TYPE /* LY_TYPE_UNION */,
1141
    LYS_SET_RANGE /* LY_TYPE_INT8 */,
1142
    LYS_SET_RANGE /* LY_TYPE_INT16 */,
1143
    LYS_SET_RANGE /* LY_TYPE_INT32 */,
1144
    LYS_SET_RANGE /* LY_TYPE_INT64 */
1145
};
1146
1147
/**
1148
 * @brief stringification of the YANG built-in data types
1149
 */
1150
const char *ly_data_type2str[LY_DATA_TYPE_COUNT] = {
1151
    LY_TYPE_UNKNOWN_STR,
1152
    LY_TYPE_BINARY_STR,
1153
    LY_TYPE_UINT8_STR,
1154
    LY_TYPE_UINT16_STR,
1155
    LY_TYPE_UINT32_STR,
1156
    LY_TYPE_UINT64_STR,
1157
    LY_TYPE_STRING_STR,
1158
    LY_TYPE_BITS_STR,
1159
    LY_TYPE_BOOL_STR,
1160
    LY_TYPE_DEC64_STR,
1161
    LY_TYPE_EMPTY_STR,
1162
    LY_TYPE_ENUM_STR,
1163
    LY_TYPE_IDENT_STR,
1164
    LY_TYPE_INST_STR,
1165
    LY_TYPE_LEAFREF_STR,
1166
    LY_TYPE_UNION_STR,
1167
    LY_TYPE_INT8_STR,
1168
    LY_TYPE_INT16_STR,
1169
    LY_TYPE_INT32_STR,
1170
    LY_TYPE_INT64_STR
1171
};
1172
1173
/**
1174
 * @brief Compile parsed type's enum structures (for enumeration and bits types).
1175
 * @param[in] ctx Compile context.
1176
 * @param[in] enums_p Array of the parsed enum structures to compile.
1177
 * @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.
1178
 * @param[in] base_enums Array of the compiled enums information from the (latest) base type to check if the current enums are compatible.
1179
 * @param[out] bitenums Newly created array of the compiled bitenums information for the current type.
1180
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
1181
 */
1182
static LY_ERR
1183
lys_compile_type_enums(struct lysc_ctx *ctx, struct lysp_type_enum *enums_p, LY_DATA_TYPE basetype,
1184
        struct lysc_type_bitenum_item *base_enums, struct lysc_type_bitenum_item **bitenums)
1185
0
{
1186
0
    LY_ERR ret = LY_SUCCESS;
1187
0
    LY_ARRAY_COUNT_TYPE u, v, match = 0;
1188
0
    int32_t highest_value = INT32_MIN, cur_val = INT32_MIN;
1189
0
    uint32_t highest_position = 0, cur_pos = 0;
1190
0
    struct lysc_type_bitenum_item *e, storage;
1191
0
    ly_bool enabled;
1192
1193
0
    if (base_enums && (ctx->pmod->version < LYS_VERSION_1_1)) {
1194
0
        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "%s type can be subtyped only in YANG 1.1 modules.",
1195
0
                basetype == LY_TYPE_ENUM ? "Enumeration" : "Bits");
1196
0
        return LY_EVALID;
1197
0
    }
1198
1199
0
    LY_ARRAY_FOR(enums_p, u) {
1200
        /* perform all checks */
1201
0
        if (base_enums) {
1202
            /* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
1203
0
            LY_ARRAY_FOR(base_enums, v) {
1204
0
                if (!strcmp(enums_p[u].name, base_enums[v].name)) {
1205
0
                    break;
1206
0
                }
1207
0
            }
1208
0
            if (v == LY_ARRAY_COUNT(base_enums)) {
1209
0
                LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1210
0
                        "Invalid %s - derived type adds new item \"%s\".",
1211
0
                        basetype == LY_TYPE_ENUM ? "enumeration" : "bits", enums_p[u].name);
1212
0
                return LY_EVALID;
1213
0
            }
1214
0
            match = v;
1215
0
        }
1216
1217
0
        if (basetype == LY_TYPE_ENUM) {
1218
0
            if (enums_p[u].flags & LYS_SET_VALUE) {
1219
                /* value assigned by model */
1220
0
                cur_val = (int32_t)enums_p[u].value;
1221
                /* check collision with other values */
1222
0
                LY_ARRAY_FOR(*bitenums, v) {
1223
0
                    if (cur_val == (*bitenums)[v].value) {
1224
0
                        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1225
0
                                "Invalid enumeration - value %d collide in items \"%s\" and \"%s\".",
1226
0
                                cur_val, enums_p[u].name, (*bitenums)[v].name);
1227
0
                        return LY_EVALID;
1228
0
                    }
1229
0
                }
1230
0
            } else if (base_enums) {
1231
                /* inherit the assigned value */
1232
0
                cur_val = base_enums[match].value;
1233
0
            } else {
1234
                /* assign value automatically */
1235
0
                if (u == 0) {
1236
0
                    cur_val = 0;
1237
0
                } else if (highest_value == INT32_MAX) {
1238
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1239
0
                            "Invalid enumeration - it is not possible to auto-assign enum value for "
1240
0
                            "\"%s\" since the highest value is already 2147483647.", enums_p[u].name);
1241
0
                    return LY_EVALID;
1242
0
                } else {
1243
0
                    cur_val = highest_value + 1;
1244
0
                }
1245
0
            }
1246
1247
            /* save highest value for auto assing */
1248
0
            if (highest_value < cur_val) {
1249
0
                highest_value = cur_val;
1250
0
            }
1251
0
        } else { /* LY_TYPE_BITS */
1252
0
            if (enums_p[u].flags & LYS_SET_VALUE) {
1253
                /* value assigned by model */
1254
0
                cur_pos = (uint32_t)enums_p[u].value;
1255
                /* check collision with other values */
1256
0
                LY_ARRAY_FOR(*bitenums, v) {
1257
0
                    if (cur_pos == (*bitenums)[v].position) {
1258
0
                        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1259
0
                                "Invalid bits - position %u collide in items \"%s\" and \"%s\".",
1260
0
                                cur_pos, enums_p[u].name, (*bitenums)[v].name);
1261
0
                        return LY_EVALID;
1262
0
                    }
1263
0
                }
1264
0
            } else if (base_enums) {
1265
                /* inherit the assigned value */
1266
0
                cur_pos = base_enums[match].position;
1267
0
            } else {
1268
                /* assign value automatically */
1269
0
                if (u == 0) {
1270
0
                    cur_pos = 0;
1271
0
                } else if (highest_position == UINT32_MAX) {
1272
                    /* counter overflow */
1273
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1274
0
                            "Invalid bits - it is not possible to auto-assign bit position for "
1275
0
                            "\"%s\" since the highest value is already 4294967295.", enums_p[u].name);
1276
0
                    return LY_EVALID;
1277
0
                } else {
1278
0
                    cur_pos = highest_position + 1;
1279
0
                }
1280
0
            }
1281
1282
            /* save highest position for auto assing */
1283
0
            if (highest_position < cur_pos) {
1284
0
                highest_position = cur_pos;
1285
0
            }
1286
0
        }
1287
1288
        /* the assigned values must not change from the derived type */
1289
0
        if (base_enums) {
1290
0
            if (basetype == LY_TYPE_ENUM) {
1291
0
                if (cur_val != base_enums[match].value) {
1292
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1293
0
                            "Invalid enumeration - value of the item \"%s\" has changed from %d to %d in the derived type.",
1294
0
                            enums_p[u].name, base_enums[match].value, cur_val);
1295
0
                    return LY_EVALID;
1296
0
                }
1297
0
            } else {
1298
0
                if (cur_pos != base_enums[match].position) {
1299
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1300
0
                            "Invalid bits - position of the item \"%s\" has changed from %u to %u in the derived type.",
1301
0
                            enums_p[u].name, base_enums[match].position, cur_pos);
1302
0
                    return LY_EVALID;
1303
0
                }
1304
0
            }
1305
0
        }
1306
1307
        /* evaluate if-ffeatures */
1308
0
        LY_CHECK_RET(lys_eval_iffeatures(ctx->ctx, enums_p[u].iffeatures, &enabled));
1309
0
        if (!enabled) {
1310
0
            continue;
1311
0
        }
1312
1313
        /* add new enum/bit */
1314
0
        LY_ARRAY_NEW_RET(ctx->ctx, *bitenums, e, LY_EMEM);
1315
0
        DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
1316
0
        DUP_STRING_GOTO(ctx->ctx, enums_p[u].dsc, e->dsc, ret, done);
1317
0
        DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
1318
0
        e->flags = (enums_p[u].flags & LYS_FLAGS_COMPILED_MASK) | (basetype == LY_TYPE_ENUM ? LYS_IS_ENUM : 0);
1319
0
        if (basetype == LY_TYPE_ENUM) {
1320
0
            e->value = cur_val;
1321
0
        } else {
1322
0
            e->position = cur_pos;
1323
0
        }
1324
0
        COMPILE_EXTS_GOTO(ctx, enums_p[u].exts, e->exts, e, ret, done);
1325
1326
0
        if (basetype == LY_TYPE_BITS) {
1327
            /* keep bits ordered by position */
1328
0
            for (v = u; v && (*bitenums)[v - 1].position > e->position; --v) {}
1329
0
            if (v != u) {
1330
0
                memcpy(&storage, e, sizeof *e);
1331
0
                memmove(&(*bitenums)[v + 1], &(*bitenums)[v], (u - v) * sizeof **bitenums);
1332
0
                memcpy(&(*bitenums)[v], &storage, sizeof storage);
1333
0
            }
1334
0
        }
1335
0
    }
1336
1337
0
done:
1338
0
    return ret;
1339
0
}
1340
1341
static LY_ERR
1342
lys_compile_type_union(struct lysc_ctx *ctx, struct lysp_type *ptypes, struct lysp_node *context_pnode, uint16_t context_flags,
1343
        const char *context_name, struct lysc_type ***utypes_p)
1344
0
{
1345
0
    LY_ERR ret = LY_SUCCESS;
1346
0
    struct lysc_type **utypes = *utypes_p;
1347
0
    struct lysc_type_union *un_aux = NULL;
1348
1349
0
    LY_ARRAY_CREATE_GOTO(ctx->ctx, utypes, LY_ARRAY_COUNT(ptypes), ret, error);
1350
0
    for (LY_ARRAY_COUNT_TYPE u = 0, additional = 0; u < LY_ARRAY_COUNT(ptypes); ++u) {
1351
0
        ret = lys_compile_type(ctx, context_pnode, context_flags, context_name, &ptypes[u], &utypes[u + additional],
1352
0
                NULL, NULL);
1353
0
        LY_CHECK_GOTO(ret, error);
1354
0
        if (utypes[u + additional]->basetype == LY_TYPE_UNION) {
1355
            /* add space for additional types from the union subtype */
1356
0
            un_aux = (struct lysc_type_union *)utypes[u + additional];
1357
0
            LY_ARRAY_CREATE_GOTO(ctx->ctx, utypes,
1358
0
                    LY_ARRAY_COUNT(ptypes) + additional + LY_ARRAY_COUNT(un_aux->types) - LY_ARRAY_COUNT(utypes), ret, error);
1359
1360
            /* copy subtypes of the subtype union */
1361
0
            for (LY_ARRAY_COUNT_TYPE v = 0; v < LY_ARRAY_COUNT(un_aux->types); ++v) {
1362
0
                if (un_aux->types[v]->basetype == LY_TYPE_LEAFREF) {
1363
0
                    struct lysc_type_leafref *lref;
1364
1365
                    /* duplicate the whole structure because of the instance-specific path resolving for realtype */
1366
0
                    utypes[u + additional] = calloc(1, sizeof(struct lysc_type_leafref));
1367
0
                    LY_CHECK_ERR_GOTO(!utypes[u + additional], LOGMEM(ctx->ctx); ret = LY_EMEM, error);
1368
0
                    lref = (struct lysc_type_leafref *)utypes[u + additional];
1369
1370
0
                    lref->basetype = LY_TYPE_LEAFREF;
1371
0
                    ret = lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)un_aux->types[v])->path, &lref->path);
1372
0
                    LY_CHECK_GOTO(ret, error);
1373
0
                    lref->refcount = 1;
1374
0
                    lref->cur_mod = ((struct lysc_type_leafref *)un_aux->types[v])->cur_mod;
1375
0
                    lref->require_instance = ((struct lysc_type_leafref *)un_aux->types[v])->require_instance;
1376
0
                    ret = lyplg_type_prefix_data_dup(ctx->ctx, LY_VALUE_SCHEMA_RESOLVED,
1377
0
                            ((struct lysc_type_leafref *)un_aux->types[v])->prefixes, (void **)&lref->prefixes);
1378
0
                    LY_CHECK_GOTO(ret, error);
1379
                    /* TODO extensions */
1380
1381
0
                } else {
1382
0
                    utypes[u + additional] = un_aux->types[v];
1383
0
                    ++un_aux->types[v]->refcount;
1384
0
                }
1385
0
                ++additional;
1386
0
                LY_ARRAY_INCREMENT(utypes);
1387
0
            }
1388
            /* compensate u increment in main loop */
1389
0
            --additional;
1390
1391
            /* free the replaced union subtype */
1392
0
            lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux);
1393
0
            un_aux = NULL;
1394
0
        } else {
1395
0
            LY_ARRAY_INCREMENT(utypes);
1396
0
        }
1397
0
    }
1398
1399
0
    *utypes_p = utypes;
1400
0
    return LY_SUCCESS;
1401
1402
0
error:
1403
0
    if (un_aux) {
1404
0
        lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux);
1405
0
    }
1406
0
    *utypes_p = utypes;
1407
0
    return ret;
1408
0
}
1409
1410
/**
1411
 * @brief The core of the lys_compile_type() - compile information about the given type (from typedef or leaf/leaf-list).
1412
 * @param[in] ctx Compile context.
1413
 * @param[in] context_pnode Schema node where the type/typedef is placed to correctly find the base types.
1414
 * @param[in] context_flags Flags of the context node or the referencing typedef to correctly check status of referencing and referenced objects.
1415
 * @param[in] context_name Name of the context node or referencing typedef for logging.
1416
 * @param[in] type_p Parsed type to compile.
1417
 * @param[in] basetype Base YANG built-in type of the type to compile.
1418
 * @param[in] tpdfname Name of the type's typedef, serves as a flag - if it is leaf/leaf-list's type, it is NULL.
1419
 * @param[in] base The latest base (compiled) type from which the current type is being derived.
1420
 * @param[out] type Newly created type structure with the filled information about the type.
1421
 * @return LY_ERR value.
1422
 */
1423
static LY_ERR
1424
lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags, const char *context_name,
1425
        struct lysp_type *type_p, LY_DATA_TYPE basetype, const char *tpdfname, struct lysc_type *base, struct lysc_type **type)
1426
0
{
1427
0
    LY_ERR ret = LY_SUCCESS;
1428
0
    struct lysc_type_bin *bin;
1429
0
    struct lysc_type_num *num;
1430
0
    struct lysc_type_str *str;
1431
0
    struct lysc_type_bits *bits;
1432
0
    struct lysc_type_enum *enumeration;
1433
0
    struct lysc_type_dec *dec;
1434
0
    struct lysc_type_identityref *idref;
1435
0
    struct lysc_type_leafref *lref;
1436
0
    struct lysc_type_union *un;
1437
1438
0
    switch (basetype) {
1439
0
    case LY_TYPE_BINARY:
1440
0
        bin = (struct lysc_type_bin *)(*type);
1441
1442
        /* RFC 7950 9.8.1, 9.4.4 - length, number of octets it contains */
1443
0
        if (type_p->length) {
1444
0
            LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
1445
0
                    base ? ((struct lysc_type_bin *)base)->length : NULL, &bin->length));
1446
0
            if (!tpdfname) {
1447
0
                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, bin->length->exts, bin->length, ret, cleanup);
1448
0
            }
1449
0
        }
1450
0
        break;
1451
0
    case LY_TYPE_BITS:
1452
        /* RFC 7950 9.7 - bits */
1453
0
        bits = (struct lysc_type_bits *)(*type);
1454
0
        if (type_p->bits) {
1455
0
            LY_CHECK_RET(lys_compile_type_enums(ctx, type_p->bits, basetype,
1456
0
                    base ? (struct lysc_type_bitenum_item *)((struct lysc_type_bits *)base)->bits : NULL,
1457
0
                    (struct lysc_type_bitenum_item **)&bits->bits));
1458
0
        }
1459
1460
0
        if (!base && !type_p->flags) {
1461
            /* type derived from bits built-in type must contain at least one bit */
1462
0
            if (tpdfname) {
1463
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "bit", "bits type ", tpdfname);
1464
0
            } else {
1465
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "bit", "bits type", "");
1466
0
            }
1467
0
            return LY_EVALID;
1468
0
        }
1469
0
        break;
1470
0
    case LY_TYPE_DEC64:
1471
0
        dec = (struct lysc_type_dec *)(*type);
1472
1473
        /* RFC 7950 9.3.4 - fraction-digits */
1474
0
        if (!base) {
1475
0
            if (!type_p->fraction_digits) {
1476
0
                if (tpdfname) {
1477
0
                    LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type ", tpdfname);
1478
0
                } else {
1479
0
                    LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type", "");
1480
0
                }
1481
0
                return LY_EVALID;
1482
0
            }
1483
0
            dec->fraction_digits = type_p->fraction_digits;
1484
0
        } else {
1485
0
            if (type_p->fraction_digits) {
1486
                /* fraction digits is prohibited in types not directly derived from built-in decimal64 */
1487
0
                if (tpdfname) {
1488
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1489
0
                            "Invalid fraction-digits substatement for type \"%s\" not directly derived from decimal64 built-in type.",
1490
0
                            tpdfname);
1491
0
                } else {
1492
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1493
0
                            "Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.");
1494
0
                }
1495
0
                return LY_EVALID;
1496
0
            }
1497
0
            dec->fraction_digits = ((struct lysc_type_dec *)base)->fraction_digits;
1498
0
        }
1499
1500
        /* RFC 7950 9.2.4 - range */
1501
0
        if (type_p->range) {
1502
0
            LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, dec->fraction_digits,
1503
0
                    base ? ((struct lysc_type_dec *)base)->range : NULL, &dec->range));
1504
0
            if (!tpdfname) {
1505
0
                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, dec->range->exts, dec->range, ret, cleanup);
1506
0
            }
1507
0
        }
1508
0
        break;
1509
0
    case LY_TYPE_STRING:
1510
0
        str = (struct lysc_type_str *)(*type);
1511
1512
        /* RFC 7950 9.4.4 - length */
1513
0
        if (type_p->length) {
1514
0
            LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
1515
0
                    base ? ((struct lysc_type_str *)base)->length : NULL, &str->length));
1516
0
            if (!tpdfname) {
1517
0
                COMPILE_EXTS_GOTO(ctx, type_p->length->exts, str->length->exts, str->length, ret, cleanup);
1518
0
            }
1519
0
        } else if (base && ((struct lysc_type_str *)base)->length) {
1520
0
            str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str *)base)->length);
1521
0
        }
1522
1523
        /* RFC 7950 9.4.5 - pattern */
1524
0
        if (type_p->patterns) {
1525
0
            LY_CHECK_RET(lys_compile_type_patterns(ctx, type_p->patterns,
1526
0
                    base ? ((struct lysc_type_str *)base)->patterns : NULL, &str->patterns));
1527
0
        } else if (base && ((struct lysc_type_str *)base)->patterns) {
1528
0
            str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str *)base)->patterns);
1529
0
        }
1530
0
        break;
1531
0
    case LY_TYPE_ENUM:
1532
0
        enumeration = (struct lysc_type_enum *)(*type);
1533
1534
        /* RFC 7950 9.6 - enum */
1535
0
        if (type_p->enums) {
1536
0
            LY_CHECK_RET(lys_compile_type_enums(ctx, type_p->enums, basetype,
1537
0
                    base ? ((struct lysc_type_enum *)base)->enums : NULL, &enumeration->enums));
1538
0
        }
1539
1540
0
        if (!base && !type_p->flags) {
1541
            /* type derived from enumerations built-in type must contain at least one enum */
1542
0
            if (tpdfname) {
1543
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type ", tpdfname);
1544
0
            } else {
1545
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type", "");
1546
0
            }
1547
0
            return LY_EVALID;
1548
0
        }
1549
0
        break;
1550
0
    case LY_TYPE_INT8:
1551
0
    case LY_TYPE_UINT8:
1552
0
    case LY_TYPE_INT16:
1553
0
    case LY_TYPE_UINT16:
1554
0
    case LY_TYPE_INT32:
1555
0
    case LY_TYPE_UINT32:
1556
0
    case LY_TYPE_INT64:
1557
0
    case LY_TYPE_UINT64:
1558
0
        num = (struct lysc_type_num *)(*type);
1559
1560
        /* RFC 6020 9.2.4 - range */
1561
0
        if (type_p->range) {
1562
0
            LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, 0,
1563
0
                    base ? ((struct lysc_type_num *)base)->range : NULL, &num->range));
1564
0
            if (!tpdfname) {
1565
0
                COMPILE_EXTS_GOTO(ctx, type_p->range->exts, num->range->exts, num->range, ret, cleanup);
1566
0
            }
1567
0
        }
1568
0
        break;
1569
0
    case LY_TYPE_IDENT:
1570
0
        idref = (struct lysc_type_identityref *)(*type);
1571
1572
        /* RFC 7950 9.10.2 - base */
1573
0
        if (type_p->bases) {
1574
0
            if (base) {
1575
                /* only the directly derived identityrefs can contain base specification */
1576
0
                if (tpdfname) {
1577
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1578
0
                            "Invalid base substatement for the type \"%s\" not directly derived from identityref built-in type.",
1579
0
                            tpdfname);
1580
0
                } else {
1581
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1582
0
                            "Invalid base substatement for the type not directly derived from identityref built-in type.");
1583
0
                }
1584
0
                return LY_EVALID;
1585
0
            }
1586
0
            LY_CHECK_RET(lys_compile_identity_bases(ctx, type_p->pmod, type_p->bases, NULL, &idref->bases, NULL));
1587
0
        }
1588
1589
0
        if (!base && !type_p->flags) {
1590
            /* type derived from identityref built-in type must contain at least one base */
1591
0
            if (tpdfname) {
1592
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "base", "identityref type ", tpdfname);
1593
0
            } else {
1594
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "base", "identityref type", "");
1595
0
            }
1596
0
            return LY_EVALID;
1597
0
        }
1598
0
        break;
1599
0
    case LY_TYPE_LEAFREF:
1600
0
        lref = (struct lysc_type_leafref *)*type;
1601
1602
        /* RFC 7950 9.9.3 - require-instance */
1603
0
        if (type_p->flags & LYS_SET_REQINST) {
1604
0
            if (type_p->pmod->version < LYS_VERSION_1_1) {
1605
0
                if (tpdfname) {
1606
0
                    LOGVAL(ctx->ctx, LYVE_SEMANTICS,
1607
0
                            "Leafref type \"%s\" can be restricted by require-instance statement only in YANG 1.1 modules.", tpdfname);
1608
0
                } else {
1609
0
                    LOGVAL(ctx->ctx, LYVE_SEMANTICS,
1610
0
                            "Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.");
1611
0
                }
1612
0
                return LY_EVALID;
1613
0
            }
1614
0
            lref->require_instance = type_p->require_instance;
1615
0
        } else if (base) {
1616
            /* inherit */
1617
0
            lref->require_instance = ((struct lysc_type_leafref *)base)->require_instance;
1618
0
        } else {
1619
            /* default is true */
1620
0
            lref->require_instance = 1;
1621
0
        }
1622
0
        if (type_p->path) {
1623
0
            LY_VALUE_FORMAT format;
1624
1625
0
            LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, type_p->path, &lref->path));
1626
0
            LY_CHECK_RET(lyplg_type_prefix_data_new(ctx->ctx, type_p->path->expr, strlen(type_p->path->expr),
1627
0
                    LY_VALUE_SCHEMA, type_p->pmod, &format, (void **)&lref->prefixes));
1628
0
        } else if (base) {
1629
0
            LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)base)->path, &lref->path));
1630
0
            LY_CHECK_RET(lyplg_type_prefix_data_dup(ctx->ctx, LY_VALUE_SCHEMA_RESOLVED,
1631
0
                    ((struct lysc_type_leafref *)base)->prefixes, (void **)&lref->prefixes));
1632
0
        } else if (tpdfname) {
1633
0
            LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "path", "leafref type ", tpdfname);
1634
0
            return LY_EVALID;
1635
0
        } else {
1636
0
            LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "path", "leafref type", "");
1637
0
            return LY_EVALID;
1638
0
        }
1639
0
        lref->cur_mod = type_p->pmod->mod;
1640
0
        break;
1641
0
    case LY_TYPE_INST:
1642
        /* RFC 7950 9.9.3 - require-instance */
1643
0
        if (type_p->flags & LYS_SET_REQINST) {
1644
0
            ((struct lysc_type_instanceid *)(*type))->require_instance = type_p->require_instance;
1645
0
        } else {
1646
            /* default is true */
1647
0
            ((struct lysc_type_instanceid *)(*type))->require_instance = 1;
1648
0
        }
1649
0
        break;
1650
0
    case LY_TYPE_UNION:
1651
0
        un = (struct lysc_type_union *)(*type);
1652
1653
        /* RFC 7950 7.4 - type */
1654
0
        if (type_p->types) {
1655
0
            if (base) {
1656
                /* only the directly derived union can contain types specification */
1657
0
                if (tpdfname) {
1658
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1659
0
                            "Invalid type substatement for the type \"%s\" not directly derived from union built-in type.",
1660
0
                            tpdfname);
1661
0
                } else {
1662
0
                    LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG,
1663
0
                            "Invalid type substatement for the type not directly derived from union built-in type.");
1664
0
                }
1665
0
                return LY_EVALID;
1666
0
            }
1667
            /* compile the type */
1668
0
            LY_CHECK_RET(lys_compile_type_union(ctx, type_p->types, context_pnode, context_flags, context_name, &un->types));
1669
0
        }
1670
1671
0
        if (!base && !type_p->flags) {
1672
            /* type derived from union built-in type must contain at least one type */
1673
0
            if (tpdfname) {
1674
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "type", "union type ", tpdfname);
1675
0
            } else {
1676
0
                LOGVAL(ctx->ctx, LY_VCODE_MISSCHILDSTMT, "type", "union type", "");
1677
0
            }
1678
0
            return LY_EVALID;
1679
0
        }
1680
0
        break;
1681
0
    case LY_TYPE_BOOL:
1682
0
    case LY_TYPE_EMPTY:
1683
0
    case LY_TYPE_UNKNOWN: /* just to complete switch */
1684
0
        break;
1685
0
    }
1686
1687
0
    if (tpdfname) {
1688
0
        switch (basetype) {
1689
0
        case LY_TYPE_BINARY:
1690
0
            type_p->compiled = *type;
1691
0
            *type = calloc(1, sizeof(struct lysc_type_bin));
1692
0
            break;
1693
0
        case LY_TYPE_BITS:
1694
0
            type_p->compiled = *type;
1695
0
            *type = calloc(1, sizeof(struct lysc_type_bits));
1696
0
            break;
1697
0
        case LY_TYPE_DEC64:
1698
0
            type_p->compiled = *type;
1699
0
            *type = calloc(1, sizeof(struct lysc_type_dec));
1700
0
            break;
1701
0
        case LY_TYPE_STRING:
1702
0
            type_p->compiled = *type;
1703
0
            *type = calloc(1, sizeof(struct lysc_type_str));
1704
0
            break;
1705
0
        case LY_TYPE_ENUM:
1706
0
            type_p->compiled = *type;
1707
0
            *type = calloc(1, sizeof(struct lysc_type_enum));
1708
0
            break;
1709
0
        case LY_TYPE_INT8:
1710
0
        case LY_TYPE_UINT8:
1711
0
        case LY_TYPE_INT16:
1712
0
        case LY_TYPE_UINT16:
1713
0
        case LY_TYPE_INT32:
1714
0
        case LY_TYPE_UINT32:
1715
0
        case LY_TYPE_INT64:
1716
0
        case LY_TYPE_UINT64:
1717
0
            type_p->compiled = *type;
1718
0
            *type = calloc(1, sizeof(struct lysc_type_num));
1719
0
            break;
1720
0
        case LY_TYPE_IDENT:
1721
0
            type_p->compiled = *type;
1722
0
            *type = calloc(1, sizeof(struct lysc_type_identityref));
1723
0
            break;
1724
0
        case LY_TYPE_LEAFREF:
1725
0
            type_p->compiled = *type;
1726
0
            *type = calloc(1, sizeof(struct lysc_type_leafref));
1727
0
            break;
1728
0
        case LY_TYPE_INST:
1729
0
            type_p->compiled = *type;
1730
0
            *type = calloc(1, sizeof(struct lysc_type_instanceid));
1731
0
            break;
1732
0
        case LY_TYPE_UNION:
1733
0
            type_p->compiled = *type;
1734
0
            *type = calloc(1, sizeof(struct lysc_type_union));
1735
0
            break;
1736
0
        case LY_TYPE_BOOL:
1737
0
        case LY_TYPE_EMPTY:
1738
0
        case LY_TYPE_UNKNOWN: /* just to complete switch */
1739
0
            break;
1740
0
        }
1741
0
    }
1742
0
    LY_CHECK_ERR_RET(!(*type), LOGMEM(ctx->ctx), LY_EMEM);
1743
1744
0
cleanup:
1745
0
    return ret;
1746
0
}
1747
1748
/**
1749
 * @brief Find the correct plugin implementing the described type
1750
 *
1751
 * @param[in] mod Module where the type is defined
1752
 * @param[in] name Name of the type (typedef)
1753
 * @param[in] basetype Type's basetype (when the built-in base plugin is supposed to be used)
1754
 * @return Pointer to the plugin implementing the described data type.
1755
 */
1756
static struct lyplg_type *
1757
lys_compile_type_get_plugin(struct lys_module *mod, const char *name, LY_DATA_TYPE basetype)
1758
0
{
1759
0
    struct lyplg_type *p;
1760
1761
    /* try to find loaded user type plugins */
1762
0
    p = lyplg_find(LYPLG_TYPE, mod->name, mod->revision, name);
1763
0
    if (!p) {
1764
        /* use the internal built-in type implementation */
1765
0
        p = lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[basetype]);
1766
0
    }
1767
1768
0
    return p;
1769
0
}
1770
1771
LY_ERR
1772
lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags, const char *context_name,
1773
        struct lysp_type *type_p, struct lysc_type **type, const char **units, struct lysp_qname **dflt)
1774
0
{
1775
0
    LY_ERR ret = LY_SUCCESS;
1776
0
    ly_bool dummyloops = 0;
1777
0
    struct type_context {
1778
0
        const struct lysp_tpdf *tpdf;
1779
0
        struct lysp_node *node;
1780
0
    } *tctx, *tctx_prev = NULL, *tctx_iter;
1781
0
    LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
1782
0
    struct lysc_type *base = NULL, *prev_type;
1783
0
    struct ly_set tpdf_chain = {0};
1784
1785
0
    (*type) = NULL;
1786
0
    if (dflt) {
1787
0
        *dflt = NULL;
1788
0
    }
1789
1790
0
    tctx = calloc(1, sizeof *tctx);
1791
0
    LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1792
0
    for (ret = lysp_type_find(type_p->name, context_pnode, type_p->pmod, &basetype, &tctx->tpdf, &tctx->node);
1793
0
            ret == LY_SUCCESS;
1794
0
            ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->tpdf->type.pmod,
1795
0
                    &basetype, &tctx->tpdf, &tctx->node)) {
1796
0
        if (basetype) {
1797
0
            break;
1798
0
        }
1799
1800
        /* check status */
1801
0
        ret = lysc_check_status(ctx, context_flags, (void *)type_p->pmod, context_name, tctx->tpdf->flags,
1802
0
                (void *)tctx->tpdf->type.pmod, tctx->node ? tctx->node->name : tctx->tpdf->name);
1803
0
        LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
1804
1805
0
        if (units && !*units) {
1806
            /* inherit units */
1807
0
            DUP_STRING(ctx->ctx, tctx->tpdf->units, *units, ret);
1808
0
            LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
1809
0
        }
1810
0
        if (dflt && !*dflt && tctx->tpdf->dflt.str) {
1811
            /* inherit default */
1812
0
            *dflt = (struct lysp_qname *)&tctx->tpdf->dflt;
1813
0
        }
1814
0
        if (dummyloops && (!units || *units) && dflt && *dflt) {
1815
0
            basetype = ((struct type_context *)tpdf_chain.objs[tpdf_chain.count - 1])->tpdf->type.compiled->basetype;
1816
0
            break;
1817
0
        }
1818
1819
0
        if (tctx->tpdf->type.compiled && (tctx->tpdf->type.compiled->refcount == 1)) {
1820
            /* context recompilation - everything was freed previously (the only reference is from the parsed type itself)
1821
             * and we need now recompile the type again in the updated context. */
1822
0
            lysc_type_free(ctx->ctx, tctx->tpdf->type.compiled);
1823
0
            ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = NULL;
1824
0
        }
1825
1826
0
        if (tctx->tpdf->type.compiled) {
1827
            /* it is not necessary to continue, the rest of the chain was already compiled,
1828
             * but we still may need to inherit default and units values, so start dummy loops */
1829
0
            basetype = tctx->tpdf->type.compiled->basetype;
1830
0
            ret = ly_set_add(&tpdf_chain, tctx, 1, NULL);
1831
0
            LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
1832
1833
0
            if ((units && !*units) || (dflt && !*dflt)) {
1834
0
                dummyloops = 1;
1835
0
                goto preparenext;
1836
0
            } else {
1837
0
                tctx = NULL;
1838
0
                break;
1839
0
            }
1840
0
        }
1841
1842
        /* circular typedef reference detection */
1843
0
        for (uint32_t u = 0; u < tpdf_chain.count; u++) {
1844
            /* local part */
1845
0
            tctx_iter = (struct type_context *)tpdf_chain.objs[u];
1846
0
            if (tctx_iter->tpdf == tctx->tpdf) {
1847
0
                LOGVAL(ctx->ctx, LYVE_REFERENCE,
1848
0
                        "Invalid \"%s\" type reference - circular chain of types detected.", tctx->tpdf->name);
1849
0
                free(tctx);
1850
0
                ret = LY_EVALID;
1851
0
                goto cleanup;
1852
0
            }
1853
0
        }
1854
0
        for (uint32_t u = 0; u < ctx->tpdf_chain.count; u++) {
1855
            /* global part for unions corner case */
1856
0
            tctx_iter = (struct type_context *)ctx->tpdf_chain.objs[u];
1857
0
            if (tctx_iter->tpdf == tctx->tpdf) {
1858
0
                LOGVAL(ctx->ctx, LYVE_REFERENCE,
1859
0
                        "Invalid \"%s\" type reference - circular chain of types detected.", tctx->tpdf->name);
1860
0
                free(tctx);
1861
0
                ret = LY_EVALID;
1862
0
                goto cleanup;
1863
0
            }
1864
0
        }
1865
1866
        /* store information for the following processing */
1867
0
        ret = ly_set_add(&tpdf_chain, tctx, 1, NULL);
1868
0
        LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
1869
1870
0
preparenext:
1871
        /* prepare next loop */
1872
0
        tctx_prev = tctx;
1873
0
        tctx = calloc(1, sizeof *tctx);
1874
0
        LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
1875
0
    }
1876
0
    free(tctx);
1877
1878
    /* allocate type according to the basetype */
1879
0
    switch (basetype) {
1880
0
    case LY_TYPE_BINARY:
1881
0
        *type = calloc(1, sizeof(struct lysc_type_bin));
1882
0
        break;
1883
0
    case LY_TYPE_BITS:
1884
0
        *type = calloc(1, sizeof(struct lysc_type_bits));
1885
0
        break;
1886
0
    case LY_TYPE_BOOL:
1887
0
    case LY_TYPE_EMPTY:
1888
0
        *type = calloc(1, sizeof(struct lysc_type));
1889
0
        break;
1890
0
    case LY_TYPE_DEC64:
1891
0
        *type = calloc(1, sizeof(struct lysc_type_dec));
1892
0
        break;
1893
0
    case LY_TYPE_ENUM:
1894
0
        *type = calloc(1, sizeof(struct lysc_type_enum));
1895
0
        break;
1896
0
    case LY_TYPE_IDENT:
1897
0
        *type = calloc(1, sizeof(struct lysc_type_identityref));
1898
0
        break;
1899
0
    case LY_TYPE_INST:
1900
0
        *type = calloc(1, sizeof(struct lysc_type_instanceid));
1901
0
        break;
1902
0
    case LY_TYPE_LEAFREF:
1903
0
        *type = calloc(1, sizeof(struct lysc_type_leafref));
1904
0
        break;
1905
0
    case LY_TYPE_STRING:
1906
0
        *type = calloc(1, sizeof(struct lysc_type_str));
1907
0
        break;
1908
0
    case LY_TYPE_UNION:
1909
0
        *type = calloc(1, sizeof(struct lysc_type_union));
1910
0
        break;
1911
0
    case LY_TYPE_INT8:
1912
0
    case LY_TYPE_UINT8:
1913
0
    case LY_TYPE_INT16:
1914
0
    case LY_TYPE_UINT16:
1915
0
    case LY_TYPE_INT32:
1916
0
    case LY_TYPE_UINT32:
1917
0
    case LY_TYPE_INT64:
1918
0
    case LY_TYPE_UINT64:
1919
0
        *type = calloc(1, sizeof(struct lysc_type_num));
1920
0
        break;
1921
0
    case LY_TYPE_UNKNOWN:
1922
0
        LOGVAL(ctx->ctx, LYVE_REFERENCE,
1923
0
                "Referenced type \"%s\" not found.", tctx_prev ? tctx_prev->tpdf->type.name : type_p->name);
1924
0
        ret = LY_EVALID;
1925
0
        goto cleanup;
1926
0
    }
1927
0
    LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
1928
0
    if (~type_substmt_map[basetype] & type_p->flags) {
1929
0
        LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid type restrictions for %s type.",
1930
0
                ly_data_type2str[basetype]);
1931
0
        free(*type);
1932
0
        (*type) = NULL;
1933
0
        ret = LY_EVALID;
1934
0
        goto cleanup;
1935
0
    }
1936
1937
    /* get restrictions from the referred typedefs */
1938
0
    for (uint32_t u = tpdf_chain.count - 1; u + 1 > 0; --u) {
1939
0
        tctx = (struct type_context *)tpdf_chain.objs[u];
1940
1941
        /* remember the typedef context for circular check */
1942
0
        ret = ly_set_add(&ctx->tpdf_chain, tctx, 1, NULL);
1943
0
        LY_CHECK_GOTO(ret, cleanup);
1944
1945
0
        if (tctx->tpdf->type.compiled) {
1946
0
            base = tctx->tpdf->type.compiled;
1947
0
            continue;
1948
0
        } else if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
1949
            /* no change, just use the type information from the base */
1950
0
            base = ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = ((struct type_context *)tpdf_chain.objs[u + 1])->tpdf->type.compiled;
1951
0
            ++base->refcount;
1952
0
            continue;
1953
0
        }
1954
1955
0
        ++(*type)->refcount;
1956
0
        if (~type_substmt_map[basetype] & tctx->tpdf->type.flags) {
1957
0
            LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Invalid type \"%s\" restriction(s) for %s type.",
1958
0
                    tctx->tpdf->name, ly_data_type2str[basetype]);
1959
0
            ret = LY_EVALID;
1960
0
            goto cleanup;
1961
0
        } else if ((basetype == LY_TYPE_EMPTY) && tctx->tpdf->dflt.str) {
1962
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
1963
0
                    "Invalid type \"%s\" - \"empty\" type must not have a default value (%s).",
1964
0
                    tctx->tpdf->name, tctx->tpdf->dflt.str);
1965
0
            ret = LY_EVALID;
1966
0
            goto cleanup;
1967
0
        }
1968
1969
0
        (*type)->basetype = basetype;
1970
        /* collect extensions */
1971
0
        COMPILE_EXTS_GOTO(ctx, tctx->tpdf->type.exts, (*type)->exts, (*type), ret, cleanup);
1972
        /* get plugin for the type */
1973
0
        (*type)->plugin = lys_compile_type_get_plugin(tctx->tpdf->type.pmod->mod, tctx->tpdf->name, basetype);
1974
0
        prev_type = *type;
1975
0
        ret = lys_compile_type_(ctx, tctx->node, tctx->tpdf->flags, tctx->tpdf->name,
1976
0
                &((struct lysp_tpdf *)tctx->tpdf)->type, basetype, tctx->tpdf->name, base, type);
1977
0
        LY_CHECK_GOTO(ret, cleanup);
1978
0
        base = prev_type;
1979
0
    }
1980
    /* remove the processed typedef contexts from the stack for circular check */
1981
0
    ctx->tpdf_chain.count = ctx->tpdf_chain.count - tpdf_chain.count;
1982
1983
    /* process the type definition in leaf */
1984
0
    if (type_p->flags || !base || (basetype == LY_TYPE_LEAFREF)) {
1985
        /* get restrictions from the node itself */
1986
0
        (*type)->basetype = basetype;
1987
0
        (*type)->plugin = base ? base->plugin : lyplg_find(LYPLG_TYPE, "", NULL, ly_data_type2str[basetype]);
1988
0
        ++(*type)->refcount;
1989
0
        ret = lys_compile_type_(ctx, context_pnode, context_flags, context_name, type_p, basetype, NULL, base, type);
1990
0
        LY_CHECK_GOTO(ret, cleanup);
1991
0
    } else if ((basetype != LY_TYPE_BOOL) && (basetype != LY_TYPE_EMPTY)) {
1992
        /* no specific restriction in leaf's type definition, copy from the base */
1993
0
        free(*type);
1994
0
        (*type) = base;
1995
0
        ++(*type)->refcount;
1996
0
    }
1997
1998
0
    COMPILE_EXTS_GOTO(ctx, type_p->exts, (*type)->exts, (*type), ret, cleanup);
1999
2000
0
cleanup:
2001
0
    ly_set_erase(&tpdf_chain, free);
2002
0
    return ret;
2003
0
}
2004
2005
/**
2006
 * @brief Special bits combination marking the uses_status value and propagated by ::lys_compile_uses() function.
2007
 */
2008
0
#define LYS_STATUS_USES LYS_CONFIG_MASK
2009
2010
/**
2011
 * @brief Compile status information of the given node.
2012
 *
2013
 * To simplify getting status of the node, the flags are set following inheritance rules, so all the nodes
2014
 * has the status correctly set during the compilation.
2015
 *
2016
 * @param[in] ctx Compile context
2017
 * @param[in,out] node_flags Flags of the compiled node which status is supposed to be resolved.
2018
 * If the status was set explicitly on the node, it is already set in the flags value and we just check
2019
 * the compatibility with the parent's status value.
2020
 * @param[in] parent_flags Flags of the parent node to check/inherit the status value.
2021
 * @return LY_ERR value.
2022
 */
2023
static LY_ERR
2024
lys_compile_status(struct lysc_ctx *ctx, uint16_t *node_flags, uint16_t parent_flags)
2025
0
{
2026
    /* status - it is not inherited by specification, but it does not make sense to have
2027
     * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
2028
0
    if (!((*node_flags) & LYS_STATUS_MASK)) {
2029
0
        if (parent_flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT)) {
2030
0
            if ((parent_flags & LYS_STATUS_USES) != LYS_STATUS_USES) {
2031
                /* do not print the warning when inheriting status from uses - the uses_status value has a special
2032
                 * combination of bits (LYS_STATUS_USES) which marks the uses_status value */
2033
0
                LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
2034
0
                        (parent_flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2035
0
            }
2036
0
            (*node_flags) |= parent_flags & LYS_STATUS_MASK;
2037
0
        } else {
2038
0
            (*node_flags) |= LYS_STATUS_CURR;
2039
0
        }
2040
0
    } else if (parent_flags & LYS_STATUS_MASK) {
2041
        /* check status compatibility with the parent */
2042
0
        if ((parent_flags & LYS_STATUS_MASK) > ((*node_flags) & LYS_STATUS_MASK)) {
2043
0
            if ((*node_flags) & LYS_STATUS_CURR) {
2044
0
                LOGVAL(ctx->ctx, LYVE_SEMANTICS,
2045
0
                        "A \"current\" status is in conflict with the parent's \"%s\" status.",
2046
0
                        (parent_flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
2047
0
            } else { /* LYS_STATUS_DEPRC */
2048
0
                LOGVAL(ctx->ctx, LYVE_SEMANTICS,
2049
0
                        "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
2050
0
            }
2051
0
            return LY_EVALID;
2052
0
        }
2053
0
    }
2054
0
    return LY_SUCCESS;
2055
0
}
2056
2057
/**
2058
 * @brief Check uniqness of the node/action/notification name.
2059
 *
2060
 * Data nodes, actions/RPCs and Notifications are stored separately (in distinguish lists) in the schema
2061
 * structures, but they share the namespace so we need to check their name collisions.
2062
 *
2063
 * @param[in] ctx Compile context.
2064
 * @param[in] parent Parent of the nodes to check, can be NULL.
2065
 * @param[in] name Name of the item to find in the given lists.
2066
 * @param[in] exclude Node that was just added that should be excluded from the name checking.
2067
 * @return LY_SUCCESS in case of unique name, LY_EEXIST otherwise.
2068
 */
2069
static LY_ERR
2070
lys_compile_node_uniqness(struct lysc_ctx *ctx, const struct lysc_node *parent, const char *name,
2071
        const struct lysc_node *exclude)
2072
0
{
2073
0
    const struct lysc_node *iter, *iter2;
2074
0
    const struct lysc_node_action *actions;
2075
0
    const struct lysc_node_notif *notifs;
2076
0
    uint32_t getnext_flags;
2077
0
    struct ly_set parent_choices = {0};
2078
2079
0
#define CHECK_NODE(iter, exclude, name) (iter != (void *)exclude && (iter)->module == exclude->module && !strcmp(name, (iter)->name))
2080
2081
0
    if (exclude->nodetype == LYS_CASE) {
2082
        /* check restricted only to all the cases */
2083
0
        assert(parent->nodetype == LYS_CHOICE);
2084
0
        LY_LIST_FOR(lysc_node_child(parent), iter) {
2085
0
            if (CHECK_NODE(iter, exclude, name)) {
2086
0
                LOGVAL(ctx->ctx, LY_VCODE_DUPIDENT, name, "case");
2087
0
                return LY_EEXIST;
2088
0
            }
2089
0
        }
2090
2091
0
        return LY_SUCCESS;
2092
0
    }
2093
2094
    /* no reason for our parent to be choice anymore */
2095
0
    assert(!parent || (parent->nodetype != LYS_CHOICE));
2096
2097
0
    if (parent && (parent->nodetype == LYS_CASE)) {
2098
        /* move to the first data definition parent */
2099
2100
        /* but remember the choice nodes on the parents path to avoid believe they collide with our node */
2101
0
        iter = lysc_data_parent(parent);
2102
0
        do {
2103
0
            parent = parent->parent;
2104
0
            if (parent && (parent->nodetype == LYS_CHOICE)) {
2105
0
                ly_set_add(&parent_choices, (void *)parent, 1, NULL);
2106
0
            }
2107
0
        } while (parent != iter);
2108
0
    }
2109
2110
0
    getnext_flags = LYS_GETNEXT_WITHCHOICE;
2111
0
    if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION))) {
2112
        /* move to the inout to avoid traversing a not-filled-yet (the other) node */
2113
0
        if (exclude->flags & LYS_IS_OUTPUT) {
2114
0
            getnext_flags |= LYS_GETNEXT_OUTPUT;
2115
0
            parent = lysc_node_child(parent)->next;
2116
0
        } else {
2117
0
            parent = lysc_node_child(parent);
2118
0
        }
2119
0
    }
2120
2121
0
    iter = NULL;
2122
0
    if (!parent && ctx->ext) {
2123
0
        while ((iter = lys_getnext_ext(iter, parent, ctx->ext, getnext_flags))) {
2124
0
            if (!ly_set_contains(&parent_choices, (void *)iter, NULL) && CHECK_NODE(iter, exclude, name)) {
2125
0
                goto error;
2126
0
            }
2127
2128
            /* we must compare with both the choice and all its nested data-definiition nodes (but not recursively) */
2129
0
            if (iter->nodetype == LYS_CHOICE) {
2130
0
                iter2 = NULL;
2131
0
                while ((iter2 = lys_getnext_ext(iter2, iter, NULL, 0))) {
2132
0
                    if (CHECK_NODE(iter2, exclude, name)) {
2133
0
                        goto error;
2134
0
                    }
2135
0
                }
2136
0
            }
2137
0
        }
2138
0
    } else {
2139
0
        while ((iter = lys_getnext(iter, parent, ctx->cur_mod->compiled, getnext_flags))) {
2140
0
            if (!ly_set_contains(&parent_choices, (void *)iter, NULL) && CHECK_NODE(iter, exclude, name)) {
2141
0
                goto error;
2142
0
            }
2143
2144
            /* we must compare with both the choice and all its nested data-definiition nodes (but not recursively) */
2145
0
            if (iter->nodetype == LYS_CHOICE) {
2146
0
                iter2 = NULL;
2147
0
                while ((iter2 = lys_getnext(iter2, iter, NULL, 0))) {
2148
0
                    if (CHECK_NODE(iter2, exclude, name)) {
2149
0
                        goto error;
2150
0
                    }
2151
0
                }
2152
0
            }
2153
0
        }
2154
2155
0
        actions = parent ? lysc_node_actions(parent) : ctx->cur_mod->compiled->rpcs;
2156
0
        LY_LIST_FOR((struct lysc_node *)actions, iter) {
2157
0
            if (CHECK_NODE(iter, exclude, name)) {
2158
0
                goto error;
2159
0
            }
2160
0
        }
2161
2162
0
        notifs = parent ? lysc_node_notifs(parent) : ctx->cur_mod->compiled->notifs;
2163
0
        LY_LIST_FOR((struct lysc_node *)notifs, iter) {
2164
0
            if (CHECK_NODE(iter, exclude, name)) {
2165
0
                goto error;
2166
0
            }
2167
0
        }
2168
0
    }
2169
0
    ly_set_erase(&parent_choices, NULL);
2170
0
    return LY_SUCCESS;
2171
2172
0
error:
2173
0
    ly_set_erase(&parent_choices, NULL);
2174
0
    LOGVAL(ctx->ctx, LY_VCODE_DUPIDENT, name, "data definition/RPC/action/notification");
2175
0
    return LY_EEXIST;
2176
2177
0
#undef CHECK_NODE
2178
0
}
2179
2180
/**
2181
 * @brief Connect the node into the siblings list and check its name uniqueness. Also,
2182
 * keep specific order of augments targetting the same node.
2183
 *
2184
 * @param[in] ctx Compile context
2185
 * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
2186
 * the choice itself is expected instead of a specific case node.
2187
 * @param[in] node Schema node to connect into the list.
2188
 * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
2189
 * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
2190
 */
2191
static LY_ERR
2192
lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
2193
0
{
2194
0
    struct lysc_node **children, *anchor = NULL;
2195
0
    int insert_after = 0;
2196
2197
0
    node->parent = parent;
2198
2199
0
    if (parent) {
2200
0
        if (node->nodetype == LYS_INPUT) {
2201
0
            assert(parent->nodetype & (LYS_ACTION | LYS_RPC));
2202
            /* input node is part of the action but link it with output */
2203
0
            node->next = &((struct lysc_node_action *)parent)->output.node;
2204
0
            node->prev = node->next;
2205
0
            return LY_SUCCESS;
2206
0
        } else if (node->nodetype == LYS_OUTPUT) {
2207
            /* output node is part of the action but link it with input */
2208
0
            node->next = NULL;
2209
0
            node->prev = &((struct lysc_node_action *)parent)->input.node;
2210
0
            return LY_SUCCESS;
2211
0
        } else if (node->nodetype == LYS_ACTION) {
2212
0
            children = (struct lysc_node **)lysc_node_actions_p(parent);
2213
0
        } else if (node->nodetype == LYS_NOTIF) {
2214
0
            children = (struct lysc_node **)lysc_node_notifs_p(parent);
2215
0
        } else {
2216
0
            children = lysc_node_child_p(parent);
2217
0
        }
2218
0
        assert(children);
2219
2220
0
        if (!(*children)) {
2221
            /* first child */
2222
0
            *children = node;
2223
0
        } else if (node->flags & LYS_KEY) {
2224
            /* special handling of adding keys */
2225
0
            assert(node->module == parent->module);
2226
0
            anchor = *children;
2227
0
            if (anchor->flags & LYS_KEY) {
2228
0
                while ((anchor->flags & LYS_KEY) && anchor->next) {
2229
0
                    anchor = anchor->next;
2230
0
                }
2231
                /* insert after the last key */
2232
0
                insert_after = 1;
2233
0
            } /* else insert before anchor (at the beginning) */
2234
0
        } else if ((*children)->prev->module == node->module) {
2235
            /* last child is from the same module, keep the order and insert at the end */
2236
0
            anchor = (*children)->prev;
2237
0
            insert_after = 1;
2238
0
        } else if (parent->module == node->module) {
2239
            /* adding module child after some augments were connected */
2240
0
            for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
2241
0
        } else {
2242
            /* some augments are already connected and we are connecting new ones,
2243
             * keep module name order and insert the node into the children list */
2244
0
            anchor = *children;
2245
0
            do {
2246
0
                anchor = anchor->prev;
2247
2248
                /* check that we have not found the last augment node from our module or
2249
                 * the first augment node from a "smaller" module or
2250
                 * the first node from a local module */
2251
0
                if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
2252
0
                        (anchor->module == parent->module)) {
2253
                    /* insert after */
2254
0
                    insert_after = 1;
2255
0
                    break;
2256
0
                }
2257
2258
                /* we have traversed all the nodes, insert before anchor (as the first node) */
2259
0
            } while (anchor->prev->next);
2260
0
        }
2261
2262
        /* insert */
2263
0
        if (anchor) {
2264
0
            if (insert_after) {
2265
0
                node->next = anchor->next;
2266
0
                node->prev = anchor;
2267
0
                anchor->next = node;
2268
0
                if (node->next) {
2269
                    /* middle node */
2270
0
                    node->next->prev = node;
2271
0
                } else {
2272
                    /* last node */
2273
0
                    (*children)->prev = node;
2274
0
                }
2275
0
            } else {
2276
0
                node->next = anchor;
2277
0
                node->prev = anchor->prev;
2278
0
                anchor->prev = node;
2279
0
                if (anchor == *children) {
2280
                    /* first node */
2281
0
                    *children = node;
2282
0
                } else {
2283
                    /* middle node */
2284
0
                    node->prev->next = node;
2285
0
                }
2286
0
            }
2287
0
        }
2288
2289
        /* check the name uniqueness (even for an only child, it may be in case) */
2290
0
        if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
2291
0
            return LY_EEXIST;
2292
0
        }
2293
0
    } else {
2294
        /* top-level element */
2295
0
        struct lysc_node **list;
2296
2297
0
        if (ctx->ext) {
2298
0
            lysc_ext_substmt(ctx->ext, LY_STMT_CONTAINER /* matches all data nodes */, (void **)&list, NULL);
2299
0
        } else if (node->nodetype == LYS_RPC) {
2300
0
            list = (struct lysc_node **)&ctx->cur_mod->compiled->rpcs;
2301
0
        } else if (node->nodetype == LYS_NOTIF) {
2302
0
            list = (struct lysc_node **)&ctx->cur_mod->compiled->notifs;
2303
0
        } else {
2304
0
            list = &ctx->cur_mod->compiled->data;
2305
0
        }
2306
0
        if (!(*list)) {
2307
0
            *list = node;
2308
0
        } else {
2309
            /* insert at the end of the module's top-level nodes list */
2310
0
            (*list)->prev->next = node;
2311
0
            node->prev = (*list)->prev;
2312
0
            (*list)->prev = node;
2313
0
        }
2314
2315
        /* check the name uniqueness on top-level */
2316
0
        if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
2317
0
            return LY_EEXIST;
2318
0
        }
2319
0
    }
2320
2321
0
    return LY_SUCCESS;
2322
0
}
2323
2324
/**
2325
 * @brief Set config and operation flags for a node.
2326
 *
2327
 * @param[in] ctx Compile context.
2328
 * @param[in] node Compiled node flags to set.
2329
 * @return LY_ERR value.
2330
 */
2331
static LY_ERR
2332
lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node)
2333
0
{
2334
    /* case never has any explicit config */
2335
0
    assert((node->nodetype != LYS_CASE) || !(node->flags & LYS_CONFIG_MASK));
2336
2337
0
    if (ctx->options & LYS_COMPILE_NO_CONFIG) {
2338
        /* ignore config statements inside Notification/RPC/action/... data */
2339
0
        node->flags &= ~LYS_CONFIG_MASK;
2340
0
    } else if (!(node->flags & LYS_CONFIG_MASK)) {
2341
        /* config not explicitly set, inherit it from parent */
2342
0
        if (node->parent) {
2343
0
            node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2344
0
        } else {
2345
            /* default is config true */
2346
0
            node->flags |= LYS_CONFIG_W;
2347
0
        }
2348
0
    } else {
2349
        /* config set explicitly */
2350
0
        node->flags |= LYS_SET_CONFIG;
2351
0
    }
2352
2353
0
    if (node->parent && (node->parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
2354
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Configuration node cannot be child of any state data node.");
2355
0
        return LY_EVALID;
2356
0
    }
2357
2358
0
    return LY_SUCCESS;
2359
0
}
2360
2361
/**
2362
 * @brief Set various flags of the compiled nodes
2363
 *
2364
 * @param[in] ctx Compile context.
2365
 * @param[in] node Compiled node where the flags will be set.
2366
 * @param[in] uses_status If the node is being placed instead of uses, here we have the uses's status value (as node's flags).
2367
 * Zero means no uses, non-zero value with no status bit set mean the default status.
2368
 */
2369
static LY_ERR
2370
lys_compile_node_flags(struct lysc_ctx *ctx, struct lysc_node *node, uint16_t uses_status)
2371
0
{
2372
    /* inherit config flags */
2373
0
    LY_CHECK_RET(lys_compile_config(ctx, node));
2374
2375
    /* status - it is not inherited by specification, but it does not make sense to have
2376
     * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
2377
0
    LY_CHECK_RET(lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (node->parent ? node->parent->flags : 0)));
2378
2379
    /* other flags */
2380
0
    if ((ctx->options & LYS_IS_INPUT) && (node->nodetype != LYS_INPUT)) {
2381
0
        node->flags |= LYS_IS_INPUT;
2382
0
    } else if ((ctx->options & LYS_IS_OUTPUT) && (node->nodetype != LYS_OUTPUT)) {
2383
0
        node->flags |= LYS_IS_OUTPUT;
2384
0
    } else if ((ctx->options & LYS_IS_NOTIF) && (node->nodetype != LYS_NOTIF)) {
2385
0
        node->flags |= LYS_IS_NOTIF;
2386
0
    }
2387
2388
0
    return LY_SUCCESS;
2389
0
}
2390
2391
LY_ERR
2392
lys_compile_node_(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
2393
        LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *),
2394
        struct lysc_node *node, struct ly_set *child_set)
2395
0
{
2396
0
    LY_ERR ret = LY_SUCCESS;
2397
0
    ly_bool not_supported, enabled;
2398
0
    struct lysp_node *dev_pnode = NULL;
2399
0
    struct lysp_when *pwhen = NULL;
2400
2401
0
    node->nodetype = pnode->nodetype;
2402
0
    node->module = ctx->cur_mod;
2403
0
    node->parent = parent;
2404
0
    node->prev = node;
2405
0
    node->priv = ctx->ctx->flags & LY_CTX_SET_PRIV_PARSED ? pnode : NULL;
2406
2407
    /* compile any deviations for this node */
2408
0
    LY_CHECK_GOTO(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, &not_supported), error);
2409
0
    if (not_supported) {
2410
0
        goto error;
2411
0
    } else if (dev_pnode) {
2412
0
        pnode = dev_pnode;
2413
0
    }
2414
2415
0
    node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
2416
2417
    /* if-features */
2418
0
    LY_CHECK_GOTO(ret = lys_eval_iffeatures(ctx->ctx, pnode->iffeatures, &enabled), error);
2419
0
    if (!enabled && !(ctx->options & (LYS_COMPILE_NO_DISABLED | LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
2420
0
        ly_set_add(&ctx->unres->disabled, node, 1, NULL);
2421
0
        ctx->options |= LYS_COMPILE_DISABLED;
2422
0
    }
2423
2424
    /* config, status and other flags */
2425
0
    ret = lys_compile_node_flags(ctx, node, uses_status);
2426
0
    LY_CHECK_GOTO(ret, error);
2427
2428
    /* list ordering */
2429
0
    if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
2430
0
        if ((node->flags & (LYS_CONFIG_R | LYS_IS_OUTPUT | LYS_IS_NOTIF)) && (node->flags & LYS_ORDBY_MASK)) {
2431
0
            LOGVRB("The ordered-by statement is ignored in lists representing %s (%s).",
2432
0
                    (node->flags & LYS_IS_OUTPUT) ? "RPC/action output parameters" :
2433
0
                    (ctx->options & LYS_IS_NOTIF) ? "notification content" : "state data", ctx->path);
2434
0
            node->flags &= ~LYS_ORDBY_MASK;
2435
0
            node->flags |= LYS_ORDBY_SYSTEM;
2436
0
        } else if (!(node->flags & LYS_ORDBY_MASK)) {
2437
            /* default ordering is system */
2438
0
            node->flags |= LYS_ORDBY_SYSTEM;
2439
0
        }
2440
0
    }
2441
2442
0
    DUP_STRING_GOTO(ctx->ctx, pnode->name, node->name, ret, error);
2443
0
    DUP_STRING_GOTO(ctx->ctx, pnode->dsc, node->dsc, ret, error);
2444
0
    DUP_STRING_GOTO(ctx->ctx, pnode->ref, node->ref, ret, error);
2445
2446
    /* insert into parent's children/compiled module (we can no longer free the node separately on error) */
2447
0
    LY_CHECK_GOTO(ret = lys_compile_node_connect(ctx, parent, node), cleanup);
2448
2449
0
    if ((pwhen = lysp_node_when(pnode))) {
2450
        /* compile when */
2451
0
        ret = lys_compile_when(ctx, pwhen, pnode->flags, lysc_data_node(node), node, NULL);
2452
0
        LY_CHECK_GOTO(ret, cleanup);
2453
0
    }
2454
2455
    /* connect any augments */
2456
0
    LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
2457
2458
    /* nodetype-specific part */
2459
0
    LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
2460
2461
    /* final compilation tasks that require the node to be connected */
2462
0
    COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, ret, cleanup);
2463
0
    if (node->flags & LYS_MAND_TRUE) {
2464
        /* inherit LYS_MAND_TRUE in parent containers */
2465
0
        lys_compile_mandatory_parents(parent, 1);
2466
0
    }
2467
2468
0
    if (child_set) {
2469
        /* add the new node into set */
2470
0
        LY_CHECK_GOTO(ret = ly_set_add(child_set, node, 1, NULL), cleanup);
2471
0
    }
2472
2473
0
    goto cleanup;
2474
2475
0
error:
2476
0
    lysc_node_free(ctx->ctx, node, 0);
2477
0
cleanup:
2478
0
    if (ret && dev_pnode) {
2479
0
        LOGVAL(ctx->ctx, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
2480
0
    }
2481
0
    lysp_dev_node_free(ctx->ctx, dev_pnode);
2482
0
    return ret;
2483
0
}
2484
2485
/**
2486
 * @brief Compile parsed action's input/output node information.
2487
 * @param[in] ctx Compile context
2488
 * @param[in] pnode Parsed inout node.
2489
 * @param[in,out] node Pre-prepared structure from lys_compile_node_() with filled generic node information
2490
 * is enriched with the inout-specific information.
2491
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2492
 */
2493
LY_ERR
2494
lys_compile_node_action_inout(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2495
0
{
2496
0
    LY_ERR ret = LY_SUCCESS;
2497
0
    struct lysp_node *child_p;
2498
0
    uint32_t prev_options = ctx->options;
2499
2500
0
    struct lysp_node_action_inout *inout_p = (struct lysp_node_action_inout *)pnode;
2501
0
    struct lysc_node_action_inout *inout = (struct lysc_node_action_inout *)node;
2502
2503
0
    COMPILE_ARRAY_GOTO(ctx, inout_p->musts, inout->musts, lys_compile_must, ret, done);
2504
0
    COMPILE_EXTS_GOTO(ctx, inout_p->exts, inout->exts, inout, ret, done);
2505
0
    ctx->options |= (inout_p->nodetype == LYS_INPUT) ? LYS_COMPILE_RPC_INPUT : LYS_COMPILE_RPC_OUTPUT;
2506
2507
0
    LY_LIST_FOR(inout_p->child, child_p) {
2508
0
        LY_CHECK_GOTO(ret = lys_compile_node(ctx, child_p, node, 0, NULL), done);
2509
0
    }
2510
2511
0
    ctx->options = prev_options;
2512
2513
0
done:
2514
0
    return ret;
2515
0
}
2516
2517
/**
2518
 * @brief Compile parsed action node information.
2519
 * @param[in] ctx Compile context
2520
 * @param[in] pnode Parsed action node.
2521
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2522
 * is enriched with the action-specific information.
2523
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2524
 */
2525
LY_ERR
2526
lys_compile_node_action(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2527
0
{
2528
0
    LY_ERR ret;
2529
0
    struct lysp_node_action *action_p = (struct lysp_node_action *)pnode;
2530
0
    struct lysc_node_action *action = (struct lysc_node_action *)node;
2531
0
    struct lysp_node_action_inout *input, implicit_input = {
2532
0
        .nodetype = LYS_INPUT,
2533
0
        .name = "input",
2534
0
        .parent = pnode,
2535
0
    };
2536
0
    struct lysp_node_action_inout *output, implicit_output = {
2537
0
        .nodetype = LYS_OUTPUT,
2538
0
        .name = "output",
2539
0
        .parent = pnode,
2540
0
    };
2541
2542
    /* input */
2543
0
    lysc_update_path(ctx, action->module, "input");
2544
0
    if (action_p->input.nodetype == LYS_UNKNOWN) {
2545
0
        input = &implicit_input;
2546
0
    } else {
2547
0
        input = &action_p->input;
2548
0
    }
2549
0
    ret = lys_compile_node_(ctx, &input->node, &action->node, 0, lys_compile_node_action_inout, &action->input.node, NULL);
2550
0
    lysc_update_path(ctx, NULL, NULL);
2551
0
    LY_CHECK_GOTO(ret, done);
2552
2553
    /* output */
2554
0
    lysc_update_path(ctx, action->module, "output");
2555
0
    if (action_p->output.nodetype == LYS_UNKNOWN) {
2556
0
        output = &implicit_output;
2557
0
    } else {
2558
0
        output = &action_p->output;
2559
0
    }
2560
0
    ret = lys_compile_node_(ctx, &output->node, &action->node, 0, lys_compile_node_action_inout, &action->output.node, NULL);
2561
0
    lysc_update_path(ctx, NULL, NULL);
2562
0
    LY_CHECK_GOTO(ret, done);
2563
2564
    /* do not check "must" semantics in a grouping */
2565
0
    if ((action->input.musts || action->output.musts) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
2566
0
        ret = ly_set_add(&ctx->unres->xpath, action, 0, NULL);
2567
0
        LY_CHECK_GOTO(ret, done);
2568
0
    }
2569
2570
0
done:
2571
0
    return ret;
2572
0
}
2573
2574
/**
2575
 * @brief Compile parsed action node information.
2576
 * @param[in] ctx Compile context
2577
 * @param[in] pnode Parsed action node.
2578
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2579
 * is enriched with the action-specific information.
2580
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2581
 */
2582
LY_ERR
2583
lys_compile_node_notif(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2584
0
{
2585
0
    LY_ERR ret = LY_SUCCESS;
2586
0
    struct lysp_node_notif *notif_p = (struct lysp_node_notif *)pnode;
2587
0
    struct lysc_node_notif *notif = (struct lysc_node_notif *)node;
2588
0
    struct lysp_node *child_p;
2589
2590
0
    COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, lys_compile_must, ret, done);
2591
0
    if (notif_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
2592
        /* do not check "must" semantics in a grouping */
2593
0
        ret = ly_set_add(&ctx->unres->xpath, notif, 0, NULL);
2594
0
        LY_CHECK_GOTO(ret, done);
2595
0
    }
2596
2597
0
    LY_LIST_FOR(notif_p->child, child_p) {
2598
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
2599
0
        LY_CHECK_GOTO(ret, done);
2600
0
    }
2601
2602
0
done:
2603
0
    return ret;
2604
0
}
2605
2606
/**
2607
 * @brief Compile parsed container node information.
2608
 * @param[in] ctx Compile context
2609
 * @param[in] pnode Parsed container node.
2610
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2611
 * is enriched with the container-specific information.
2612
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2613
 */
2614
static LY_ERR
2615
lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2616
0
{
2617
0
    struct lysp_node_container *cont_p = (struct lysp_node_container *)pnode;
2618
0
    struct lysc_node_container *cont = (struct lysc_node_container *)node;
2619
0
    struct lysp_node *child_p;
2620
0
    LY_ERR ret = LY_SUCCESS;
2621
2622
0
    if (cont_p->presence) {
2623
        /* presence container */
2624
0
        cont->flags |= LYS_PRESENCE;
2625
0
    }
2626
2627
    /* more cases when the container has meaning but is kept NP for convenience:
2628
     *   - when condition
2629
     *   - direct child action/notification
2630
     */
2631
2632
0
    LY_LIST_FOR(cont_p->child, child_p) {
2633
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
2634
0
        LY_CHECK_GOTO(ret, done);
2635
0
    }
2636
2637
0
    COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, lys_compile_must, ret, done);
2638
0
    if (cont_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
2639
        /* do not check "must" semantics in a grouping */
2640
0
        ret = ly_set_add(&ctx->unres->xpath, cont, 0, NULL);
2641
0
        LY_CHECK_GOTO(ret, done);
2642
0
    }
2643
2644
0
    LY_LIST_FOR((struct lysp_node *)cont_p->actions, child_p) {
2645
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
2646
0
        LY_CHECK_GOTO(ret, done);
2647
0
    }
2648
0
    LY_LIST_FOR((struct lysp_node *)cont_p->notifs, child_p) {
2649
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
2650
0
        LY_CHECK_GOTO(ret, done);
2651
0
    }
2652
2653
0
done:
2654
0
    return ret;
2655
0
}
2656
2657
/**
2658
 * @brief Compile type in leaf/leaf-list node and do all the necessary checks.
2659
 * @param[in] ctx Compile context.
2660
 * @param[in] context_node Schema node where the type/typedef is placed to correctly find the base types.
2661
 * @param[in] type_p Parsed type to compile.
2662
 * @param[in,out] leaf Compiled leaf structure (possibly cast leaf-list) to provide node information and to store the compiled type information.
2663
 * @return LY_ERR value.
2664
 */
2665
static LY_ERR
2666
lys_compile_node_type(struct lysc_ctx *ctx, struct lysp_node *context_node, struct lysp_type *type_p,
2667
        struct lysc_node_leaf *leaf)
2668
0
{
2669
0
    struct lysp_qname *dflt;
2670
2671
0
    LY_CHECK_RET(lys_compile_type(ctx, context_node, leaf->flags, leaf->name, type_p, &leaf->type,
2672
0
            leaf->units ? NULL : &leaf->units, &dflt));
2673
2674
    /* store default value, if any */
2675
0
    if (dflt && !(leaf->flags & LYS_SET_DFLT)) {
2676
0
        LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, dflt));
2677
0
    }
2678
2679
0
    if ((leaf->type->basetype == LY_TYPE_LEAFREF) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
2680
        /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
2681
0
        LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
2682
0
    } else if ((leaf->type->basetype == LY_TYPE_UNION) && !(ctx->options & (LYS_COMPILE_DISABLED | LYS_COMPILE_GROUPING))) {
2683
0
        LY_ARRAY_COUNT_TYPE u;
2684
0
        LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
2685
0
            if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
2686
                /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
2687
0
                LY_CHECK_RET(ly_set_add(&ctx->unres->leafrefs, leaf, 0, NULL));
2688
0
            }
2689
0
        }
2690
0
    } else if (leaf->type->basetype == LY_TYPE_EMPTY) {
2691
0
        if ((leaf->nodetype == LYS_LEAFLIST) && (ctx->pmod->version < LYS_VERSION_1_1)) {
2692
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
2693
0
            return LY_EVALID;
2694
0
        }
2695
0
    }
2696
2697
0
    return LY_SUCCESS;
2698
0
}
2699
2700
/**
2701
 * @brief Compile parsed leaf node information.
2702
 * @param[in] ctx Compile context
2703
 * @param[in] pnode Parsed leaf node.
2704
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2705
 * is enriched with the leaf-specific information.
2706
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2707
 */
2708
static LY_ERR
2709
lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2710
0
{
2711
0
    struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf *)pnode;
2712
0
    struct lysc_node_leaf *leaf = (struct lysc_node_leaf *)node;
2713
0
    LY_ERR ret = LY_SUCCESS;
2714
2715
0
    COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, lys_compile_must, ret, done);
2716
0
    if (leaf_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
2717
        /* do not check "must" semantics in a grouping */
2718
0
        ret = ly_set_add(&ctx->unres->xpath, leaf, 0, NULL);
2719
0
        LY_CHECK_GOTO(ret, done);
2720
0
    }
2721
0
    if (leaf_p->units) {
2722
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, leaf_p->units, 0, &leaf->units), done);
2723
0
        leaf->flags |= LYS_SET_UNITS;
2724
0
    }
2725
2726
    /* compile type */
2727
0
    ret = lys_compile_node_type(ctx, pnode, &leaf_p->type, leaf);
2728
0
    LY_CHECK_GOTO(ret, done);
2729
2730
    /* store/update default value */
2731
0
    if (leaf_p->dflt.str) {
2732
0
        LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, &leaf_p->dflt));
2733
0
        leaf->flags |= LYS_SET_DFLT;
2734
0
    }
2735
2736
    /* checks */
2737
0
    if ((leaf->flags & LYS_SET_DFLT) && (leaf->flags & LYS_MAND_TRUE)) {
2738
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
2739
0
                "Invalid mandatory leaf with a default value.");
2740
0
        return LY_EVALID;
2741
0
    }
2742
2743
0
done:
2744
0
    return ret;
2745
0
}
2746
2747
/**
2748
 * @brief Compile parsed leaf-list node information.
2749
 * @param[in] ctx Compile context
2750
 * @param[in] pnode Parsed leaf-list node.
2751
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
2752
 * is enriched with the leaf-list-specific information.
2753
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2754
 */
2755
static LY_ERR
2756
lys_compile_node_leaflist(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
2757
0
{
2758
0
    struct lysp_node_leaflist *llist_p = (struct lysp_node_leaflist *)pnode;
2759
0
    struct lysc_node_leaflist *llist = (struct lysc_node_leaflist *)node;
2760
0
    LY_ERR ret = LY_SUCCESS;
2761
2762
0
    COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, lys_compile_must, ret, done);
2763
0
    if (llist_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
2764
        /* do not check "must" semantics in a grouping */
2765
0
        ret = ly_set_add(&ctx->unres->xpath, llist, 0, NULL);
2766
0
        LY_CHECK_GOTO(ret, done);
2767
0
    }
2768
0
    if (llist_p->units) {
2769
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, llist_p->units, 0, &llist->units), done);
2770
0
        llist->flags |= LYS_SET_UNITS;
2771
0
    }
2772
2773
    /* compile type */
2774
0
    ret = lys_compile_node_type(ctx, pnode, &llist_p->type, (struct lysc_node_leaf *)llist);
2775
0
    LY_CHECK_GOTO(ret, done);
2776
2777
    /* store/update default values */
2778
0
    if (llist_p->dflts) {
2779
0
        if (ctx->pmod->version < LYS_VERSION_1_1) {
2780
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
2781
0
                    "Leaf-list default values are allowed only in YANG 1.1 modules.");
2782
0
            return LY_EVALID;
2783
0
        }
2784
2785
0
        LY_CHECK_GOTO(lysc_unres_llist_dflts_add(ctx, llist, llist_p->dflts), done);
2786
0
        llist->flags |= LYS_SET_DFLT;
2787
0
    }
2788
2789
0
    llist->min = llist_p->min;
2790
0
    if (llist->min) {
2791
0
        llist->flags |= LYS_MAND_TRUE;
2792
0
    }
2793
0
    llist->max = llist_p->max ? llist_p->max : UINT32_MAX;
2794
2795
0
    if (llist->flags & LYS_CONFIG_R) {
2796
        /* state leaf-list is always ordered-by user */
2797
0
        llist->flags &= ~LYS_ORDBY_SYSTEM;
2798
0
        llist->flags |= LYS_ORDBY_USER;
2799
0
    }
2800
2801
    /* checks */
2802
0
    if ((llist->flags & LYS_SET_DFLT) && (llist->flags & LYS_MAND_TRUE)) {
2803
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "The default statement is present on leaf-list with a nonzero min-elements.");
2804
0
        return LY_EVALID;
2805
0
    }
2806
2807
0
    if (llist->min > llist->max) {
2808
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Leaf-list min-elements %u is bigger than max-elements %u.",
2809
0
                llist->min, llist->max);
2810
0
        return LY_EVALID;
2811
0
    }
2812
2813
0
done:
2814
0
    return ret;
2815
0
}
2816
2817
LY_ERR
2818
lysc_resolve_schema_nodeid(struct lysc_ctx *ctx, const char *nodeid, size_t nodeid_len, const struct lysc_node *ctx_node,
2819
        const struct lys_module *cur_mod, LY_VALUE_FORMAT format, void *prefix_data, uint16_t nodetype,
2820
        const struct lysc_node **target, uint16_t *result_flag)
2821
0
{
2822
0
    LY_ERR ret = LY_EVALID;
2823
0
    const char *name, *prefix, *id;
2824
0
    size_t name_len, prefix_len;
2825
0
    const struct lys_module *mod = NULL;
2826
0
    const char *nodeid_type;
2827
0
    uint32_t getnext_extra_flag = 0;
2828
0
    uint16_t current_nodetype = 0;
2829
2830
0
    assert(nodeid);
2831
0
    assert(target);
2832
0
    assert(result_flag);
2833
0
    *target = NULL;
2834
0
    *result_flag = 0;
2835
2836
0
    id = nodeid;
2837
2838
0
    if (ctx_node) {
2839
        /* descendant-schema-nodeid */
2840
0
        nodeid_type = "descendant";
2841
2842
0
        if (*id == '/') {
2843
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE,
2844
0
                    "Invalid descendant-schema-nodeid value \"%.*s\" - absolute-schema-nodeid used.",
2845
0
                    (int)(nodeid_len ? nodeid_len : strlen(nodeid)), nodeid);
2846
0
            return LY_EVALID;
2847
0
        }
2848
0
    } else {
2849
        /* absolute-schema-nodeid */
2850
0
        nodeid_type = "absolute";
2851
2852
0
        if (*id != '/') {
2853
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE,
2854
0
                    "Invalid absolute-schema-nodeid value \"%.*s\" - missing starting \"/\".",
2855
0
                    (int)(nodeid_len ? nodeid_len : strlen(nodeid)), nodeid);
2856
0
            return LY_EVALID;
2857
0
        }
2858
0
        ++id;
2859
0
    }
2860
2861
0
    while (*id && (ret = ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len)) == LY_SUCCESS) {
2862
0
        if (prefix) {
2863
0
            mod = ly_resolve_prefix(ctx->ctx, prefix, prefix_len, format, prefix_data);
2864
0
            if (!mod) {
2865
                /* module must always be found */
2866
0
                assert(prefix);
2867
0
                LOGVAL(ctx->ctx, LYVE_REFERENCE,
2868
0
                        "Invalid %s-schema-nodeid value \"%.*s\" - prefix \"%.*s\" not defined in module \"%s\".",
2869
0
                        nodeid_type, (int)(id - nodeid), nodeid, (int)prefix_len, prefix, LYSP_MODULE_NAME(ctx->pmod));
2870
0
                return LY_ENOTFOUND;
2871
0
            }
2872
0
        } else {
2873
0
            switch (format) {
2874
0
            case LY_VALUE_SCHEMA:
2875
0
            case LY_VALUE_SCHEMA_RESOLVED:
2876
                /* use the current module */
2877
0
                mod = cur_mod;
2878
0
                break;
2879
0
            case LY_VALUE_JSON:
2880
0
            case LY_VALUE_LYB:
2881
0
                if (!ctx_node) {
2882
0
                    LOGINT_RET(ctx->ctx);
2883
0
                }
2884
                /* inherit the module of the previous context node */
2885
0
                mod = ctx_node->module;
2886
0
                break;
2887
0
            case LY_VALUE_CANON:
2888
0
            case LY_VALUE_XML:
2889
                /* not really defined */
2890
0
                LOGINT_RET(ctx->ctx);
2891
0
            }
2892
0
        }
2893
2894
0
        if (ctx_node && (ctx_node->nodetype & (LYS_RPC | LYS_ACTION))) {
2895
            /* move through input/output manually */
2896
0
            if (mod != ctx_node->module) {
2897
0
                LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid %s-schema-nodeid value \"%.*s\" - target node not found.",
2898
0
                        nodeid_type, (int)(id - nodeid), nodeid);
2899
0
                return LY_ENOTFOUND;
2900
0
            }
2901
0
            if (!ly_strncmp("input", name, name_len)) {
2902
0
                ctx_node = &((struct lysc_node_action *)ctx_node)->input.node;
2903
0
            } else if (!ly_strncmp("output", name, name_len)) {
2904
0
                ctx_node = &((struct lysc_node_action *)ctx_node)->output.node;
2905
0
                getnext_extra_flag = LYS_GETNEXT_OUTPUT;
2906
0
            } else {
2907
                /* only input or output is valid */
2908
0
                ctx_node = NULL;
2909
0
            }
2910
0
        } else {
2911
0
            ctx_node = lys_find_child(ctx_node, mod, name, name_len, 0,
2912
0
                    getnext_extra_flag | LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE);
2913
0
            getnext_extra_flag = 0;
2914
0
        }
2915
0
        if (!ctx_node) {
2916
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid %s-schema-nodeid value \"%.*s\" - target node not found.",
2917
0
                    nodeid_type, (int)(id - nodeid), nodeid);
2918
0
            return LY_ENOTFOUND;
2919
0
        }
2920
0
        current_nodetype = ctx_node->nodetype;
2921
2922
0
        if (current_nodetype == LYS_NOTIF) {
2923
0
            (*result_flag) |= LYS_COMPILE_NOTIFICATION;
2924
0
        } else if (current_nodetype == LYS_INPUT) {
2925
0
            (*result_flag) |= LYS_COMPILE_RPC_INPUT;
2926
0
        } else if (current_nodetype == LYS_OUTPUT) {
2927
0
            (*result_flag) |= LYS_COMPILE_RPC_OUTPUT;
2928
0
        }
2929
2930
0
        if (!*id || (nodeid_len && ((size_t)(id - nodeid) >= nodeid_len))) {
2931
0
            break;
2932
0
        }
2933
0
        if (*id != '/') {
2934
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE,
2935
0
                    "Invalid %s-schema-nodeid value \"%.*s\" - missing \"/\" as node-identifier separator.",
2936
0
                    nodeid_type, (int)(id - nodeid + 1), nodeid);
2937
0
            return LY_EVALID;
2938
0
        }
2939
0
        ++id;
2940
0
    }
2941
2942
0
    if (ret == LY_SUCCESS) {
2943
0
        *target = ctx_node;
2944
0
        if (nodetype && !(current_nodetype & nodetype)) {
2945
0
            return LY_EDENIED;
2946
0
        }
2947
0
    } else {
2948
0
        LOGVAL(ctx->ctx, LYVE_REFERENCE,
2949
0
                "Invalid %s-schema-nodeid value \"%.*s\" - unexpected end of expression.",
2950
0
                nodeid_type, (int)(nodeid_len ? nodeid_len : strlen(nodeid)), nodeid);
2951
0
    }
2952
2953
0
    return ret;
2954
0
}
2955
2956
/**
2957
 * @brief Compile information about list's uniques.
2958
 * @param[in] ctx Compile context.
2959
 * @param[in] uniques Sized array list of unique statements.
2960
 * @param[in] list Compiled list where the uniques are supposed to be resolved and stored.
2961
 * @return LY_ERR value.
2962
 */
2963
static LY_ERR
2964
lys_compile_node_list_unique(struct lysc_ctx *ctx, struct lysp_qname *uniques, struct lysc_node_list *list)
2965
0
{
2966
0
    LY_ERR ret = LY_SUCCESS;
2967
0
    struct lysc_node_leaf **key, ***unique;
2968
0
    struct lysc_node *parent;
2969
0
    const char *keystr, *delim;
2970
0
    size_t len;
2971
0
    LY_ARRAY_COUNT_TYPE v;
2972
0
    int8_t config; /* -1 - not yet seen; 0 - LYS_CONFIG_R; 1 - LYS_CONFIG_W */
2973
0
    uint16_t flags;
2974
2975
0
    LY_ARRAY_FOR(uniques, v) {
2976
0
        config = -1;
2977
0
        LY_ARRAY_NEW_RET(ctx->ctx, list->uniques, unique, LY_EMEM);
2978
0
        keystr = uniques[v].str;
2979
0
        while (keystr) {
2980
0
            delim = strpbrk(keystr, " \t\n");
2981
0
            if (delim) {
2982
0
                len = delim - keystr;
2983
0
                while (isspace(*delim)) {
2984
0
                    ++delim;
2985
0
                }
2986
0
            } else {
2987
0
                len = strlen(keystr);
2988
0
            }
2989
2990
            /* unique node must be present */
2991
0
            LY_ARRAY_NEW_RET(ctx->ctx, *unique, key, LY_EMEM);
2992
0
            ret = lysc_resolve_schema_nodeid(ctx, keystr, len, &list->node, uniques[v].mod->mod,
2993
0
                    LY_VALUE_SCHEMA, (void *)uniques[v].mod, LYS_LEAF, (const struct lysc_node **)key, &flags);
2994
0
            if (ret != LY_SUCCESS) {
2995
0
                if (ret == LY_EDENIED) {
2996
0
                    LOGVAL(ctx->ctx, LYVE_REFERENCE,
2997
0
                            "Unique's descendant-schema-nodeid \"%.*s\" refers to %s node instead of a leaf.",
2998
0
                            (int)len, keystr, lys_nodetype2str((*key)->nodetype));
2999
0
                }
3000
0
                return LY_EVALID;
3001
0
            } else if (flags) {
3002
0
                LOGVAL(ctx->ctx, LYVE_REFERENCE,
3003
0
                        "Unique's descendant-schema-nodeid \"%.*s\" refers into %s node.",
3004
0
                        (int)len, keystr, flags & LYS_IS_NOTIF ? "notification" : "RPC/action");
3005
0
                return LY_EVALID;
3006
0
            }
3007
3008
            /* all referenced leafs must be of the same config type */
3009
0
            if ((config != -1) && ((((*key)->flags & LYS_CONFIG_W) && (config == 0)) ||
3010
0
                    (((*key)->flags & LYS_CONFIG_R) && (config == 1)))) {
3011
0
                LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3012
0
                        "Unique statement \"%s\" refers to leaves with different config type.", uniques[v].str);
3013
0
                return LY_EVALID;
3014
0
            } else if ((*key)->flags & LYS_CONFIG_W) {
3015
0
                config = 1;
3016
0
            } else { /* LYS_CONFIG_R */
3017
0
                config = 0;
3018
0
            }
3019
3020
            /* we forbid referencing nested lists because it is unspecified what instance of such a list to use */
3021
0
            for (parent = (*key)->parent; parent != (struct lysc_node *)list; parent = parent->parent) {
3022
0
                if (parent->nodetype == LYS_LIST) {
3023
0
                    LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3024
0
                            "Unique statement \"%s\" refers to a leaf in nested list \"%s\".", uniques[v].str, parent->name);
3025
0
                    return LY_EVALID;
3026
0
                }
3027
0
            }
3028
3029
            /* check status */
3030
0
            LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
3031
0
                    (*key)->flags, (*key)->module, (*key)->name));
3032
3033
            /* mark leaf as unique */
3034
0
            (*key)->flags |= LYS_UNIQUE;
3035
3036
            /* next unique value in line */
3037
0
            keystr = delim;
3038
0
        }
3039
        /* next unique definition */
3040
0
    }
3041
3042
0
    return LY_SUCCESS;
3043
0
}
3044
3045
/**
3046
 * @brief Compile parsed list node information.
3047
 * @param[in] ctx Compile context
3048
 * @param[in] pnode Parsed list node.
3049
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3050
 * is enriched with the list-specific information.
3051
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3052
 */
3053
static LY_ERR
3054
lys_compile_node_list(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
3055
0
{
3056
0
    struct lysp_node_list *list_p = (struct lysp_node_list *)pnode;
3057
0
    struct lysc_node_list *list = (struct lysc_node_list *)node;
3058
0
    struct lysp_node *child_p;
3059
0
    struct lysc_node_leaf *key, *prev_key = NULL;
3060
0
    size_t len;
3061
0
    const char *keystr, *delim;
3062
0
    LY_ERR ret = LY_SUCCESS;
3063
3064
0
    list->min = list_p->min;
3065
0
    if (list->min) {
3066
0
        list->flags |= LYS_MAND_TRUE;
3067
0
    }
3068
0
    list->max = list_p->max ? list_p->max : (uint32_t)-1;
3069
3070
0
    LY_LIST_FOR(list_p->child, child_p) {
3071
0
        LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0, NULL));
3072
0
    }
3073
3074
0
    COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, lys_compile_must, ret, done);
3075
0
    if (list_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
3076
        /* do not check "must" semantics in a grouping */
3077
0
        LY_CHECK_RET(ly_set_add(&ctx->unres->xpath, list, 0, NULL));
3078
0
    }
3079
3080
    /* keys */
3081
0
    if ((list->flags & LYS_CONFIG_W) && (!list_p->key || !list_p->key[0])) {
3082
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Missing key in list representing configuration data.");
3083
0
        return LY_EVALID;
3084
0
    }
3085
3086
    /* find all the keys (must be direct children) */
3087
0
    keystr = list_p->key;
3088
0
    if (!keystr) {
3089
        /* keyless list */
3090
0
        list->flags &= ~LYS_ORDBY_SYSTEM;
3091
0
        list->flags |= LYS_KEYLESS | LYS_ORDBY_USER;
3092
0
    }
3093
0
    while (keystr) {
3094
0
        delim = strpbrk(keystr, " \t\n");
3095
0
        if (delim) {
3096
0
            len = delim - keystr;
3097
0
            while (isspace(*delim)) {
3098
0
                ++delim;
3099
0
            }
3100
0
        } else {
3101
0
            len = strlen(keystr);
3102
0
        }
3103
3104
        /* key node must be present */
3105
0
        key = (struct lysc_node_leaf *)lys_find_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE);
3106
0
        if (!key) {
3107
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE, "The list's key \"%.*s\" not found.", (int)len, keystr);
3108
0
            return LY_EVALID;
3109
0
        }
3110
        /* keys must be unique */
3111
0
        if (key->flags & LYS_KEY) {
3112
            /* the node was already marked as a key */
3113
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Duplicated key identifier \"%.*s\".", (int)len, keystr);
3114
0
            return LY_EVALID;
3115
0
        }
3116
3117
0
        lysc_update_path(ctx, list->module, key->name);
3118
        /* key must have the same config flag as the list itself */
3119
0
        if ((list->flags & LYS_CONFIG_MASK) != (key->flags & LYS_CONFIG_MASK)) {
3120
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Key of the configuration list must not be status leaf.");
3121
0
            return LY_EVALID;
3122
0
        }
3123
0
        if (ctx->pmod->version < LYS_VERSION_1_1) {
3124
            /* YANG 1.0 denies key to be of empty type */
3125
0
            if (key->type->basetype == LY_TYPE_EMPTY) {
3126
0
                LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3127
0
                        "List's key cannot be of \"empty\" type until it is in YANG 1.1 module.");
3128
0
                return LY_EVALID;
3129
0
            }
3130
0
        } else {
3131
            /* when and if-feature are illegal on list keys */
3132
0
            if (key->when) {
3133
0
                LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3134
0
                        "List's key must not have any \"when\" statement.");
3135
0
                return LY_EVALID;
3136
0
            }
3137
            /* TODO check key, it cannot have any if-features */
3138
0
        }
3139
3140
        /* check status */
3141
0
        LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
3142
0
                key->flags, key->module, key->name));
3143
3144
        /* ignore default values of the key */
3145
0
        if (key->dflt) {
3146
0
            key->dflt->realtype->plugin->free(ctx->ctx, key->dflt);
3147
0
            lysc_type_free(ctx->ctx, (struct lysc_type *)key->dflt->realtype);
3148
0
            free(key->dflt);
3149
0
            key->dflt = NULL;
3150
0
        }
3151
        /* mark leaf as key */
3152
0
        key->flags |= LYS_KEY;
3153
3154
        /* move it to the correct position */
3155
0
        if ((prev_key && ((struct lysc_node *)prev_key != key->prev)) || (!prev_key && key->prev->next)) {
3156
            /* fix links in closest previous siblings of the key */
3157
0
            if (key->next) {
3158
0
                key->next->prev = key->prev;
3159
0
            } else {
3160
                /* last child */
3161
0
                list->child->prev = key->prev;
3162
0
            }
3163
0
            if (key->prev->next) {
3164
0
                key->prev->next = key->next;
3165
0
            }
3166
            /* fix links in the key */
3167
0
            if (prev_key) {
3168
0
                key->prev = &prev_key->node;
3169
0
                key->next = prev_key->next;
3170
0
            } else {
3171
0
                key->prev = list->child->prev;
3172
0
                key->next = list->child;
3173
0
            }
3174
            /* fix links in closes future siblings of the key */
3175
0
            if (prev_key) {
3176
0
                if (prev_key->next) {
3177
0
                    prev_key->next->prev = &key->node;
3178
0
                } else {
3179
0
                    list->child->prev = &key->node;
3180
0
                }
3181
0
                prev_key->next = &key->node;
3182
0
            } else {
3183
0
                list->child->prev = &key->node;
3184
0
            }
3185
            /* fix links in parent */
3186
0
            if (!key->prev->next) {
3187
0
                list->child = &key->node;
3188
0
            }
3189
0
        }
3190
3191
        /* next key value */
3192
0
        prev_key = key;
3193
0
        keystr = delim;
3194
0
        lysc_update_path(ctx, NULL, NULL);
3195
0
    }
3196
3197
    /* uniques */
3198
0
    if (list_p->uniques) {
3199
0
        LY_CHECK_RET(lys_compile_node_list_unique(ctx, list_p->uniques, list));
3200
0
    }
3201
3202
0
    LY_LIST_FOR((struct lysp_node *)list_p->actions, child_p) {
3203
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
3204
0
        LY_CHECK_GOTO(ret, done);
3205
0
    }
3206
0
    LY_LIST_FOR((struct lysp_node *)list_p->notifs, child_p) {
3207
0
        ret = lys_compile_node(ctx, child_p, node, 0, NULL);
3208
0
        LY_CHECK_GOTO(ret, done);
3209
0
    }
3210
3211
    /* checks */
3212
0
    if (list->min > list->max) {
3213
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "List min-elements %u is bigger than max-elements %u.",
3214
0
                list->min, list->max);
3215
0
        return LY_EVALID;
3216
0
    }
3217
3218
0
done:
3219
0
    return ret;
3220
0
}
3221
3222
/**
3223
 * @brief Do some checks and set the default choice's case.
3224
 *
3225
 * Selects (and stores into ::lysc_node_choice#dflt) the default case and set LYS_SET_DFLT flag on it.
3226
 *
3227
 * @param[in] ctx Compile context.
3228
 * @param[in] dflt Name of the default branch. Can even contain a prefix.
3229
 * @param[in,out] ch The compiled choice node, its dflt member is filled to point to the default case node of the choice.
3230
 * @return LY_ERR value.
3231
 */
3232
static LY_ERR
3233
lys_compile_node_choice_dflt(struct lysc_ctx *ctx, struct lysp_qname *dflt, struct lysc_node_choice *ch)
3234
0
{
3235
0
    struct lysc_node *iter;
3236
0
    const struct lys_module *mod;
3237
0
    const char *prefix = NULL, *name;
3238
0
    size_t prefix_len = 0;
3239
3240
    /* could use lys_parse_nodeid(), but it checks syntax which is already done in this case by the parsers */
3241
0
    name = strchr(dflt->str, ':');
3242
0
    if (name) {
3243
0
        prefix = dflt->str;
3244
0
        prefix_len = name - prefix;
3245
0
        ++name;
3246
0
    } else {
3247
0
        name = dflt->str;
3248
0
    }
3249
0
    if (prefix) {
3250
0
        mod = ly_resolve_prefix(ctx->ctx, prefix, prefix_len, LY_VALUE_SCHEMA, (void *)dflt->mod);
3251
0
        if (!mod) {
3252
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE, "Default case prefix \"%.*s\" not found "
3253
0
                    "in imports of \"%s\".", (int)prefix_len, prefix, LYSP_MODULE_NAME(dflt->mod));
3254
0
            return LY_EVALID;
3255
0
        }
3256
0
    } else {
3257
0
        mod = ch->module;
3258
0
    }
3259
3260
0
    ch->dflt = (struct lysc_node_case *)lys_find_child(&ch->node, mod, name, 0, LYS_CASE, LYS_GETNEXT_WITHCASE);
3261
0
    if (!ch->dflt) {
3262
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3263
0
                "Default case \"%s\" not found.", dflt->str);
3264
0
        return LY_EVALID;
3265
0
    }
3266
3267
    /* no mandatory nodes directly under the default case */
3268
0
    LY_LIST_FOR(ch->dflt->child, iter) {
3269
0
        if (iter->parent != (struct lysc_node *)ch->dflt) {
3270
0
            break;
3271
0
        }
3272
0
        if (iter->flags & LYS_MAND_TRUE) {
3273
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3274
0
                    "Mandatory node \"%s\" under the default case \"%s\".", iter->name, dflt->str);
3275
0
            return LY_EVALID;
3276
0
        }
3277
0
    }
3278
3279
0
    if (ch->flags & LYS_MAND_TRUE) {
3280
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS, "Invalid mandatory choice with a default case.");
3281
0
        return LY_EVALID;
3282
0
    }
3283
3284
0
    ch->dflt->flags |= LYS_SET_DFLT;
3285
0
    return LY_SUCCESS;
3286
0
}
3287
3288
LY_ERR
3289
lys_compile_node_choice_child(struct lysc_ctx *ctx, struct lysp_node *child_p, struct lysc_node *node,
3290
        struct ly_set *child_set)
3291
0
{
3292
0
    LY_ERR ret = LY_SUCCESS;
3293
0
    struct lysp_node *child_p_next = child_p->next;
3294
0
    struct lysp_node_case *cs_p;
3295
3296
0
    if (child_p->nodetype == LYS_CASE) {
3297
        /* standard case under choice */
3298
0
        ret = lys_compile_node(ctx, child_p, node, 0, child_set);
3299
0
    } else {
3300
        /* we need the implicit case first, so create a fake parsed case */
3301
0
        cs_p = calloc(1, sizeof *cs_p);
3302
0
        cs_p->nodetype = LYS_CASE;
3303
0
        DUP_STRING_GOTO(ctx->ctx, child_p->name, cs_p->name, ret, free_fake_node);
3304
0
        cs_p->child = child_p;
3305
3306
        /* make the child the only case child */
3307
0
        child_p->next = NULL;
3308
3309
        /* compile it normally */
3310
0
        ret = lys_compile_node(ctx, (struct lysp_node *)cs_p, node, 0, child_set);
3311
3312
0
free_fake_node:
3313
        /* free the fake parsed node and correct pointers back */
3314
0
        cs_p->child = NULL;
3315
0
        lysp_node_free(ctx->ctx, (struct lysp_node *)cs_p);
3316
0
        child_p->next = child_p_next;
3317
0
    }
3318
3319
0
    return ret;
3320
0
}
3321
3322
/**
3323
 * @brief Compile parsed choice node information.
3324
 *
3325
 * @param[in] ctx Compile context
3326
 * @param[in] pnode Parsed choice node.
3327
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3328
 * is enriched with the choice-specific information.
3329
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3330
 */
3331
static LY_ERR
3332
lys_compile_node_choice(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
3333
0
{
3334
0
    struct lysp_node_choice *ch_p = (struct lysp_node_choice *)pnode;
3335
0
    struct lysc_node_choice *ch = (struct lysc_node_choice *)node;
3336
0
    struct lysp_node *child_p;
3337
0
    LY_ERR ret = LY_SUCCESS;
3338
3339
0
    assert(node->nodetype == LYS_CHOICE);
3340
3341
0
    LY_LIST_FOR(ch_p->child, child_p) {
3342
0
        LY_CHECK_RET(lys_compile_node_choice_child(ctx, child_p, node, NULL));
3343
0
    }
3344
3345
    /* default branch */
3346
0
    if (ch_p->dflt.str) {
3347
0
        LY_CHECK_RET(lys_compile_node_choice_dflt(ctx, &ch_p->dflt, ch));
3348
0
    }
3349
3350
0
    return ret;
3351
0
}
3352
3353
/**
3354
 * @brief Compile parsed anydata or anyxml node information.
3355
 * @param[in] ctx Compile context
3356
 * @param[in] pnode Parsed anydata or anyxml node.
3357
 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3358
 * is enriched with the any-specific information.
3359
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3360
 */
3361
static LY_ERR
3362
lys_compile_node_any(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
3363
0
{
3364
0
    struct lysp_node_anydata *any_p = (struct lysp_node_anydata *)pnode;
3365
0
    struct lysc_node_anydata *any = (struct lysc_node_anydata *)node;
3366
0
    LY_ERR ret = LY_SUCCESS;
3367
3368
0
    COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, lys_compile_must, ret, done);
3369
0
    if (any_p->musts && !(ctx->options & (LYS_COMPILE_GROUPING | LYS_COMPILE_DISABLED))) {
3370
        /* do not check "must" semantics in a grouping */
3371
0
        ret = ly_set_add(&ctx->unres->xpath, any, 0, NULL);
3372
0
        LY_CHECK_GOTO(ret, done);
3373
0
    }
3374
3375
0
    if (any->flags & LYS_CONFIG_W) {
3376
0
        LOGVRB("Use of %s to define configuration data is not recommended. %s",
3377
0
                ly_stmt2str(any->nodetype == LYS_ANYDATA ? LY_STMT_ANYDATA : LY_STMT_ANYXML), ctx->path);
3378
0
    }
3379
0
done:
3380
0
    return ret;
3381
0
}
3382
3383
/**
3384
 * @brief Prepare the case structure in choice node for the new data node.
3385
 *
3386
 * It is able to handle implicit as well as explicit cases and the situation when the case has multiple data nodes and the case was already
3387
 * created in the choice when the first child was processed.
3388
 *
3389
 * @param[in] ctx Compile context.
3390
 * @param[in] pnode Node image from the parsed tree. If the case is explicit, it is the LYS_CASE node, but in case of implicit case,
3391
 *                   it is the LYS_CHOICE, LYS_AUGMENT or LYS_GROUPING node.
3392
 * @param[in] ch The compiled choice structure where the new case structures are created (if needed).
3393
 * @param[in] child The new data node being part of a case (no matter if explicit or implicit).
3394
 * @return The case structure where the child node belongs to, NULL in case of error. Note that the child is not connected into the siblings list,
3395
 * it is linked from the case structure only in case it is its first child.
3396
 */
3397
static LY_ERR
3398
lys_compile_node_case(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
3399
0
{
3400
0
    struct lysp_node *child_p;
3401
0
    struct lysp_node_case *cs_p = (struct lysp_node_case *)pnode;
3402
3403
0
    if (pnode->nodetype & (LYS_CHOICE | LYS_AUGMENT | LYS_GROUPING)) {
3404
        /* we have to add an implicit case node into the parent choice */
3405
0
    } else if (pnode->nodetype == LYS_CASE) {
3406
        /* explicit parent case */
3407
0
        LY_LIST_FOR(cs_p->child, child_p) {
3408
0
            LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0, NULL));
3409
0
        }
3410
0
    } else {
3411
0
        LOGINT_RET(ctx->ctx);
3412
0
    }
3413
3414
0
    return LY_SUCCESS;
3415
0
}
3416
3417
void
3418
lys_compile_mandatory_parents(struct lysc_node *parent, ly_bool add)
3419
0
{
3420
0
    const struct lysc_node *iter;
3421
3422
0
    if (add) { /* set flag */
3423
0
        for ( ; parent && parent->nodetype == LYS_CONTAINER && !(parent->flags & LYS_MAND_TRUE) && !(parent->flags & LYS_PRESENCE);
3424
0
                parent = parent->parent) {
3425
0
            parent->flags |= LYS_MAND_TRUE;
3426
0
        }
3427
0
    } else { /* unset flag */
3428
0
        for ( ; parent && parent->nodetype == LYS_CONTAINER && (parent->flags & LYS_MAND_TRUE); parent = parent->parent) {
3429
0
            for (iter = lysc_node_child(parent); iter; iter = iter->next) {
3430
0
                if (iter->flags & LYS_MAND_TRUE) {
3431
                    /* there is another mandatory node */
3432
0
                    return;
3433
0
                }
3434
0
            }
3435
            /* unset mandatory flag - there is no mandatory children in the non-presence container */
3436
0
            parent->flags &= ~LYS_MAND_TRUE;
3437
0
        }
3438
0
    }
3439
0
}
3440
3441
/**
3442
 * @brief Get the grouping with the specified name from given groupings sized array.
3443
 * @param[in] grps Linked list of groupings.
3444
 * @param[in] name Name of the grouping to find,
3445
 * @return NULL when there is no grouping with the specified name
3446
 * @return Pointer to the grouping of the specified @p name.
3447
 */
3448
static struct lysp_node_grp *
3449
match_grouping(struct lysp_node_grp *grps, const char *name)
3450
0
{
3451
0
    struct lysp_node_grp *grp;
3452
3453
0
    LY_LIST_FOR(grps, grp) {
3454
0
        if (!strcmp(grp->name, name)) {
3455
0
            return grp;
3456
0
        }
3457
0
    }
3458
3459
0
    return NULL;
3460
0
}
3461
3462
/**
3463
 * @brief Find grouping for a uses.
3464
 *
3465
 * @param[in] ctx Compile context.
3466
 * @param[in] uses_p Parsed uses node.
3467
 * @param[out] gpr_p Found grouping on success.
3468
 * @param[out] grp_pmod Module of @p grp_p on success.
3469
 * @return LY_ERR value.
3470
 */
3471
static LY_ERR
3472
lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_node_grp **grp_p,
3473
        struct lysp_module **grp_pmod)
3474
0
{
3475
0
    struct lysp_node *pnode;
3476
0
    struct lysp_node_grp *grp;
3477
0
    LY_ARRAY_COUNT_TYPE u;
3478
0
    const char *id, *name, *prefix, *local_pref;
3479
0
    size_t prefix_len, name_len;
3480
0
    struct lysp_module *pmod, *found = NULL;
3481
0
    const struct lys_module *mod;
3482
3483
0
    *grp_p = NULL;
3484
0
    *grp_pmod = NULL;
3485
3486
    /* search for the grouping definition */
3487
0
    id = uses_p->name;
3488
0
    LY_CHECK_RET(ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len), LY_EVALID);
3489
0
    local_pref = ctx->pmod->is_submod ? ((struct lysp_submodule *)ctx->pmod)->prefix : ctx->pmod->mod->prefix;
3490
0
    if (!prefix || !ly_strncmp(local_pref, prefix, prefix_len)) {
3491
        /* current module, search local groupings first */
3492
0
        pmod = ctx->pmod->mod->parsed; /* make sure that we will start in main_module, not submodule */
3493
0
        for (pnode = uses_p->parent; !found && pnode; pnode = pnode->parent) {
3494
0
            if ((grp = match_grouping((struct lysp_node_grp *)lysp_node_groupings(pnode), name))) {
3495
0
                found = ctx->pmod;
3496
0
                break;
3497
0
            }
3498
0
        }
3499
0
    } else {
3500
        /* foreign module, find it first */
3501
0
        mod = ly_resolve_prefix(ctx->ctx, prefix, prefix_len, LY_VALUE_SCHEMA, ctx->pmod);
3502
0
        if (!mod) {
3503
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE,
3504
0
                    "Invalid prefix used for grouping reference.", uses_p->name);
3505
0
            return LY_EVALID;
3506
0
        }
3507
0
        pmod = mod->parsed;
3508
0
    }
3509
3510
0
    if (!found) {
3511
        /* search in top-level groupings of the main module ... */
3512
0
        if ((grp = match_grouping(pmod->groupings, name))) {
3513
0
            found = pmod;
3514
0
        } else {
3515
            /* ... and all the submodules */
3516
0
            LY_ARRAY_FOR(pmod->includes, u) {
3517
0
                if ((grp = match_grouping(pmod->includes[u].submodule->groupings, name))) {
3518
0
                    found = (struct lysp_module *)pmod->includes[u].submodule;
3519
0
                    break;
3520
0
                }
3521
0
            }
3522
0
        }
3523
0
    }
3524
0
    if (!found) {
3525
0
        LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3526
0
                "Grouping \"%s\" referenced by a uses statement not found.", uses_p->name);
3527
0
        return LY_EVALID;
3528
0
    }
3529
3530
0
    if (!(ctx->options & LYS_COMPILE_GROUPING)) {
3531
        /* remember that the grouping is instantiated to avoid its standalone validation */
3532
0
        grp->flags |= LYS_USED_GRP;
3533
0
    }
3534
3535
0
    *grp_p = grp;
3536
0
    *grp_pmod = found;
3537
0
    return LY_SUCCESS;
3538
0
}
3539
3540
/**
3541
 * @brief Compile parsed uses statement - resolve target grouping and connect its content into parent.
3542
 * If present, also apply uses's modificators.
3543
 *
3544
 * @param[in] ctx Compile context
3545
 * @param[in] uses_p Parsed uses schema node.
3546
 * @param[in] parent Compiled parent node where the content of the referenced grouping is supposed to be connected. It is
3547
 * NULL for top-level nodes, in such a case the module where the node will be connected is taken from
3548
 * the compile context.
3549
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3550
 */
3551
static LY_ERR
3552
lys_compile_uses(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysc_node *parent, struct ly_set *child_set)
3553
0
{
3554
0
    struct lysp_node *pnode;
3555
0
    struct lysc_node *child;
3556
0
    struct lysp_node_grp *grp = NULL;
3557
0
    uint32_t i, grp_stack_count;
3558
0
    struct lysp_module *grp_mod, *mod_old = ctx->pmod;
3559
0
    LY_ERR ret = LY_SUCCESS;
3560
0
    struct lysc_when *when_shared = NULL;
3561
0
    struct ly_set uses_child_set = {0};
3562
3563
    /* find the referenced grouping */
3564
0
    LY_CHECK_RET(lys_compile_uses_find_grouping(ctx, uses_p, &grp, &grp_mod));
3565
3566
    /* grouping must not reference themselves - stack in ctx maintains list of groupings currently being applied */
3567
0
    grp_stack_count = ctx->groupings.count;
3568
0
    LY_CHECK_RET(ly_set_add(&ctx->groupings, (void *)grp, 0, NULL));
3569
0
    if (grp_stack_count == ctx->groupings.count) {
3570
        /* the target grouping is already in the stack, so we are already inside it -> circular dependency */
3571
0
        LOGVAL(ctx->ctx, LYVE_REFERENCE,
3572
0
                "Grouping \"%s\" references itself through a uses statement.", grp->name);
3573
0
        return LY_EVALID;
3574
0
    }
3575
3576
    /* check status */
3577
0
    ret = lysc_check_status(ctx, uses_p->flags, ctx->pmod, uses_p->name, grp->flags, grp_mod, grp->name);
3578
0
    LY_CHECK_GOTO(ret, cleanup);
3579
3580
    /* compile any augments and refines so they can be applied during the grouping nodes compilation */
3581
0
    ret = lys_precompile_uses_augments_refines(ctx, uses_p, parent);
3582
0
    LY_CHECK_GOTO(ret, cleanup);
3583
3584
    /* switch context's parsed module being processed */
3585
0
    ctx->pmod = grp_mod;
3586
3587
    /* compile data nodes */
3588
0
    LY_LIST_FOR(grp->child, pnode) {
3589
        /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
3590
0
        ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
3591
0
        LY_CHECK_GOTO(ret, cleanup);
3592
0
    }
3593
3594
0
    if (child_set) {
3595
        /* add these children to our compiled child_set as well since uses is a schema-only node */
3596
0
        LY_CHECK_GOTO(ret = ly_set_merge(child_set, &uses_child_set, 1, NULL), cleanup);
3597
0
    }
3598
3599
0
    if (uses_p->when) {
3600
        /* pass uses's when to all the data children */
3601
0
        for (i = 0; i < uses_child_set.count; ++i) {
3602
0
            child = uses_child_set.snodes[i];
3603
3604
0
            ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
3605
0
            LY_CHECK_GOTO(ret, cleanup);
3606
0
        }
3607
0
    }
3608
3609
    /* compile actions */
3610
0
    if (grp->actions) {
3611
0
        struct lysc_node_action **actions;
3612
0
        actions = parent ? lysc_node_actions_p(parent) : &ctx->cur_mod->compiled->rpcs;
3613
0
        if (!actions) {
3614
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
3615
0
                    grp->actions->name, lys_nodetype2str(grp->actions->nodetype),
3616
0
                    parent->name, lys_nodetype2str(parent->nodetype));
3617
0
            ret = LY_EVALID;
3618
0
            goto cleanup;
3619
0
        }
3620
0
        LY_LIST_FOR((struct lysp_node *)grp->actions, pnode) {
3621
            /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
3622
0
            ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
3623
0
            LY_CHECK_GOTO(ret, cleanup);
3624
0
        }
3625
3626
0
        if (uses_p->when) {
3627
            /* inherit when */
3628
0
            LY_LIST_FOR((struct lysc_node *)*actions, child) {
3629
0
                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
3630
0
                LY_CHECK_GOTO(ret, cleanup);
3631
0
            }
3632
0
        }
3633
0
    }
3634
3635
    /* compile notifications */
3636
0
    if (grp->notifs) {
3637
0
        struct lysc_node_notif **notifs;
3638
0
        notifs = parent ? lysc_node_notifs_p(parent) : &ctx->cur_mod->compiled->notifs;
3639
0
        if (!notifs) {
3640
0
            LOGVAL(ctx->ctx, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
3641
0
                    grp->notifs->name, lys_nodetype2str(grp->notifs->nodetype),
3642
0
                    parent->name, lys_nodetype2str(parent->nodetype));
3643
0
            ret = LY_EVALID;
3644
0
            goto cleanup;
3645
0
        }
3646
3647
0
        LY_LIST_FOR((struct lysp_node *)grp->notifs, pnode) {
3648
            /* LYS_STATUS_USES in uses_status is a special bits combination to be able to detect status flags from uses */
3649
0
            ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | LYS_STATUS_USES, &uses_child_set);
3650
0
            LY_CHECK_GOTO(ret, cleanup);
3651
0
        }
3652
3653
0
        if (uses_p->when) {
3654
            /* inherit when */
3655
0
            LY_LIST_FOR((struct lysc_node *)*notifs, child) {
3656
0
                ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_data_node(parent), child, &when_shared);
3657
0
                LY_CHECK_GOTO(ret, cleanup);
3658
0
            }
3659
0
        }
3660
0
    }
3661
3662
    /* check that all augments were applied */
3663
0
    for (i = 0; i < ctx->uses_augs.count; ++i) {
3664
0
        if (((struct lysc_augment *)ctx->uses_augs.objs[i])->aug_p->parent != (struct lysp_node *)uses_p) {
3665
            /* augment of some parent uses, irrelevant now */
3666
0
            continue;
3667
0
        }
3668
3669
0
        LOGVAL(ctx->ctx, LYVE_REFERENCE, "Augment target node \"%s\" in grouping \"%s\" was not found.",
3670
0
                ((struct lysc_augment *)ctx->uses_augs.objs[i])->nodeid->expr, grp->name);
3671
0
        ret = LY_ENOTFOUND;
3672
0
    }
3673
0
    LY_CHECK_GOTO(ret, cleanup);
3674
3675
    /* check that all refines were applied */
3676
0
    for (i = 0; i < ctx->uses_rfns.count; ++i) {
3677
0
        if (((struct lysc_refine *)ctx->uses_rfns.objs[i])->uses_p != uses_p) {
3678
            /* refine of some paretn uses, irrelevant now */
3679
0
            continue;
3680
0
        }
3681
3682
0
        LOGVAL(ctx->ctx, LYVE_REFERENCE, "Refine(s) target node \"%s\" in grouping \"%s\" was not found.",
3683
0
                ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid->expr, grp->name);
3684
0
        ret = LY_ENOTFOUND;
3685
0
    }
3686
0
    LY_CHECK_GOTO(ret, cleanup);
3687
3688
0
cleanup:
3689
    /* reload previous context's parsed module being processed */
3690
0
    ctx->pmod = mod_old;
3691
3692
    /* remove the grouping from the stack for circular groupings dependency check */
3693
0
    ly_set_rm_index(&ctx->groupings, ctx->groupings.count - 1, NULL);
3694
0
    assert(ctx->groupings.count == grp_stack_count);
3695
3696
0
    ly_set_erase(&uses_child_set, NULL);
3697
0
    return ret;
3698
0
}
3699
3700
static int
3701
lys_compile_grouping_pathlog(struct lysc_ctx *ctx, struct lysp_node *node, char **path)
3702
0
{
3703
0
    struct lysp_node *iter;
3704
0
    int len = 0;
3705
3706
0
    *path = NULL;
3707
0
    for (iter = node; iter && len >= 0; iter = iter->parent) {
3708
0
        char *s = *path;
3709
0
        char *id;
3710
3711
0
        switch (iter->nodetype) {
3712
0
        case LYS_USES:
3713
0
            LY_CHECK_RET(asprintf(&id, "{uses='%s'}", iter->name) == -1, -1);
3714
0
            break;
3715
0
        case LYS_GROUPING:
3716
0
            LY_CHECK_RET(asprintf(&id, "{grouping='%s'}", iter->name) == -1, -1);
3717
0
            break;
3718
0
        case LYS_AUGMENT:
3719
0
            LY_CHECK_RET(asprintf(&id, "{augment='%s'}", iter->name) == -1, -1);
3720
0
            break;
3721
0
        default:
3722
0
            id = strdup(iter->name);
3723
0
            break;
3724
0
        }
3725
3726
0
        if (!iter->parent) {
3727
            /* print prefix */
3728
0
            len = asprintf(path, "/%s:%s%s", ctx->cur_mod->name, id, s ? s : "");
3729
0
        } else {
3730
            /* prefix is the same as in parent */
3731
0
            len = asprintf(path, "/%s%s", id, s ? s : "");
3732
0
        }
3733
0
        free(s);
3734
0
        free(id);
3735
0
    }
3736
3737
0
    if (len < 0) {
3738
0
        free(*path);
3739
0
        *path = NULL;
3740
0
    } else if (len == 0) {
3741
0
        *path = strdup("/");
3742
0
        len = 1;
3743
0
    }
3744
0
    return len;
3745
0
}
3746
3747
LY_ERR
3748
lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_node_grp *grp)
3749
0
{
3750
0
    LY_ERR ret;
3751
0
    char *path;
3752
0
    int len;
3753
3754
0
    struct lysp_node_uses fake_uses = {
3755
0
        .parent = pnode,
3756
0
        .nodetype = LYS_USES,
3757
0
        .flags = 0, .next = NULL,
3758
0
        .name = grp->name,
3759
0
        .dsc = NULL, .ref = NULL, .when = NULL, .iffeatures = NULL, .exts = NULL,
3760
0
        .refines = NULL, .augments = NULL
3761
0
    };
3762
0
    struct lysc_node_container fake_container = {
3763
0
        .nodetype = LYS_CONTAINER,
3764
0
        .flags = pnode ? (pnode->flags & LYS_FLAGS_COMPILED_MASK) : 0,
3765
0
        .module = ctx->cur_mod,
3766
0
        .parent = NULL, .next = NULL,
3767
0
        .prev = &fake_container.node,
3768
0
        .name = "fake",
3769
0
        .dsc = NULL, .ref = NULL, .exts = NULL, .when = NULL,
3770
0
        .child = NULL, .musts = NULL, .actions = NULL, .notifs = NULL
3771
0
    };
3772
3773
0
    if (grp->parent) {
3774
0
        LOGWRN(ctx->ctx, "Locally scoped grouping \"%s\" not used.", grp->name);
3775
0
    }
3776
3777
0
    len = lys_compile_grouping_pathlog(ctx, grp->parent, &path);
3778
0
    if (len < 0) {
3779
0
        LOGMEM(ctx->ctx);
3780
0
        return LY_EMEM;
3781
0
    }
3782
0
    strncpy(ctx->path, path, LYSC_CTX_BUFSIZE - 1);
3783
0
    ctx->path_len = (uint32_t)len;
3784
0
    free(path);
3785
3786
0
    lysc_update_path(ctx, NULL, "{grouping}");
3787
0
    lysc_update_path(ctx, NULL, grp->name);
3788
0
    ret = lys_compile_uses(ctx, &fake_uses, &fake_container.node, NULL);
3789
0
    lysc_update_path(ctx, NULL, NULL);
3790
0
    lysc_update_path(ctx, NULL, NULL);
3791
3792
0
    ctx->path_len = 1;
3793
0
    ctx->path[1] = '\0';
3794
3795
    /* cleanup */
3796
0
    lysc_node_container_free(ctx->ctx, &fake_container);
3797
3798
0
    return ret;
3799
0
}
3800
3801
LY_ERR
3802
lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
3803
        struct ly_set *child_set)
3804
0
{
3805
0
    LY_ERR ret = LY_SUCCESS;
3806
0
    struct lysc_node *node = NULL;
3807
0
    uint32_t prev_opts = ctx->options;
3808
3809
0
    LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *);
3810
3811
0
    if (pnode->nodetype != LYS_USES) {
3812
0
        lysc_update_path(ctx, parent ? parent->module : NULL, pnode->name);
3813
0
    } else {
3814
0
        lysc_update_path(ctx, NULL, "{uses}");
3815
0
        lysc_update_path(ctx, NULL, pnode->name);
3816
0
    }
3817
3818
0
    switch (pnode->nodetype) {
3819
0
    case LYS_CONTAINER:
3820
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_container));
3821
0
        node_compile_spec = lys_compile_node_container;
3822
0
        break;
3823
0
    case LYS_LEAF:
3824
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_leaf));
3825
0
        node_compile_spec = lys_compile_node_leaf;
3826
0
        break;
3827
0
    case LYS_LIST:
3828
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_list));
3829
0
        node_compile_spec = lys_compile_node_list;
3830
0
        break;
3831
0
    case LYS_LEAFLIST:
3832
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_leaflist));
3833
0
        node_compile_spec = lys_compile_node_leaflist;
3834
0
        break;
3835
0
    case LYS_CHOICE:
3836
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_choice));
3837
0
        node_compile_spec = lys_compile_node_choice;
3838
0
        break;
3839
0
    case LYS_CASE:
3840
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_case));
3841
0
        node_compile_spec = lys_compile_node_case;
3842
0
        break;
3843
0
    case LYS_ANYXML:
3844
0
    case LYS_ANYDATA:
3845
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_anydata));
3846
0
        node_compile_spec = lys_compile_node_any;
3847
0
        break;
3848
0
    case LYS_RPC:
3849
0
    case LYS_ACTION:
3850
0
        if (ctx->options & (LYS_IS_INPUT | LYS_IS_OUTPUT | LYS_IS_NOTIF)) {
3851
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3852
0
                    "Action \"%s\" is placed inside %s.", pnode->name,
3853
0
                    (ctx->options & LYS_IS_NOTIF) ? "notification" : "another RPC/action");
3854
0
            return LY_EVALID;
3855
0
        }
3856
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_action));
3857
0
        node_compile_spec = lys_compile_node_action;
3858
0
        ctx->options |= LYS_COMPILE_NO_CONFIG;
3859
0
        break;
3860
0
    case LYS_NOTIF:
3861
0
        if (ctx->options & (LYS_IS_INPUT | LYS_IS_OUTPUT | LYS_IS_NOTIF)) {
3862
0
            LOGVAL(ctx->ctx, LYVE_SEMANTICS,
3863
0
                    "Notification \"%s\" is placed inside %s.", pnode->name,
3864
0
                    (ctx->options & LYS_IS_NOTIF) ? "another notification" : "RPC/action");
3865
0
            return LY_EVALID;
3866
0
        }
3867
0
        node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_notif));
3868
0
        node_compile_spec = lys_compile_node_notif;
3869
0
        ctx->options |= LYS_COMPILE_NOTIFICATION;
3870
0
        break;
3871
0
    case LYS_USES:
3872
0
        ret = lys_compile_uses(ctx, (struct lysp_node_uses *)pnode, parent, child_set);
3873
0
        lysc_update_path(ctx, NULL, NULL);
3874
0
        lysc_update_path(ctx, NULL, NULL);
3875
0
        return ret;
3876
0
    default:
3877
0
        LOGINT(ctx->ctx);
3878
0
        return LY_EINT;
3879
0
    }
3880
0
    LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
3881
3882
0
    ret = lys_compile_node_(ctx, pnode, parent, uses_status, node_compile_spec, node, child_set);
3883
3884
0
    ctx->options = prev_opts;
3885
0
    lysc_update_path(ctx, NULL, NULL);
3886
0
    return ret;
3887
0
}