Coverage Report

Created: 2026-03-26 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libyang/src/schema_compile.c
Line
Count
Source
1
/**
2
 * @file schema_compile.c
3
 * @author Radek Krejci <rkrejci@cesnet.cz>
4
 * @author Michal Vasko <mvasko@cesnet.cz>
5
 * @brief Schema compilation.
6
 *
7
 * Copyright (c) 2015 - 2024 CESNET, z.s.p.o.
8
 *
9
 * This source code is licensed under BSD 3-Clause License (the "License").
10
 * You may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     https://opensource.org/licenses/BSD-3-Clause
14
 */
15
16
#define _GNU_SOURCE
17
18
#include "schema_compile.h"
19
20
#include <assert.h>
21
#include <stddef.h>
22
#include <stdint.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "compat.h"
28
#include "context.h"
29
#include "dict.h"
30
#include "in.h"
31
#include "log.h"
32
#include "ly_common.h"
33
#include "lyb.h"
34
#include "parser_schema.h"
35
#include "path.h"
36
#include "plugins.h"
37
#include "plugins_exts.h"
38
#include "plugins_internal.h"
39
#include "plugins_types.h"
40
#include "schema_compile_amend.h"
41
#include "schema_compile_node.h"
42
#include "schema_features.h"
43
#include "set.h"
44
#include "tree.h"
45
#include "tree_data.h"
46
#include "tree_schema.h"
47
#include "tree_schema_free.h"
48
#include "tree_schema_internal.h"
49
#include "xpath.h"
50
51
void
52
lysc_update_path(struct lysc_ctx *ctx, const struct lys_module *parent_module, const char *name)
53
11.9M
{
54
11.9M
    int len;
55
11.9M
    uint8_t nextlevel = 0; /* 0 - no starttag, 1 - '/' starttag, 2 - '=' starttag + '}' endtag */
56
57
11.9M
    if (!name) {
58
        /* removing last path segment */
59
5.98M
        if (ctx->path[ctx->path_len - 1] == '}') {
60
43.1M
            for ( ; ctx->path[ctx->path_len] != '=' && ctx->path[ctx->path_len] != '{'; --ctx->path_len) {}
61
2.87M
            if (ctx->path[ctx->path_len] == '=') {
62
1.49M
                ctx->path[ctx->path_len++] = '}';
63
1.49M
            } else {
64
                /* not a top-level special tag, remove also preceiding '/' */
65
1.37M
                goto remove_nodelevel;
66
1.37M
            }
67
3.11M
        } else {
68
4.48M
remove_nodelevel:
69
53.0M
            for ( ; ctx->path[ctx->path_len] != '/'; --ctx->path_len) {}
70
4.48M
            if (ctx->path_len == 0) {
71
                /* top-level (last segment) */
72
1.44M
                ctx->path_len = 1;
73
1.44M
            }
74
4.48M
        }
75
        /* set new terminating NULL-byte */
76
5.98M
        ctx->path[ctx->path_len] = '\0';
77
5.99M
    } else {
78
5.99M
        if (ctx->path_len > 1) {
79
4.54M
            if (!parent_module && (ctx->path[ctx->path_len - 1] == '}') && (ctx->path[ctx->path_len - 2] != '\'')) {
80
                /* extension of the special tag */
81
1.50M
                nextlevel = 2;
82
1.50M
                --ctx->path_len;
83
3.04M
            } else {
84
                /* there is already some path, so add next level */
85
3.04M
                nextlevel = 1;
86
3.04M
            }
87
4.54M
        } /* else the path is just initiated with '/', so do not add additional slash in case of top-level nodes */
88
89
5.99M
        if (nextlevel != 2) {
90
4.49M
            if ((parent_module && (parent_module == ctx->cur_mod)) || (!parent_module && (ctx->path_len > 1) && (name[0] == '{'))) {
91
                /* module not changed, print the name unprefixed */
92
3.04M
                len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "%s%s",
93
3.04M
                        nextlevel ? "/" : "", name);
94
3.04M
            } else {
95
1.44M
                len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "%s%s:%s",
96
1.44M
                        nextlevel ? "/" : "", ctx->cur_mod->name, name);
97
1.44M
            }
98
4.49M
        } else {
99
1.50M
            len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "='%s'}", name);
100
1.50M
        }
101
5.99M
        if (len >= LYSC_CTX_BUFSIZE - (int)ctx->path_len) {
102
            /* output truncated */
103
5.61k
            ctx->path_len = LYSC_CTX_BUFSIZE - 1;
104
5.98M
        } else {
105
5.98M
            ctx->path_len += len;
106
5.98M
        }
107
5.99M
    }
108
109
11.9M
    ly_log_location_revert(0, 1, 0);
110
11.9M
    ly_log_location(NULL, ctx->path, NULL);
111
11.9M
}
112
113
LY_ERR
114
lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lysc_ext_instance *ext, void *parent)
115
396k
{
116
396k
    LY_ERR ret = LY_SUCCESS;
117
396k
    struct lyplg_ext *ext_plg;
118
119
396k
    DUP_STRING_GOTO(ctx->ctx, extp->argument, ext->argument, ret, cleanup);
120
396k
    ext->module = ctx->cur_mod;
121
396k
    ext->parent = parent;
122
396k
    ext->parent_stmt = extp->parent_stmt;
123
396k
    ext->parent_stmt_index = extp->parent_stmt_index;
124
125
396k
    lysc_update_path(ctx, (ext->parent_stmt & LY_STMT_NODE_MASK) ? ((struct lysc_node *)ext->parent)->module : NULL,
126
396k
            "{ext-inst}");
127
396k
    lysc_update_path(ctx, NULL, extp->name);
128
129
    /* find the compiled extension definition */
130
396k
    LY_CHECK_GOTO(ret = lysc_ext_find_definition(ctx->ctx, extp, &ext->def), cleanup);
131
132
    /* compile nested extensions */
133
396k
    COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup);
134
135
    /* compile this extension */
136
396k
    if (ext->def->plugin_ref && (ext_plg = LYSC_GET_EXT_PLG(ext->def->plugin_ref))->compile) {
137
396k
        if (ext->argument) {
138
396k
            lysc_update_path(ctx, ext->module, ext->argument);
139
396k
        }
140
396k
        ret = ext_plg->compile(ctx, extp, ext);
141
396k
        if (ret == LY_ENOT) {
142
0
            lysc_ext_instance_free(ctx->ctx, ext);
143
0
        }
144
396k
        if (ext->argument) {
145
396k
            lysc_update_path(ctx, NULL, NULL);
146
396k
        }
147
396k
        LY_CHECK_GOTO(ret, cleanup);
148
396k
    }
149
150
396k
cleanup:
151
396k
    lysc_update_path(ctx, NULL, NULL);
152
396k
    lysc_update_path(ctx, NULL, NULL);
153
396k
    return ret;
154
396k
}
155
156
static void
157
lysc_unres_must_free(struct lysc_unres_must *m)
158
1.11k
{
159
1.11k
    LY_ARRAY_FREE(m->local_mods);
160
1.11k
    free(m);
161
1.11k
}
162
163
static void
164
lysc_unres_dflt_free(const struct ly_ctx *ctx, struct lysc_unres_dflt *r)
165
26.7k
{
166
26.7k
    assert(!r->dflt || !r->dflts);
167
26.7k
    if (r->dflt) {
168
26.7k
        lysp_qname_free((struct ly_ctx *)ctx, r->dflt);
169
26.7k
        free(r->dflt);
170
26.7k
    } else {
171
0
        FREE_ARRAY((struct ly_ctx *)ctx, r->dflts, lysp_qname_free);
172
0
    }
173
26.7k
    free(r);
174
26.7k
}
175
176
LY_ERR
177
lys_identity_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lysp_module *parsed_mod,
178
        const struct lysp_ident *identities_p, struct lysc_ident **identities)
179
262k
{
180
262k
    LY_ARRAY_COUNT_TYPE u, v;
181
262k
    struct lysc_ctx cctx = {0};
182
262k
    struct lysc_ident *ident;
183
262k
    LY_ERR ret = LY_SUCCESS;
184
185
262k
    assert(ctx_sc || ctx);
186
187
262k
    if (!ctx_sc) {
188
262k
        if (parsed_mod) {
189
262k
            LYSC_CTX_INIT_PMOD(cctx, parsed_mod, NULL);
190
262k
        } else {
191
0
            LYSC_CTX_INIT_CTX(cctx, ctx);
192
0
        }
193
262k
        ctx_sc = &cctx;
194
262k
    }
195
196
262k
    if (!identities_p) {
197
215k
        return LY_SUCCESS;
198
215k
    }
199
200
46.5k
    lysc_update_path(ctx_sc, NULL, "{identity}");
201
260k
    LY_ARRAY_FOR(identities_p, u) {
202
260k
        lysc_update_path(ctx_sc, NULL, identities_p[u].name);
203
204
        /* add new compiled identity */
205
260k
        LY_ARRAY_NEW_GOTO(ctx_sc->ctx, *identities, ident, ret, done);
206
207
260k
        DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].name, ident->name, ret, done);
208
260k
        DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].dsc, ident->dsc, ret, done);
209
260k
        DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].ref, ident->ref, ret, done);
210
260k
        ident->module = ctx_sc->cur_mod;
211
        /* backlinks (derived) can be added no sooner than when all the identities in the current module are present */
212
260k
        COMPILE_EXTS_GOTO(ctx_sc, identities_p[u].exts, ident->exts, ident, ret, done);
213
260k
        ident->flags = identities_p[u].flags;
214
215
260k
        lysc_update_path(ctx_sc, NULL, NULL);
216
260k
    }
217
46.5k
    lysc_update_path(ctx_sc, NULL, NULL);
218
219
    /* revalidate the backward parent pointers from extensions now that the array is final */
220
260k
    LY_ARRAY_FOR(*identities, u) {
221
260k
        LY_ARRAY_FOR((*identities)[u].exts, v) {
222
0
            (*identities)[u].exts[v].parent = &(*identities)[u];
223
0
        }
224
260k
    }
225
226
46.5k
done:
227
46.5k
    if (ret) {
228
0
        lysc_update_path(ctx_sc, NULL, NULL);
229
0
        lysc_update_path(ctx_sc, NULL, NULL);
230
0
    }
231
46.5k
    return ret;
232
46.5k
}
233
234
/**
235
 * @brief Check circular dependency of identities - identity MUST NOT reference itself (via their base statement).
236
 *
237
 * The function works in the same way as lys_compile_feature_circular_check() with different structures and error messages.
238
 *
239
 * @param[in] ctx Compile context for logging.
240
 * @param[in] ident The base identity (its derived list is being extended by the identity being currently processed).
241
 * @param[in] derived The list of derived identities of the identity being currently processed (not the one provided as @p ident)
242
 * @return LY_SUCCESS if everything is ok.
243
 * @return LY_EVALID if the identity is derived from itself.
244
 */
245
static LY_ERR
246
lys_compile_identity_circular_check(struct lysc_ctx *ctx, struct lysc_ident *ident, struct lysc_ident **derived)
247
214k
{
248
214k
    LY_ERR ret = LY_SUCCESS;
249
214k
    LY_ARRAY_COUNT_TYPE u, v;
250
214k
    struct ly_set recursion = {0};
251
214k
    struct lysc_ident *drv;
252
253
214k
    if (!derived) {
254
214k
        return LY_SUCCESS;
255
214k
    }
256
257
0
    for (u = 0; u < LY_ARRAY_COUNT(derived); ++u) {
258
0
        if (ident == derived[u]) {
259
0
            LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE,
260
0
                    "Identity \"%s\" is indirectly derived from itself.", ident->name);
261
0
            ret = LY_EVALID;
262
0
            goto cleanup;
263
0
        }
264
0
        ret = ly_set_add(&recursion, derived[u], 0, NULL);
265
0
        LY_CHECK_GOTO(ret, cleanup);
266
0
    }
267
268
0
    for (v = 0; v < recursion.count; ++v) {
269
0
        drv = recursion.objs[v];
270
0
        for (u = 0; u < LY_ARRAY_COUNT(drv->derived); ++u) {
271
0
            if (ident == drv->derived[u]) {
272
0
                LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE,
273
0
                        "Identity \"%s\" is indirectly derived from itself.", ident->name);
274
0
                ret = LY_EVALID;
275
0
                goto cleanup;
276
0
            }
277
0
            ret = ly_set_add(&recursion, drv->derived[u], 0, NULL);
278
0
            LY_CHECK_GOTO(ret, cleanup);
279
0
        }
280
0
    }
281
282
0
cleanup:
283
0
    ly_set_erase(&recursion, NULL);
284
0
    return ret;
285
0
}
286
287
LY_ERR
288
lys_compile_identity_bases(struct lysc_ctx *ctx, const struct lysp_module *base_pmod, const char **bases_p,
289
        struct lysc_ident *ident, struct lysc_ident ***bases)
290
270k
{
291
270k
    LY_ARRAY_COUNT_TYPE u, v;
292
270k
    const char *s, *name;
293
270k
    const struct lys_module *mod;
294
270k
    struct lysc_ident **idref;
295
296
270k
    assert(ident || bases);
297
298
270k
    if ((LY_ARRAY_COUNT(bases_p) > 1) && (ctx->pmod->version < LYS_VERSION_1_1)) {
299
0
        LOGVAL(ctx->ctx, NULL, LYVE_SYNTAX_YANG,
300
0
                "Multiple bases in %s are allowed only in YANG 1.1 modules.", ident ? "identity" : "identityref type");
301
0
        return LY_EVALID;
302
0
    }
303
304
270k
    LY_ARRAY_FOR(bases_p, u) {
305
270k
        s = strchr(bases_p[u], ':');
306
270k
        if (s) {
307
            /* prefixed identity */
308
40.4k
            name = &s[1];
309
40.4k
            mod = ly_resolve_prefix(ctx->ctx, bases_p[u], s - bases_p[u], LY_VALUE_SCHEMA, (void *)base_pmod);
310
230k
        } else {
311
230k
            name = bases_p[u];
312
230k
            mod = base_pmod->mod;
313
230k
        }
314
270k
        if (!mod) {
315
0
            if (ident) {
316
0
                LOGVAL(ctx->ctx, NULL, LYVE_SYNTAX_YANG,
317
0
                        "Invalid prefix used for base (%s) of identity \"%s\".", bases_p[u], ident->name);
318
0
            } else {
319
0
                LOGVAL(ctx->ctx, NULL, LYVE_SYNTAX_YANG,
320
0
                        "Invalid prefix used for base (%s) of identityref.", bases_p[u]);
321
0
            }
322
0
            return LY_EVALID;
323
0
        }
324
325
270k
        idref = NULL;
326
456k
        LY_ARRAY_FOR(mod->identities, v) {
327
456k
            if (!strcmp(name, mod->identities[v].name)) {
328
270k
                if (ident) {
329
214k
                    if (ident == &mod->identities[v]) {
330
0
                        LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Identity \"%s\" is derived from itself.", ident->name);
331
0
                        return LY_EVALID;
332
0
                    }
333
214k
                    LY_CHECK_RET(lys_compile_identity_circular_check(ctx, &mod->identities[v], ident->derived));
334
                    /* we have match! store the backlink */
335
214k
                    LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, idref, LY_EMEM);
336
214k
                    *idref = ident;
337
214k
                } else {
338
                    /* we have match! store the found identity */
339
56.5k
                    LY_ARRAY_NEW_RET(ctx->ctx, *bases, idref, LY_EMEM);
340
56.5k
                    *idref = &mod->identities[v];
341
56.5k
                }
342
270k
                break;
343
270k
            }
344
456k
        }
345
270k
        if (!idref) {
346
0
            if (ident) {
347
0
                LOGVAL(ctx->ctx, NULL, LYVE_SYNTAX_YANG,
348
0
                        "Unable to find base (%s) of identity \"%s\".", bases_p[u], ident->name);
349
0
            } else {
350
0
                LOGVAL(ctx->ctx, NULL, LYVE_SYNTAX_YANG,
351
0
                        "Unable to find base (%s) of identityref.", bases_p[u]);
352
0
            }
353
0
            return LY_EVALID;
354
0
        }
355
270k
    }
356
357
270k
    return LY_SUCCESS;
358
270k
}
359
360
/**
361
 * @brief For the given array of identities, set the backlinks from all their base identities.
362
 *
363
 * @param[in] ctx Compile context, not only for logging but also to get the current module to resolve prefixes.
364
 * @param[in] idents_p Array of identities definitions from the parsed schema structure.
365
 * @param[in,out] idents Array of referencing identities to which the backlinks are supposed to be set.
366
 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
367
 */
368
static LY_ERR
369
lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident **idents)
370
46.5k
{
371
46.5k
    LY_ARRAY_COUNT_TYPE u, v;
372
373
46.5k
    lysc_update_path(ctx, NULL, "{identity}");
374
375
307k
    for (u = 0; u < LY_ARRAY_COUNT(*idents); ++u) {
376
        /* find matching parsed identity */
377
1.05M
        for (v = 0; v < LY_ARRAY_COUNT(idents_p); ++v) {
378
1.05M
            if (idents_p[v].name == (*idents)[u].name) {
379
260k
                break;
380
260k
            }
381
1.05M
        }
382
383
260k
        if ((v == LY_ARRAY_COUNT(idents_p)) || !idents_p[v].bases) {
384
            /* identity not found (it may be from a submodule) or identity without bases */
385
46.6k
            continue;
386
46.6k
        }
387
388
214k
        lysc_update_path(ctx, NULL, (*idents)[u].name);
389
214k
        LY_CHECK_RET(lys_compile_identity_bases(ctx, ctx->pmod, idents_p[v].bases, &(*idents)[u], NULL));
390
214k
        lysc_update_path(ctx, NULL, NULL);
391
214k
    }
392
393
46.5k
    lysc_update_path(ctx, NULL, NULL);
394
46.5k
    return LY_SUCCESS;
395
46.5k
}
396
397
LY_ERR
398
lys_compile_expr_implement(const struct ly_ctx *ctx, const struct lyxp_expr *expr, LY_VALUE_FORMAT format,
399
        void *prefix_data, ly_bool implement, struct lys_glob_unres *unres, const struct lys_module **mod_p)
400
194k
{
401
194k
    uint32_t i;
402
194k
    const char *ptr, *start, **imp_f, *all_f[] = {"*", NULL};
403
194k
    const struct lys_module *mod;
404
405
194k
    assert(implement || mod_p);
406
407
194k
    if (mod_p) {
408
33.3k
        *mod_p = NULL;
409
33.3k
    }
410
411
4.17M
    for (i = 0; i < expr->used; ++i) {
412
3.98M
        if ((expr->tokens[i] != LYXP_TOKEN_NAMETEST) && (expr->tokens[i] != LYXP_TOKEN_LITERAL)) {
413
            /* token cannot have a prefix */
414
2.79M
            continue;
415
2.79M
        }
416
417
1.18M
        start = expr->expr + expr->tok_pos[i];
418
1.18M
        if (!(ptr = ly_strnchr(start, ':', expr->tok_len[i]))) {
419
            /* token without a prefix */
420
1.05M
            continue;
421
1.05M
        }
422
423
131k
        if (!(mod = ly_resolve_prefix(ctx, start, ptr - start, format, prefix_data))) {
424
            /* unknown prefix, do not care right now */
425
23.8k
            continue;
426
23.8k
        }
427
428
        /* unimplemented module found */
429
107k
        if (!mod->implemented && !implement) {
430
            /* should not be implemented now */
431
0
            *mod_p = mod;
432
0
            break;
433
0
        }
434
435
107k
        if (!mod->implemented) {
436
            /* implement if not implemented */
437
0
            imp_f = (ctx->opts & LY_CTX_ENABLE_IMP_FEATURES) ? all_f : NULL;
438
0
            LY_CHECK_RET(lys_implement((struct lys_module *)mod, imp_f, unres));
439
0
        }
440
107k
        if (!mod->compiled) {
441
            /* compile if not implemented before or only marked for compilation */
442
0
            LY_CHECK_RET(lys_compile((struct lys_module *)mod, &unres->ds_unres));
443
0
        }
444
107k
    }
445
446
194k
    return LY_SUCCESS;
447
194k
}
448
449
/**
450
 * @brief Check when for cyclic dependencies.
451
 *
452
 * @param[in] set Set with all the referenced nodes.
453
 * @param[in] node Node whose "when" referenced nodes are in @p set.
454
 * @return LY_ERR value
455
 */
456
static LY_ERR
457
lys_compile_unres_when_cyclic(struct lyxp_set *set, const struct lysc_node *node)
458
3.63k
{
459
3.63k
    struct lyxp_set tmp_set;
460
3.63k
    struct lyxp_set_scnode *xp_scnode;
461
3.63k
    uint32_t i, j, idx;
462
3.63k
    LY_ARRAY_COUNT_TYPE u;
463
3.63k
    LY_ERR ret = LY_SUCCESS;
464
465
3.63k
    memset(&tmp_set, 0, sizeof tmp_set);
466
467
    /* prepare in_ctx of the set */
468
25.6k
    for (i = 0; i < set->used; ++i) {
469
21.9k
        xp_scnode = &set->val.scnodes[i];
470
471
21.9k
        if (xp_scnode->in_ctx != LYXP_SET_SCNODE_START_USED) {
472
            /* check node when, skip the context node (it was just checked) */
473
19.5k
            xp_scnode->in_ctx = LYXP_SET_SCNODE_ATOM_CTX;
474
19.5k
        }
475
21.9k
    }
476
477
25.7k
    for (i = 0; i < set->used; ++i) {
478
22.1k
        xp_scnode = &set->val.scnodes[i];
479
22.1k
        if (xp_scnode->in_ctx != LYXP_SET_SCNODE_ATOM_CTX) {
480
            /* already checked */
481
2.44k
            continue;
482
2.44k
        }
483
484
19.6k
        if ((xp_scnode->type != LYXP_NODE_ELEM) || !lysc_node_when(xp_scnode->scnode)) {
485
            /* no when to check */
486
19.4k
            xp_scnode->in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
487
19.4k
            continue;
488
19.4k
        }
489
490
188
        node = xp_scnode->scnode;
491
388
        do {
492
388
            struct lysc_when **when_list, *when;
493
494
388
            when_list = lysc_node_when(node);
495
388
            LY_ARRAY_FOR(when_list, u) {
496
246
                when = when_list[u];
497
246
                ret = lyxp_atomize(set->ctx, when->cond, node->module, LY_VALUE_SCHEMA_RESOLVED, when->prefixes,
498
246
                        when->context, when->context, &tmp_set, LYXP_SCNODE_SCHEMA);
499
246
                if (ret != LY_SUCCESS) {
500
6
                    LOG_LOCSET(node);
501
6
                    LOGVAL(set->ctx, NULL, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when->cond->expr);
502
6
                    LOG_LOCBACK(1);
503
6
                    goto cleanup;
504
6
                }
505
506
1.31k
                for (j = 0; j < tmp_set.used; ++j) {
507
1.08k
                    if (tmp_set.val.scnodes[j].type != LYXP_NODE_ELEM) {
508
                        /* skip roots'n'stuff, no when, nothing to check */
509
165
                        tmp_set.val.scnodes[j].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
510
165
                        continue;
511
165
                    }
512
513
                    /* try to find this node in our set */
514
915
                    if (lyxp_set_scnode_contains(set, tmp_set.val.scnodes[j].scnode, LYXP_NODE_ELEM, -1, &idx) &&
515
793
                            (set->val.scnodes[idx].in_ctx == LYXP_SET_SCNODE_START_USED)) {
516
6
                        LOG_LOCSET(node);
517
6
                        LOGVAL(set->ctx, NULL, LYVE_SEMANTICS, "When condition cyclic dependency on the node \"%s\".",
518
6
                                tmp_set.val.scnodes[j].scnode->name);
519
6
                        LOG_LOCBACK(1);
520
6
                        ret = LY_EVALID;
521
6
                        goto cleanup;
522
6
                    }
523
524
                    /* needs to be checked, if in both sets, will be ignored */
525
909
                    tmp_set.val.scnodes[j].in_ctx = LYXP_SET_SCNODE_ATOM_CTX;
526
909
                }
527
528
234
                if (when->context != node) {
529
                    /* node actually depends on this "when", not the context node */
530
49
                    assert(tmp_set.val.scnodes[0].scnode == when->context);
531
49
                    if (tmp_set.val.scnodes[0].in_ctx == LYXP_SET_SCNODE_START_USED) {
532
                        /* replace the non-traversed context node with the dependent node */
533
0
                        tmp_set.val.scnodes[0].scnode = (struct lysc_node *)node;
534
49
                    } else {
535
                        /* context node was traversed, so just add the dependent node */
536
49
                        ret = lyxp_set_scnode_insert_node(&tmp_set, node, LYXP_SET_SCNODE_START_USED, LYXP_AXIS_CHILD, NULL);
537
49
                        LY_CHECK_GOTO(ret, cleanup);
538
49
                    }
539
49
                }
540
541
                /* merge this set into the global when set */
542
234
                lyxp_set_scnode_merge(set, &tmp_set);
543
234
            }
544
545
            /* check when of non-data parents as well */
546
376
            node = node->parent;
547
376
        } while (node && (node->nodetype & (LYS_CASE | LYS_CHOICE)));
548
549
        /* this node when was checked (xp_scnode could have been reallocd) */
550
176
        set->val.scnodes[i].in_ctx = LYXP_SET_SCNODE_ATOM_NODE;
551
176
    }
552
553
3.63k
cleanup:
554
3.63k
    lyxp_set_free_content(&tmp_set);
555
3.63k
    return ret;
556
3.63k
}
557
558
LY_ERR
559
lysc_check_status(struct lysc_ctx *ctx, const struct lysc_node *snode, uint16_t flags1, void *mod1, const char *name1,
560
        uint16_t flags2, void *mod2, const char *name2)
561
2.17M
{
562
2.17M
    uint16_t flg1, flg2;
563
564
2.17M
    flg1 = (flags1 & LYS_STATUS_MASK) ? (flags1 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
565
2.17M
    flg2 = (flags2 & LYS_STATUS_MASK) ? (flags2 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
566
567
2.17M
    if ((flg1 < flg2) && (mod1 == mod2)) {
568
24
        if (ctx) {
569
0
            if (snode) {
570
0
                LOG_LOCSET(snode);
571
0
            }
572
0
            LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "A %s definition \"%s\" is not allowed to reference %s definition \"%s\".",
573
0
                    flg1 == LYS_STATUS_CURR ? "current" : "deprecated", name1,
574
0
                    flg2 == LYS_STATUS_OBSLT ? "obsolete" : "deprecated", name2);
575
0
            if (snode) {
576
0
                LOG_LOCBACK(1);
577
0
            }
578
0
        }
579
24
        return LY_EVALID;
580
24
    }
581
582
2.17M
    return LY_SUCCESS;
583
2.17M
}
584
585
/**
586
 * @brief Check when expressions of a node on a complete compiled schema tree.
587
 *
588
 * @param[in] ctx Compile context.
589
 * @param[in] when When to check.
590
 * @param[in] node Node with @p when.
591
 * @return LY_ERR value.
592
 */
593
static LY_ERR
594
lys_compile_unres_when(struct lysc_ctx *ctx, const struct lysc_when *when, const struct lysc_node *node)
595
3.81k
{
596
3.81k
    struct lyxp_set tmp_set = {0};
597
3.81k
    uint32_t i, opts;
598
3.81k
    struct lysc_node *schema;
599
3.81k
    LY_ERR ret = LY_SUCCESS;
600
601
3.81k
    opts = LYXP_SCNODE_SCHEMA | ((node->flags & LYS_IS_OUTPUT) ? LYXP_SCNODE_OUTPUT : 0);
602
603
    /* check "when" */
604
3.81k
    ret = lyxp_atomize(ctx->ctx, when->cond, node->module, LY_VALUE_SCHEMA_RESOLVED, when->prefixes, when->context,
605
3.81k
            when->context, &tmp_set, opts);
606
3.81k
    if (ret) {
607
149
        LOG_LOCSET(node);
608
149
        LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when->cond->expr);
609
149
        LOG_LOCBACK(1);
610
149
        goto cleanup;
611
149
    }
612
613
3.66k
    ctx->path[0] = '\0';
614
3.66k
    lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
615
24.5k
    for (i = 0; i < tmp_set.used; ++i) {
616
20.9k
        if (tmp_set.val.scnodes[i].type != LYXP_NODE_ELEM) {
617
            /* skip roots'n'stuff */
618
2.63k
            continue;
619
18.3k
        } else if (tmp_set.val.scnodes[i].in_ctx == LYXP_SET_SCNODE_START_USED) {
620
            /* context node not actually traversed */
621
1.01k
            continue;
622
1.01k
        }
623
624
17.2k
        schema = tmp_set.val.scnodes[i].scnode;
625
626
        /* XPath expression cannot reference "lower" status than the node that has the definition */
627
17.2k
        if (lysc_check_status(NULL, NULL, when->flags, node->module, node->name, schema->flags, schema->module,
628
17.2k
                schema->name)) {
629
24
            LOGWRN(ctx->ctx, "When condition \"%s\" may be referencing %s node \"%s\".", when->cond->expr,
630
24
                    (schema->flags == LYS_STATUS_OBSLT) ? "obsolete" : "deprecated", schema->name);
631
24
        }
632
633
        /* check dummy node children/value accessing */
634
17.2k
        if (lysc_data_parent(schema) == node) {
635
3
            LOG_LOCSET(node);
636
3
            LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "When condition is accessing its own conditional node children.");
637
3
            LOG_LOCBACK(1);
638
3
            ret = LY_EVALID;
639
3
            goto cleanup;
640
17.2k
        } else if ((schema == node) && (tmp_set.val.scnodes[i].in_ctx == LYXP_SET_SCNODE_ATOM_VAL)) {
641
28
            LOG_LOCSET(node);
642
28
            LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "When condition is accessing its own conditional node value.");
643
28
            LOG_LOCBACK(1);
644
28
            ret = LY_EVALID;
645
28
            goto cleanup;
646
28
        }
647
17.2k
    }
648
649
3.63k
    if (when->context != node) {
650
        /* node actually depends on this "when", not the context node */
651
2.56k
        assert(tmp_set.val.scnodes[0].scnode == when->context);
652
2.56k
        if (tmp_set.val.scnodes[0].in_ctx == LYXP_SET_SCNODE_START_USED) {
653
            /* replace the non-traversed context node with the dependent node */
654
1.47k
            tmp_set.val.scnodes[0].scnode = (struct lysc_node *)node;
655
1.47k
        } else {
656
            /* context node was traversed, so just add the dependent node */
657
1.08k
            ret = lyxp_set_scnode_insert_node(&tmp_set, node, LYXP_SET_SCNODE_START_USED, LYXP_AXIS_CHILD, NULL);
658
1.08k
            LY_CHECK_GOTO(ret, cleanup);
659
1.08k
        }
660
2.56k
    }
661
662
    /* check cyclic dependencies */
663
3.63k
    ret = lys_compile_unres_when_cyclic(&tmp_set, node);
664
3.63k
    LY_CHECK_GOTO(ret, cleanup);
665
666
3.81k
cleanup:
667
3.81k
    lyxp_set_free_content(&tmp_set);
668
3.81k
    return ret;
669
3.62k
}
670
671
/**
672
 * @brief Check must expressions of a node on a complete compiled schema tree.
673
 *
674
 * @param[in] ctx Compile context.
675
 * @param[in] node Node to check.
676
 * @param[in] local_mods Sized array of local modules for musts of @p node at the same index.
677
 * @return LY_ERR value.
678
 */
679
static LY_ERR
680
lys_compile_unres_must(struct lysc_ctx *ctx, const struct lysc_node *node, const struct lysp_module **local_mods)
681
654
{
682
654
    struct lyxp_set tmp_set;
683
654
    uint32_t i, opts;
684
654
    LY_ARRAY_COUNT_TYPE u;
685
654
    struct lysc_must *musts;
686
654
    LY_ERR ret = LY_SUCCESS;
687
654
    uint16_t flg;
688
689
654
    memset(&tmp_set, 0, sizeof tmp_set);
690
654
    opts = LYXP_SCNODE_SCHEMA | ((node->flags & LYS_IS_OUTPUT) ? LYXP_SCNODE_OUTPUT : 0);
691
692
654
    musts = lysc_node_musts(node);
693
28.6k
    LY_ARRAY_FOR(musts, u) {
694
        /* check "must" */
695
28.6k
        ret = lyxp_atomize(ctx->ctx, musts[u].cond, node->module, LY_VALUE_SCHEMA_RESOLVED, musts[u].prefixes, node,
696
28.6k
                node, &tmp_set, opts);
697
28.6k
        if (ret) {
698
82
            LOG_LOCSET(node);
699
82
            LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "Invalid must condition \"%s\".", musts[u].cond->expr);
700
82
            LOG_LOCBACK(1);
701
82
            goto cleanup;
702
82
        }
703
704
28.5k
        ctx->path[0] = '\0';
705
28.5k
        lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
706
64.4k
        for (i = 0; i < tmp_set.used; ++i) {
707
            /* skip roots'n'stuff */
708
35.8k
            if (tmp_set.val.scnodes[i].type == LYXP_NODE_ELEM) {
709
32.2k
                struct lysc_node *schema = tmp_set.val.scnodes[i].scnode;
710
711
                /* XPath expression cannot reference "lower" status than the node that has the definition */
712
32.2k
                if (local_mods[u]->mod == node->module) {
713
                    /* use flags of the context node since the definition is local */
714
32.2k
                    flg = node->flags;
715
32.2k
                } else {
716
                    /* definition is foreign (deviation, refine), always current */
717
0
                    flg = LYS_STATUS_CURR;
718
0
                }
719
32.2k
                if (lysc_check_status(NULL, NULL, flg, local_mods[u]->mod, node->name, schema->flags, schema->module,
720
32.2k
                        schema->name)) {
721
0
                    LOGWRN(ctx->ctx, "Must condition \"%s\" may be referencing %s node \"%s\".", musts[u].cond->expr,
722
0
                            (schema->flags == LYS_STATUS_OBSLT) ? "obsolete" : "deprecated", schema->name);
723
0
                    break;
724
0
                }
725
32.2k
            }
726
35.8k
        }
727
728
28.5k
        lyxp_set_free_content(&tmp_set);
729
28.5k
    }
730
731
654
cleanup:
732
654
    lyxp_set_free_content(&tmp_set);
733
654
    return ret;
734
654
}
735
736
/**
737
 * @brief Remove all disabled bits/enums from a sized array.
738
 *
739
 * @param[in] ctx Context with the dictionary.
740
 * @param[in] items Sized array of bits/enums.
741
 */
742
static void
743
lys_compile_unres_disabled_bitenum_remove(const struct ly_ctx *ctx, struct lysc_type_bitenum_item *items)
744
48.9k
{
745
48.9k
    LY_ARRAY_COUNT_TYPE u = 0, last_u;
746
747
173k
    while (u < LY_ARRAY_COUNT(items)) {
748
124k
        if (items[u].flags & LYS_DISABLED) {
749
            /* free the disabled item */
750
20.2k
            lysc_enum_item_free(ctx, &items[u]);
751
752
            /* replace it with the following items */
753
20.2k
            last_u = LY_ARRAY_COUNT(items) - 1;
754
20.2k
            if (u < last_u) {
755
10.1k
                memmove(items + u, items + u + 1, (last_u - u) * sizeof *items);
756
10.1k
            }
757
758
            /* one item less */
759
20.2k
            LY_ARRAY_DECREMENT(items);
760
20.2k
            continue;
761
20.2k
        }
762
763
104k
        ++u;
764
104k
    }
765
48.9k
}
766
767
/**
768
 * @brief Find and remove all disabled bits/enums in a leaf/leaf-list type.
769
 *
770
 * @param[in] ctx Compile context.
771
 * @param[in] leaf Leaf/leaf-list to check.
772
 * @return LY_ERR value
773
 */
774
static LY_ERR
775
lys_compile_unres_disabled_bitenum(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf)
776
48.9k
{
777
48.9k
    struct lysc_type **t;
778
48.9k
    LY_ARRAY_COUNT_TYPE u, count;
779
48.9k
    struct lysc_type_enum *ent;
780
48.9k
    ly_bool has_value = 0;
781
782
48.9k
    if (leaf->type->basetype == LY_TYPE_UNION) {
783
0
        t = ((struct lysc_type_union *)leaf->type)->types;
784
0
        count = LY_ARRAY_COUNT(t);
785
48.9k
    } else {
786
48.9k
        t = &leaf->type;
787
48.9k
        count = 1;
788
48.9k
    }
789
97.9k
    for (u = 0; u < count; ++u) {
790
48.9k
        if ((t[u]->basetype == LY_TYPE_BITS) || (t[u]->basetype == LY_TYPE_ENUM)) {
791
            /* remove all disabled items */
792
48.9k
            ent = (struct lysc_type_enum *)(t[u]);
793
48.9k
            lys_compile_unres_disabled_bitenum_remove(ctx->ctx, ent->enums);
794
795
48.9k
            if (LY_ARRAY_COUNT(ent->enums)) {
796
48.9k
                has_value = 1;
797
48.9k
            }
798
48.9k
        } else {
799
0
            has_value = 1;
800
0
        }
801
48.9k
    }
802
803
48.9k
    if (!has_value) {
804
0
        LOG_LOCSET((struct lysc_node *)leaf);
805
0
        LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "Node \"%s\" without any (or all disabled) valid values.", leaf->name);
806
0
        LOG_LOCBACK(1);
807
0
        return LY_EVALID;
808
0
    }
809
810
48.9k
    return LY_SUCCESS;
811
48.9k
}
812
813
/**
814
 * @brief Check a leafref for circular references.
815
 *
816
 * @param[in] type Referenced type, is checked recursively for other leafrefs.
817
 * @param[in] lref Initial leafref type that cannot be referenced.
818
 * @return LY_SUCCESS on success;
819
 * @return LY_EVALID on a circular chein of leafrefs.
820
 */
821
static LY_ERR
822
lys_compile_leafref_circ_check(const struct lysc_type *type, const struct lysc_type *lref)
823
161k
{
824
161k
    const struct lysc_type_union *un;
825
161k
    LY_ARRAY_COUNT_TYPE u;
826
827
161k
    if (!type) {
828
        /* not resolved yet */
829
0
        return LY_SUCCESS;
830
0
    }
831
832
161k
    if (type == lref) {
833
        /* circular chain detected */
834
0
        return LY_EVALID;
835
0
    }
836
837
161k
    switch (type->basetype) {
838
0
    case LY_TYPE_LEAFREF:
839
        /* check the referenced type */
840
0
        LY_CHECK_RET(lys_compile_leafref_circ_check(((struct lysc_type_leafref *)type)->realtype, lref));
841
0
        break;
842
0
    case LY_TYPE_UNION:
843
        /* check all the union types */
844
0
        un = (struct lysc_type_union *)type;
845
0
        LY_ARRAY_FOR(un->types, u) {
846
0
            LY_CHECK_RET(lys_compile_leafref_circ_check(un->types[u], lref));
847
0
        }
848
161k
    default:
849
        /* no more leafref references */
850
161k
        break;
851
161k
    }
852
853
161k
    return LY_SUCCESS;
854
161k
}
855
856
/**
857
 * @brief Check leafref for its target existence on a complete compiled schema tree.
858
 *
859
 * @param[in] ctx Compile context.
860
 * @param[in] node Context node for the leafref.
861
 * @param[in] lref Leafref to check/resolve.
862
 * @param[in] local_mod Local module for the leafref type.
863
 * @return LY_ERR value.
864
 */
865
static LY_ERR
866
lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, struct lysc_type_leafref *lref,
867
        const struct lysp_module *local_mod)
868
161k
{
869
161k
    const struct lysc_node *target = NULL;
870
161k
    struct ly_path *p;
871
161k
    uint16_t flg;
872
873
161k
    assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
874
875
161k
    if (lref->realtype) {
876
        /* already resolved, may happen (shared union typedef with a leafref) */
877
0
        return LY_SUCCESS;
878
0
    }
879
880
    /* try to find the target, current module is that of the context node (RFC 7950 6.4.1 second bullet) */
881
161k
    LY_CHECK_RET(ly_path_compile_leafref(ctx->ctx, node, lref->path,
882
161k
            (node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
883
161k
            LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &p));
884
885
    /* get the target node */
886
161k
    target = p[LY_ARRAY_COUNT(p) - 1].node;
887
161k
    ly_path_free(p);
888
889
161k
    if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
890
0
        LOG_LOCSET(node);
891
0
        LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
892
0
                lref->path->expr, lys_nodetype2str(target->nodetype));
893
0
        LOG_LOCBACK(1);
894
0
        return LY_EVALID;
895
0
    }
896
897
    /* check status */
898
161k
    ctx->path[0] = '\0';
899
161k
    lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
900
161k
    ctx->path_len = strlen(ctx->path);
901
161k
    if (node->module == local_mod->mod) {
902
        /* use flags of the context node since the definition is local */
903
161k
        flg = node->flags;
904
161k
    } else {
905
        /* definition is foreign (deviation), always current */
906
0
        flg = LYS_STATUS_CURR;
907
0
    }
908
161k
    if (lysc_check_status(ctx, node, flg, local_mod->mod, node->name, target->flags, target->module, target->name)) {
909
0
        return LY_EVALID;
910
0
    }
911
161k
    ctx->path_len = 1;
912
161k
    ctx->path[1] = '\0';
913
914
    /* check config */
915
161k
    if (lref->require_instance) {
916
161k
        if ((node->flags & LYS_CONFIG_W) && (target->flags & LYS_CONFIG_R)) {
917
0
            LOG_LOCSET(node);
918
0
            LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target is supposed"
919
0
                    " to represent configuration data (as the leafref does), but it does not.", lref->path->expr);
920
0
            LOG_LOCBACK(1);
921
0
            return LY_EVALID;
922
0
        }
923
161k
    }
924
925
    /* check for circular chain of leafrefs */
926
161k
    if (lys_compile_leafref_circ_check(((struct lysc_node_leaf *)target)->type, (struct lysc_type *)lref)) {
927
0
        LOG_LOCSET(node);
928
0
        LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Invalid leafref path \"%s\" - circular chain of leafrefs detected.",
929
0
                lref->path->expr);
930
0
        LOG_LOCBACK(1);
931
0
        return LY_EVALID;
932
0
    }
933
934
    /* store the type */
935
161k
    lref->realtype = ((struct lysc_node_leaf *)target)->type;
936
161k
    ++lref->realtype->refcount;
937
161k
    return LY_SUCCESS;
938
161k
}
939
940
/**
941
 * @brief Compile default value(s) for leaf or leaf-list expecting a complete compiled schema tree.
942
 *
943
 * @param[in] ctx Compile context.
944
 * @param[in] node Leaf or leaf-list to compile the default value(s) for.
945
 * @param[in] type Type of the default value.
946
 * @param[in] dflt Default value.
947
 * @param[in] dflt_pmod Parsed module of the @p dflt to resolve possible prefixes.
948
 * @param[out] value Default value.
949
 * @param[in,out] unres Global unres structure for newly implemented modules.
950
 * @return LY_ERECOMPILE if the whole dep set needs to be recompiled for the value to be checked.
951
 * @return LY_ERR value.
952
 */
953
static LY_ERR
954
lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_type *type, const char *dflt,
955
        const struct lysp_module *dflt_pmod, struct lysc_value *value, struct lys_glob_unres *unres)
956
26.7k
{
957
26.7k
    LY_ERR rc = LY_SUCCESS;
958
26.7k
    uint32_t options;
959
26.7k
    struct lyd_value storage = {0}, *val;
960
26.7k
    struct ly_err_item *err = NULL;
961
26.7k
    LY_VALUE_FORMAT format;
962
26.7k
    struct lyplg_type *type_plg;
963
964
26.7k
    options = (ctx->ctx->opts & LY_CTX_REF_IMPLEMENTED) ? LYPLG_TYPE_STORE_IMPLEMENT : 0;
965
26.7k
    type_plg = LYSC_GET_TYPE_PLG(type->plugin_ref);
966
26.7k
    rc = type_plg->store(ctx->ctx, type, dflt, strlen(dflt) * 8, options, LY_VALUE_SCHEMA, (void *)dflt_pmod,
967
26.7k
            LYD_HINT_SCHEMA, node, &storage, unres, &err);
968
26.7k
    if (rc == LY_ERECOMPILE) {
969
        /* fine, but we need to recompile */
970
0
        return rc;
971
26.7k
    } else if (rc == LY_EINCOMPLETE) {
972
        /* we have no data so we will not be resolving it */
973
0
        rc = LY_SUCCESS;
974
0
    }
975
976
26.7k
    if (!rc) {
977
        /* store the original value with the resolved prefixes */
978
26.3k
        LY_CHECK_GOTO(rc = lysdict_insert(ctx->ctx, dflt, 0, &value->str), cleanup);
979
26.3k
        LY_CHECK_GOTO(rc = lyplg_type_prefix_data_new(ctx->ctx, dflt, strlen(dflt), LY_VALUE_SCHEMA, dflt_pmod, &format,
980
26.3k
                (void **)&value->prefixes), cleanup);
981
26.3k
    } else {
982
407
        LOG_LOCSET(node);
983
407
        if (err) {
984
407
            LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "Invalid default - value does not fit the type (%s).", err->msg);
985
407
            ly_err_free(err);
986
407
        } else {
987
0
            LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS, "Invalid default - value does not fit the type.");
988
0
        }
989
407
        LOG_LOCBACK(1);
990
407
    }
991
992
26.7k
cleanup:
993
26.7k
    if (storage.realtype->basetype == LY_TYPE_UNION) {
994
0
        val = &storage.subvalue->value;
995
26.7k
    } else {
996
26.7k
        val = &storage;
997
26.7k
    }
998
26.7k
    if (val->realtype->basetype == LY_TYPE_INST) {
999
        /* ly_path includes references to other nodes, in case they are in foreign modules, the context would
1000
         * need to be freed in specific order to avoid accessing freed memory, so just avoid storing it */
1001
0
        ly_path_free(val->target);
1002
0
        val->target = NULL;
1003
0
    }
1004
26.7k
    type_plg->free(ctx->ctx, &storage);
1005
26.7k
    return rc;
1006
26.7k
}
1007
1008
/**
1009
 * @brief Compile default value of a leaf expecting a complete compiled schema tree.
1010
 *
1011
 * @param[in] ctx Compile context.
1012
 * @param[in] leaf Leaf that the default value is for.
1013
 * @param[in] dflt Default value to compile.
1014
 * @param[in,out] unres Global unres structure for newly implemented modules.
1015
 * @return LY_ERR value.
1016
 */
1017
static LY_ERR
1018
lys_compile_unres_leaf_dlft(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt,
1019
        struct lys_glob_unres *unres)
1020
26.7k
{
1021
26.7k
    assert(!leaf->dflt.str);
1022
1023
26.7k
    if (leaf->flags & (LYS_MAND_TRUE | LYS_KEY)) {
1024
        /* ignore default values for keys and mandatory leaves */
1025
0
        return LY_SUCCESS;
1026
0
    }
1027
1028
    /* store the default value */
1029
26.7k
    return lys_compile_unres_dflt(ctx, &leaf->node, leaf->type, dflt->str, dflt->mod, &leaf->dflt, unres);
1030
26.7k
}
1031
1032
/**
1033
 * @brief Compile default values of a leaf-list expecting a complete compiled schema tree.
1034
 *
1035
 * @param[in] ctx Compile context.
1036
 * @param[in] llist Leaf-list that the default value(s) are for.
1037
 * @param[in] dflt Default value to compile, in case of a single value.
1038
 * @param[in] dflts Sized array of default values, in case of more values.
1039
 * @param[in,out] unres Global unres structure for newly implemented modules.
1040
 * @return LY_ERR value.
1041
 */
1042
static LY_ERR
1043
lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflt,
1044
        struct lysp_qname *dflts, struct lys_glob_unres *unres)
1045
0
{
1046
0
    LY_ARRAY_COUNT_TYPE orig_count, u, v;
1047
1048
0
    assert(dflt || dflts);
1049
1050
    /* in case there were already some defaults and we are adding new by deviations */
1051
0
    orig_count = LY_ARRAY_COUNT(llist->dflts);
1052
1053
    /* allocate new items */
1054
0
    LY_ARRAY_CREATE_RET(ctx->ctx, llist->dflts, orig_count + (dflts ? LY_ARRAY_COUNT(dflts) : 1), LY_EMEM);
1055
1056
    /* fill each new default value */
1057
0
    if (dflts) {
1058
0
        LY_ARRAY_FOR(dflts, u) {
1059
0
            LY_CHECK_RET(lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflts[u].str, dflts[u].mod,
1060
0
                    &llist->dflts[orig_count + u], unres));
1061
0
            LY_ARRAY_INCREMENT(llist->dflts);
1062
0
        }
1063
0
    } else {
1064
0
        LY_CHECK_RET(lys_compile_unres_dflt(ctx, &llist->node, llist->type, dflt->str, dflt->mod,
1065
0
                &llist->dflts[orig_count], unres));
1066
0
        LY_ARRAY_INCREMENT(llist->dflts);
1067
0
    }
1068
1069
    /* check default value uniqueness */
1070
0
    if (llist->flags & LYS_CONFIG_W) {
1071
        /* configuration data values must be unique - so check the default values */
1072
0
        for (u = orig_count; u < LY_ARRAY_COUNT(llist->dflts); ++u) {
1073
0
            for (v = 0; v < u; ++v) {
1074
0
                if (llist->dflts[u].str == llist->dflts[v].str) {
1075
0
                    LOG_LOCSET((struct lysc_node *)llist);
1076
0
                    LOGVAL(ctx->ctx, NULL, LYVE_SEMANTICS,
1077
0
                            "Configuration leaf-list has multiple defaults of the same value \"%s\".", llist->dflts[u].str);
1078
0
                    LOG_LOCBACK(1);
1079
0
                    return LY_EVALID;
1080
0
                }
1081
0
            }
1082
0
        }
1083
0
    }
1084
1085
0
    return LY_SUCCESS;
1086
0
}
1087
1088
/**
1089
 * @brief Iteratively get all leafrefs from @p node
1090
 * if the node is of type union, otherwise just return the leafref.
1091
 *
1092
 * @param[in] node Node that may contain the leafref.
1093
 * @param[in,out] index Value that is passed between function calls.
1094
 * For each new node, initialize value of the @p index to 0, otherwise
1095
 * do not modify the value between calls.
1096
 * @return Pointer to the leafref or next leafref, otherwise NULL.
1097
 */
1098
static struct lysc_type_leafref *
1099
lys_type_leafref_next(const struct lysc_node *node, LY_ARRAY_COUNT_TYPE *index)
1100
1.29M
{
1101
1.29M
    struct lysc_type_leafref *ret = NULL;
1102
1.29M
    struct lysc_type_union *uni;
1103
1.29M
    struct lysc_type *leaf_type;
1104
1105
1.29M
    assert(node->nodetype & LYD_NODE_TERM);
1106
1107
1.29M
    leaf_type = ((struct lysc_node_leaf *)node)->type;
1108
1.29M
    if (leaf_type->basetype == LY_TYPE_UNION) {
1109
80.9k
        uni = (struct lysc_type_union *)leaf_type;
1110
1111
        /* find next union leafref */
1112
202k
        while (*index < LY_ARRAY_COUNT(uni->types)) {
1113
161k
            if (uni->types[*index]->basetype == LY_TYPE_LEAFREF) {
1114
40.4k
                ret = (struct lysc_type_leafref *)uni->types[*index];
1115
40.4k
                ++(*index);
1116
40.4k
                break;
1117
40.4k
            }
1118
1119
121k
            ++(*index);
1120
121k
        }
1121
1.21M
    } else {
1122
        /* return just the single leafref */
1123
1.21M
        if (*index == 0) {
1124
605k
            ++(*index);
1125
605k
            assert(leaf_type->basetype == LY_TYPE_LEAFREF);
1126
605k
            ret = (struct lysc_type_leafref *)leaf_type;
1127
605k
        }
1128
1.21M
    }
1129
1130
1.29M
    return ret;
1131
1.29M
}
1132
1133
/**
1134
 * @brief Implement all referenced modules by leafrefs, when and must conditions.
1135
 *
1136
 * @param[in] ctx libyang context.
1137
 * @param[in] unres Global unres structure with the sets to resolve.
1138
 * @return LY_SUCCESS on success.
1139
 * @return LY_ERECOMPILE if the whole dep set needs to be recompiled with the new implemented modules.
1140
 * @return LY_ERR value on error.
1141
 */
1142
static LY_ERR
1143
lys_compile_unres_depset_implement(struct ly_ctx *ctx, struct lys_glob_unres *unres)
1144
414k
{
1145
414k
    struct lys_depset_unres *ds_unres = &unres->ds_unres;
1146
414k
    struct lysc_type_leafref *lref;
1147
414k
    const struct lys_module *mod;
1148
414k
    LY_ARRAY_COUNT_TYPE u;
1149
414k
    struct lysc_unres_leafref *l;
1150
414k
    struct lysc_unres_when *w;
1151
414k
    struct lysc_unres_must *m;
1152
414k
    struct lysc_must *musts;
1153
414k
    ly_bool not_implemented;
1154
414k
    uint32_t di = 0, li = 0, wi = 0, mi = 0;
1155
1156
414k
implement_all:
1157
    /* disabled leafrefs - even those because we need to check their target exists */
1158
414k
    while (di < ds_unres->disabled_leafrefs.count) {
1159
0
        l = ds_unres->disabled_leafrefs.objs[di];
1160
1161
0
        u = 0;
1162
0
        while ((lref = lys_type_leafref_next(l->node, &u))) {
1163
0
            LY_CHECK_RET(lys_compile_expr_implement(ctx, lref->path, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, 1, unres, NULL));
1164
0
        }
1165
1166
0
        ++di;
1167
0
    }
1168
1169
    /* leafrefs */
1170
576k
    while (li < ds_unres->leafrefs.count) {
1171
161k
        l = ds_unres->leafrefs.objs[li];
1172
1173
161k
        u = 0;
1174
323k
        while ((lref = lys_type_leafref_next(l->node, &u))) {
1175
161k
            LY_CHECK_RET(lys_compile_expr_implement(ctx, lref->path, LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, 1, unres, NULL));
1176
161k
        }
1177
1178
161k
        ++li;
1179
161k
    }
1180
1181
    /* when conditions */
1182
419k
    while (wi < ds_unres->whens.count) {
1183
4.44k
        w = ds_unres->whens.objs[wi];
1184
1185
4.44k
        LY_CHECK_RET(lys_compile_expr_implement(ctx, w->when->cond, LY_VALUE_SCHEMA_RESOLVED, w->when->prefixes,
1186
4.44k
                ctx->opts & LY_CTX_REF_IMPLEMENTED, unres, &mod));
1187
4.44k
        if (mod) {
1188
0
            LOGWRN(ctx, "When condition \"%s\" check skipped because referenced module \"%s\" is not implemented.",
1189
0
                    w->when->cond->expr, mod->name);
1190
1191
            /* remove from the set to skip the check */
1192
0
            ly_set_rm_index(&ds_unres->whens, wi, free);
1193
0
            continue;
1194
0
        }
1195
1196
4.44k
        ++wi;
1197
4.44k
    }
1198
1199
    /* must conditions */
1200
415k
    while (mi < ds_unres->musts.count) {
1201
771
        m = ds_unres->musts.objs[mi];
1202
1203
771
        not_implemented = 0;
1204
771
        musts = lysc_node_musts(m->node);
1205
28.9k
        LY_ARRAY_FOR(musts, u) {
1206
28.9k
            LY_CHECK_RET(lys_compile_expr_implement(ctx, musts[u].cond, LY_VALUE_SCHEMA_RESOLVED, musts[u].prefixes,
1207
28.9k
                    ctx->opts & LY_CTX_REF_IMPLEMENTED, unres, &mod));
1208
28.9k
            if (mod) {
1209
0
                LOGWRN(ctx, "Must condition \"%s\" check skipped because referenced module \"%s\" is not implemented.",
1210
0
                        musts[u].cond->expr, mod->name);
1211
1212
                /* need to implement modules from all the expressions */
1213
0
                not_implemented = 1;
1214
0
            }
1215
28.9k
        }
1216
1217
771
        if (not_implemented) {
1218
            /* remove from the set to skip the check */
1219
0
            lysc_unres_must_free(m);
1220
0
            ly_set_rm_index(&ds_unres->musts, mi, NULL);
1221
0
            continue;
1222
0
        }
1223
1224
771
        ++mi;
1225
771
    }
1226
1227
414k
    if ((di < ds_unres->disabled_leafrefs.count) || (li < ds_unres->leafrefs.count) || (wi < ds_unres->whens.count)) {
1228
        /* new items in the sets */
1229
0
        goto implement_all;
1230
0
    }
1231
1232
414k
    return LY_SUCCESS;
1233
414k
}
1234
1235
/**
1236
 * @brief Check that a disabled node (to be freed) can be freed and is not referenced.
1237
 *
1238
 * @param[in] node Disabled node to check.
1239
 * @return LY_ERR value.
1240
 */
1241
static LY_ERR
1242
lys_compile_unres_check_disabled(const struct lysc_node *node)
1243
25
{
1244
25
    const struct lysc_node *parent;
1245
25
    struct lysc_node_list *slist;
1246
25
    LY_ARRAY_COUNT_TYPE u, v;
1247
25
    int found;
1248
1249
25
    if (node->flags & LYS_KEY) {
1250
0
        LOG_LOCSET(node);
1251
0
        LOGVAL(node->module->ctx, NULL, LYVE_REFERENCE, "Key \"%s\" is disabled.", node->name);
1252
0
        LOG_LOCBACK(1);
1253
0
        return LY_EVALID;
1254
0
    }
1255
1256
25
    for (parent = node->parent; parent; parent = parent->parent) {
1257
0
        if (parent->nodetype != LYS_LIST) {
1258
0
            continue;
1259
0
        }
1260
1261
        /* check and fix list uniques */
1262
0
        slist = (struct lysc_node_list *)parent;
1263
0
        found = 0;
1264
0
        LY_ARRAY_FOR(slist->uniques, u) {
1265
0
            LY_ARRAY_FOR(slist->uniques[u], v) {
1266
0
                if (slist->uniques[u][v] == (struct lysc_node_leaf *)node) {
1267
0
                    found = 1;
1268
0
                    break;
1269
0
                }
1270
0
            }
1271
1272
0
            if (found) {
1273
0
                break;
1274
0
            }
1275
0
        }
1276
1277
0
        if (found) {
1278
0
            if (LY_ARRAY_COUNT(slist->uniques[u]) > 1) {
1279
                /* remove the item */
1280
0
                if (v < LY_ARRAY_COUNT(slist->uniques[u]) - 1) {
1281
0
                    memmove(&slist->uniques[u][v], &slist->uniques[u][v + 1],
1282
0
                            (LY_ARRAY_COUNT(slist->uniques[u]) - v - 1) * sizeof slist->uniques[u][v]);
1283
0
                }
1284
0
                LY_ARRAY_DECREMENT(slist->uniques[u]);
1285
0
            } else {
1286
                /* remove the whole unique array */
1287
0
                LY_ARRAY_FREE(slist->uniques[u]);
1288
0
                if (LY_ARRAY_COUNT(slist->uniques) > 1) {
1289
0
                    if (u < LY_ARRAY_COUNT(slist->uniques) - 1) {
1290
0
                        memmove(&slist->uniques[u], &slist->uniques[u + 1],
1291
0
                                (LY_ARRAY_COUNT(slist->uniques) - u - 1) * sizeof slist->uniques[u]);
1292
0
                    }
1293
0
                    LY_ARRAY_DECREMENT(slist->uniques);
1294
0
                } else {
1295
0
                    LY_ARRAY_FREE(slist->uniques);
1296
0
                    slist->uniques = NULL;
1297
0
                }
1298
0
            }
1299
0
        }
1300
0
    }
1301
1302
25
    return LY_SUCCESS;
1303
25
}
1304
1305
/**
1306
 * @brief Finish dependency set compilation by resolving all the unres sets.
1307
 *
1308
 * @param[in] ctx libyang context.
1309
 * @param[in] unres Global unres structure with the sets to resolve.
1310
 * @return LY_SUCCESS on success.
1311
 * @return LY_ERECOMPILE if the dep set needs to be recompiled.
1312
 * @return LY_ERR value on error.
1313
 */
1314
static LY_ERR
1315
lys_compile_unres_depset(struct ly_ctx *ctx, struct lys_glob_unres *unres)
1316
414k
{
1317
414k
    LY_ERR ret = LY_SUCCESS;
1318
414k
    struct lysc_node *node;
1319
414k
    struct lysc_type *typeiter;
1320
414k
    struct lysc_type_leafref *lref;
1321
414k
    struct lysc_ctx cctx = {0};
1322
414k
    struct lys_depset_unres *ds_unres = &unres->ds_unres;
1323
414k
    struct ly_path *path;
1324
414k
    LY_ARRAY_COUNT_TYPE v;
1325
414k
    struct lysc_unres_leafref *l;
1326
414k
    struct lysc_unres_when *w;
1327
414k
    struct lysc_unres_must *m;
1328
414k
    struct lysc_unres_dflt *d;
1329
414k
    uint32_t i, processed_leafrefs = 0;
1330
1331
414k
resolve_all:
1332
    /* implement all referenced modules to get final ds_unres set */
1333
414k
    if ((ret = lys_compile_unres_depset_implement(ctx, unres))) {
1334
0
        goto cleanup;
1335
0
    }
1336
1337
    /* check disabled leafrefs */
1338
414k
    while (ds_unres->disabled_leafrefs.count) {
1339
        /* remember index, it can change before we get to free this item */
1340
0
        i = ds_unres->disabled_leafrefs.count - 1;
1341
0
        l = ds_unres->disabled_leafrefs.objs[i];
1342
0
        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed, l->ext);
1343
1344
0
        v = 0;
1345
0
        while ((ret == LY_SUCCESS) && (lref = lys_type_leafref_next(l->node, &v))) {
1346
0
            ret = lys_compile_unres_leafref(&cctx, l->node, lref, l->local_mod);
1347
0
        }
1348
0
        LY_CHECK_GOTO(ret, cleanup);
1349
1350
0
        ly_set_rm_index(&ds_unres->disabled_leafrefs, i, free);
1351
0
    }
1352
1353
    /* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
1354
     * can be also leafref, in case it is already resolved, go through the chain and check that it does not
1355
     * point to the starting leafref type). The second round stores the first non-leafref type for later data validation.
1356
     * Also do the same check for set of the disabled leafrefs, but without the second round. */
1357
576k
    for (i = processed_leafrefs; i < ds_unres->leafrefs.count; ++i) {
1358
161k
        l = ds_unres->leafrefs.objs[i];
1359
161k
        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed, l->ext);
1360
1361
161k
        v = 0;
1362
323k
        while ((ret == LY_SUCCESS) && (lref = lys_type_leafref_next(l->node, &v))) {
1363
161k
            ret = lys_compile_unres_leafref(&cctx, l->node, lref, l->local_mod);
1364
161k
        }
1365
161k
        LY_CHECK_GOTO(ret, cleanup);
1366
161k
    }
1367
576k
    for (i = processed_leafrefs; i < ds_unres->leafrefs.count; ++i) {
1368
161k
        l = ds_unres->leafrefs.objs[i];
1369
1370
        /* store pointer to the real type */
1371
161k
        v = 0;
1372
323k
        while ((lref = lys_type_leafref_next(l->node, &v))) {
1373
161k
            for (typeiter = lref->realtype;
1374
161k
                    typeiter->basetype == LY_TYPE_LEAFREF;
1375
161k
                    typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
1376
1377
161k
            lysc_type_free(cctx.ctx, lref->realtype);
1378
161k
            lref->realtype = typeiter;
1379
161k
            ++lref->realtype->refcount;
1380
161k
        }
1381
1382
        /* if 'goto' will be used on the 'resolve_all' label, then the current leafref will not be processed again */
1383
161k
        processed_leafrefs++;
1384
161k
    }
1385
1386
    /* check when, the referenced modules must be implemented now */
1387
418k
    while (ds_unres->whens.count) {
1388
3.81k
        i = ds_unres->whens.count - 1;
1389
3.81k
        w = ds_unres->whens.objs[i];
1390
3.81k
        LYSC_CTX_INIT_PMOD(cctx, w->node->module->parsed, NULL);
1391
1392
3.81k
        ret = lys_compile_unres_when(&cctx, w->when, w->node);
1393
3.81k
        LY_CHECK_GOTO(ret, cleanup);
1394
1395
3.62k
        free(w);
1396
3.62k
        ly_set_rm_index(&ds_unres->whens, i, NULL);
1397
3.62k
    }
1398
1399
    /* check must */
1400
415k
    while (ds_unres->musts.count) {
1401
654
        i = ds_unres->musts.count - 1;
1402
654
        m = ds_unres->musts.objs[i];
1403
654
        LYSC_CTX_INIT_PMOD(cctx, m->node->module->parsed, m->ext);
1404
1405
654
        ret = lys_compile_unres_must(&cctx, m->node, m->local_mods);
1406
654
        LY_CHECK_GOTO(ret, cleanup);
1407
1408
572
        lysc_unres_must_free(m);
1409
572
        ly_set_rm_index(&ds_unres->musts, i, NULL);
1410
572
    }
1411
1412
    /* remove disabled enums/bits */
1413
463k
    while (ds_unres->disabled_bitenums.count) {
1414
48.9k
        i = ds_unres->disabled_bitenums.count - 1;
1415
48.9k
        node = ds_unres->disabled_bitenums.objs[i];
1416
48.9k
        LYSC_CTX_INIT_PMOD(cctx, node->module->parsed, NULL);
1417
1418
48.9k
        ret = lys_compile_unres_disabled_bitenum(&cctx, (struct lysc_node_leaf *)node);
1419
48.9k
        LY_CHECK_GOTO(ret, cleanup);
1420
1421
48.9k
        ly_set_rm_index(&ds_unres->disabled_bitenums, i, NULL);
1422
48.9k
    }
1423
1424
    /* finish incomplete default values compilation */
1425
440k
    while (ds_unres->dflts.count) {
1426
26.7k
        i = ds_unres->dflts.count - 1;
1427
26.7k
        d = ds_unres->dflts.objs[i];
1428
26.7k
        LYSC_CTX_INIT_PMOD(cctx, d->leaf->module->parsed, NULL);
1429
1430
26.7k
        if (d->leaf->nodetype == LYS_LEAF) {
1431
26.7k
            ret = lys_compile_unres_leaf_dlft(&cctx, d->leaf, d->dflt, unres);
1432
26.7k
        } else {
1433
0
            ret = lys_compile_unres_llist_dflts(&cctx, d->llist, d->dflt, d->dflts, unres);
1434
0
        }
1435
26.7k
        LY_CHECK_GOTO(ret, cleanup);
1436
1437
26.3k
        lysc_unres_dflt_free(ctx, d);
1438
26.3k
        ly_set_rm_index(&ds_unres->dflts, i, NULL);
1439
26.3k
    }
1440
1441
    /* some unres items may have been added by the default values */
1442
413k
    if ((processed_leafrefs != ds_unres->leafrefs.count) || ds_unres->disabled_leafrefs.count ||
1443
413k
            ds_unres->whens.count || ds_unres->musts.count || ds_unres->dflts.count) {
1444
0
        goto resolve_all;
1445
0
    }
1446
1447
    /* finally, remove all disabled nodes */
1448
414k
    for (i = 0; i < ds_unres->disabled.count; ++i) {
1449
25
        node = ds_unres->disabled.snodes[i];
1450
25
        ret = lys_compile_unres_check_disabled(node);
1451
25
        LY_CHECK_GOTO(ret, cleanup);
1452
1453
25
        LYSC_CTX_INIT_PMOD(cctx, node->module->parsed, NULL);
1454
1455
25
        lysc_node_free(cctx.ctx, node, 1);
1456
25
    }
1457
1458
    /* also check if the leafref target has not been disabled */
1459
575k
    for (i = 0; i < ds_unres->leafrefs.count; ++i) {
1460
161k
        l = ds_unres->leafrefs.objs[i];
1461
161k
        LYSC_CTX_INIT_PMOD(cctx, l->node->module->parsed, l->ext);
1462
1463
161k
        v = 0;
1464
323k
        while ((lref = lys_type_leafref_next(l->node, &v))) {
1465
161k
            ret = ly_path_compile_leafref(cctx.ctx, l->node, lref->path,
1466
161k
                    (l->node->flags & LYS_IS_OUTPUT) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
1467
161k
                    LY_VALUE_SCHEMA_RESOLVED, lref->prefixes, &path);
1468
161k
            ly_path_free(path);
1469
1470
161k
            assert(ret != LY_ERECOMPILE);
1471
161k
            if (ret) {
1472
0
                LOG_LOCSET(l->node);
1473
0
                LOGVAL(ctx, NULL, LYVE_REFERENCE, "Target of leafref \"%s\" cannot be referenced because it is disabled.",
1474
0
                        l->node->name);
1475
0
                LOG_LOCBACK(1);
1476
0
                ret = LY_EVALID;
1477
0
                goto cleanup;
1478
0
            }
1479
161k
        }
1480
161k
    }
1481
1482
414k
cleanup:
1483
414k
    return ret;
1484
413k
}
1485
1486
/**
1487
 * @brief Erase dep set unres.
1488
 *
1489
 * @param[in] ctx libyang context.
1490
 * @param[in] unres Global unres structure with the sets to resolve.
1491
 */
1492
static void
1493
lys_compile_unres_depset_erase(const struct ly_ctx *ctx, struct lys_glob_unres *unres)
1494
831k
{
1495
831k
    uint32_t i;
1496
1497
831k
    ly_set_erase(&unres->ds_unres.whens, free);
1498
831k
    for (i = 0; i < unres->ds_unres.musts.count; ++i) {
1499
543
        lysc_unres_must_free(unres->ds_unres.musts.objs[i]);
1500
543
    }
1501
831k
    ly_set_erase(&unres->ds_unres.musts, NULL);
1502
831k
    ly_set_erase(&unres->ds_unres.leafrefs, free);
1503
831k
    for (i = 0; i < unres->ds_unres.dflts.count; ++i) {
1504
441
        lysc_unres_dflt_free(ctx, unres->ds_unres.dflts.objs[i]);
1505
441
    }
1506
831k
    ly_set_erase(&unres->ds_unres.dflts, NULL);
1507
831k
    ly_set_erase(&unres->ds_unres.disabled, NULL);
1508
831k
    ly_set_erase(&unres->ds_unres.disabled_leafrefs, free);
1509
831k
    ly_set_erase(&unres->ds_unres.disabled_bitenums, NULL);
1510
831k
}
1511
1512
/**
1513
 * @brief Compile all flagged modules in a dependency set, recursively if recompilation is needed.
1514
 *
1515
 * @param[in] ctx libyang context.
1516
 * @param[in] dep_set Dependency set to compile.
1517
 * @param[in,out] unres Global unres to use.
1518
 * @return LY_ERR value.
1519
 */
1520
static LY_ERR
1521
lys_compile_depset_r(struct ly_ctx *ctx, struct ly_set *dep_set, struct lys_glob_unres *unres)
1522
416k
{
1523
416k
    LY_ERR ret = LY_SUCCESS;
1524
416k
    struct lys_module *mod;
1525
416k
    uint32_t i;
1526
1527
828k
    for (i = 0; i < dep_set->count; ++i) {
1528
413k
        mod = dep_set->objs[i];
1529
413k
        if (!mod->to_compile) {
1530
            /* skip */
1531
219k
            continue;
1532
219k
        }
1533
413k
        assert(mod->implemented);
1534
1535
        /* free the compiled module, if any */
1536
194k
        lysc_module_free(ctx, mod->compiled);
1537
194k
        mod->compiled = NULL;
1538
1539
        /* (re)compile the module */
1540
194k
        LY_CHECK_GOTO(ret = lys_compile(mod, &unres->ds_unres), cleanup);
1541
192k
    }
1542
1543
414k
resolve_unres:
1544
    /* resolve dep set unres */
1545
414k
    ret = lys_compile_unres_depset(ctx, unres);
1546
414k
    lys_compile_unres_depset_erase(ctx, unres);
1547
1548
414k
    if (ret == LY_ERECOMPILE) {
1549
        /* new module is implemented referencing previously compiled modules, recompile the whole dep set */
1550
0
        return lys_compile_depset_r(ctx, dep_set, unres);
1551
414k
    } else if (ret) {
1552
        /* error */
1553
681
        goto cleanup;
1554
681
    }
1555
1556
    /* success, unset the flags of all the modules in the dep set */
1557
825k
    for (i = 0; i < dep_set->count; ++i) {
1558
411k
        mod = dep_set->objs[i];
1559
1560
411k
        if (mod->to_compile && !mod->compiled) {
1561
            /* new module is implemented but does not require recompilation of the whole dep set */
1562
0
            LY_CHECK_GOTO(ret = lys_compile(mod, &unres->ds_unres), cleanup);
1563
0
            goto resolve_unres;
1564
0
        }
1565
1566
411k
        mod->to_compile = 0;
1567
411k
    }
1568
1569
416k
cleanup:
1570
416k
    lys_compile_unres_depset_erase(ctx, unres);
1571
416k
    return ret;
1572
413k
}
1573
1574
/**
1575
 * @brief Check if-feature of all features of all modules in a dep set.
1576
 *
1577
 * @param[in] dep_set Dep set to check.
1578
 * @return LY_ERR value.
1579
 */
1580
static LY_ERR
1581
lys_compile_depset_check_features(struct ly_set *dep_set)
1582
416k
{
1583
416k
    struct lys_module *mod;
1584
416k
    uint32_t i;
1585
1586
830k
    for (i = 0; i < dep_set->count; ++i) {
1587
413k
        mod = dep_set->objs[i];
1588
413k
        if (!mod->to_compile) {
1589
            /* skip */
1590
219k
            continue;
1591
219k
        }
1592
1593
        /* check features of this module */
1594
194k
        LY_CHECK_RET(lys_check_features(mod->parsed));
1595
194k
    }
1596
1597
416k
    return LY_SUCCESS;
1598
416k
}
1599
1600
LY_ERR
1601
lys_compile_depset_all(struct ly_ctx *ctx, struct lys_glob_unres *unres)
1602
54.6k
{
1603
54.6k
    uint32_t i;
1604
1605
468k
    for (i = 0; i < unres->dep_sets.count; ++i) {
1606
416k
        LY_CHECK_RET(lys_compile_depset_check_features(unres->dep_sets.objs[i]));
1607
416k
        LY_CHECK_RET(lys_compile_depset_r(ctx, unres->dep_sets.objs[i], unres));
1608
413k
    }
1609
1610
52.1k
    return LY_SUCCESS;
1611
54.6k
}
1612
1613
/**
1614
 * @brief Finish compilation of all the module unres sets in a compile context.
1615
 *
1616
 * @param[in] ctx Compile context with unres sets.
1617
 * @return LY_ERR value.
1618
 */
1619
static LY_ERR
1620
lys_compile_unres_mod(struct lysc_ctx *ctx)
1621
192k
{
1622
192k
    struct lysc_augment *aug;
1623
192k
    struct lysc_deviation *dev;
1624
192k
    struct lys_module *orig_mod = ctx->cur_mod;
1625
192k
    uint32_t i;
1626
1627
    /* check that all augments were applied */
1628
236k
    for (i = 0; i < ctx->augs.count; ++i) {
1629
43.4k
        aug = ctx->augs.objs[i];
1630
43.4k
        ctx->cur_mod = aug->aug_pmod->mod;
1631
43.4k
        if (aug->ext) {
1632
0
            lysc_update_path(ctx, NULL, "{ext-inst}");
1633
0
            lysc_update_path(ctx, NULL, aug->ext->name);
1634
0
        }
1635
43.4k
        lysc_update_path(ctx, NULL, "{augment}");
1636
43.4k
        lysc_update_path(ctx, NULL, aug->nodeid->str);
1637
43.4k
        LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Augment%s target node \"%s\" from module \"%s\" was not found.",
1638
43.4k
                aug->ext ? " ext-inst" : "", aug->nodeid->str, LYSP_MODULE_NAME(aug->aug_pmod));
1639
43.4k
        ctx->cur_mod = orig_mod;
1640
43.4k
        lysc_update_path(ctx, NULL, NULL);
1641
43.4k
        lysc_update_path(ctx, NULL, NULL);
1642
43.4k
        if (aug->ext) {
1643
0
            lysc_update_path(ctx, NULL, NULL);
1644
0
            lysc_update_path(ctx, NULL, NULL);
1645
0
        }
1646
43.4k
    }
1647
192k
    if (ctx->augs.count) {
1648
299
        return LY_ENOTFOUND;
1649
299
    }
1650
1651
    /* check that all deviations were applied */
1652
192k
    for (i = 0; i < ctx->devs.count; ++i) {
1653
0
        dev = ctx->devs.objs[i];
1654
0
        lysc_update_path(ctx, NULL, "{deviation}");
1655
0
        lysc_update_path(ctx, NULL, dev->nodeid->str);
1656
0
        LOGVAL(ctx->ctx, NULL, LYVE_REFERENCE, "Deviation(s) target node \"%s\" from module \"%s\" was not found.",
1657
0
                dev->nodeid->str, LYSP_MODULE_NAME(dev->dev_pmods[0]));
1658
0
        lysc_update_path(ctx, NULL, NULL);
1659
0
        lysc_update_path(ctx, NULL, NULL);
1660
0
    }
1661
192k
    if (ctx->devs.count) {
1662
0
        return LY_ENOTFOUND;
1663
0
    }
1664
1665
192k
    return LY_SUCCESS;
1666
192k
}
1667
1668
/**
1669
 * @brief Erase all the module unres sets in a compile context.
1670
 *
1671
 * @param[in] ctx Compile context with unres sets.
1672
 * @param[in] error Whether the compilation finished with an error or not.
1673
 */
1674
static void
1675
lys_compile_unres_mod_erase(struct lysc_ctx *ctx, ly_bool error)
1676
194k
{
1677
194k
    uint32_t i;
1678
1679
194k
    ly_set_erase(&ctx->groupings, NULL);
1680
194k
    ly_set_erase(&ctx->tpdf_chain, NULL);
1681
1682
194k
    if (!error) {
1683
        /* there can be no leftover deviations or augments */
1684
192k
        LY_CHECK_ERR_RET(ctx->augs.count, LOGINT(ctx->ctx), );
1685
192k
        LY_CHECK_ERR_RET(ctx->devs.count, LOGINT(ctx->ctx), );
1686
1687
192k
        ly_set_erase(&ctx->augs, NULL);
1688
192k
        ly_set_erase(&ctx->devs, NULL);
1689
192k
        ly_set_erase(&ctx->uses_augs, NULL);
1690
192k
        ly_set_erase(&ctx->uses_rfns, NULL);
1691
192k
    } else {
1692
45.2k
        for (i = 0; i < ctx->augs.count; ++i) {
1693
43.4k
            lysc_augment_free(ctx->ctx, ctx->augs.objs[i]);
1694
43.4k
        }
1695
1.78k
        ly_set_erase(&ctx->augs, NULL);
1696
1.78k
        for (i = 0; i < ctx->devs.count; ++i) {
1697
0
            lysc_deviation_free(ctx->ctx, ctx->devs.objs[i]);
1698
0
        }
1699
1.78k
        ly_set_erase(&ctx->devs, NULL);
1700
1.78k
        for (i = 0; i < ctx->uses_augs.count; ++i) {
1701
0
            lysc_augment_free(ctx->ctx, ctx->uses_augs.objs[i]);
1702
0
        }
1703
1.78k
        ly_set_erase(&ctx->uses_augs, NULL);
1704
1.78k
        for (i = 0; i < ctx->uses_rfns.count; ++i) {
1705
0
            lysc_refine_free(ctx->ctx, ctx->uses_rfns.objs[i]);
1706
0
        }
1707
1.78k
        ly_set_erase(&ctx->uses_rfns, NULL);
1708
1.78k
    }
1709
194k
}
1710
1711
/**
1712
 * @brief Compile (copy) all enabled features of a parsed module.
1713
 *
1714
 * @param[in] mod Module with the parsed and compiled module.
1715
 * @return LY_ERR value.
1716
 */
1717
static LY_ERR
1718
lys_compile_enabled_features(struct lys_module *mod)
1719
194k
{
1720
194k
    LY_ERR rc = LY_SUCCESS;
1721
194k
    struct lysp_feature *f = NULL;
1722
194k
    uint32_t idx = 0;
1723
194k
    const char **feat_p;
1724
1725
    /* copy enabled features */
1726
204k
    while ((f = lysp_feature_next(f, mod->parsed, &idx))) {
1727
10.1k
        if (f->flags & LYS_FENABLED) {
1728
0
            LY_ARRAY_NEW_GOTO(mod->ctx, mod->compiled->features, feat_p, rc, cleanup);
1729
0
            LY_CHECK_GOTO(rc = lysdict_dup(mod->ctx, f->name, feat_p), cleanup);
1730
0
        }
1731
10.1k
    }
1732
1733
    /* last NULL feature */
1734
388k
    LY_ARRAY_NEW_GOTO(mod->ctx, mod->compiled->features, feat_p, rc, cleanup);
1735
388k
    LY_ARRAY_DECREMENT(mod->compiled->features);
1736
1737
388k
cleanup:
1738
194k
    return rc;
1739
388k
}
1740
1741
LY_ERR
1742
lys_compile(struct lys_module *mod, struct lys_depset_unres *unres)
1743
194k
{
1744
194k
    struct lysc_ctx ctx = {0};
1745
194k
    struct lysc_module *mod_c = NULL;
1746
194k
    struct lysp_module *sp;
1747
194k
    struct lysp_submodule *submod;
1748
194k
    struct lysp_node *pnode;
1749
194k
    struct lysp_node_grp *grp;
1750
194k
    LY_ARRAY_COUNT_TYPE u;
1751
194k
    LY_ERR ret = LY_SUCCESS;
1752
1753
583k
    LY_CHECK_ARG_RET(NULL, mod, mod->parsed, !mod->compiled, mod->ctx, LY_EINVAL);
1754
1755
194k
    assert(mod->implemented && mod->to_compile);
1756
1757
194k
    sp = mod->parsed;
1758
194k
    LYSC_CTX_INIT_PMOD(ctx, sp, NULL);
1759
194k
    ctx.unres = unres;
1760
1761
194k
    mod->compiled = mod_c = calloc(1, sizeof *mod_c);
1762
194k
    LY_CHECK_ERR_RET(!mod_c, LOGMEM(mod->ctx), LY_EMEM);
1763
194k
    mod_c->mod = mod;
1764
1765
    /* copy the enabled features */
1766
194k
    LY_CHECK_GOTO(ret = lys_compile_enabled_features(mod), cleanup);
1767
1768
    /* compile augments and deviations of our module from other modules so they can be applied during compilation */
1769
194k
    LY_CHECK_GOTO(ret = lys_precompile_own_augments(&ctx), cleanup);
1770
194k
    LY_CHECK_GOTO(ret = lys_precompile_own_deviations(&ctx), cleanup);
1771
1772
    /* data nodes */
1773
437k
    LY_LIST_FOR(sp->data, pnode) {
1774
437k
        LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), cleanup);
1775
435k
    }
1776
1777
    /* top-level RPCs */
1778
193k
    LY_LIST_FOR((struct lysp_node *)sp->rpcs, pnode) {
1779
4.07k
        LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), cleanup);
1780
4.03k
    }
1781
1782
    /* top-level notifications */
1783
192k
    LY_LIST_FOR((struct lysp_node *)sp->notifs, pnode) {
1784
53.3k
        LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), cleanup);
1785
53.3k
    }
1786
1787
    /* module extension instances */
1788
192k
    COMPILE_EXTS_GOTO(&ctx, sp->exts, mod_c->exts, mod_c, ret, cleanup);
1789
1790
    /* the same for submodules */
1791
192k
    LY_ARRAY_FOR(sp->includes, u) {
1792
0
        submod = sp->includes[u].submodule;
1793
0
        ctx.pmod = (struct lysp_module *)submod;
1794
1795
0
        LY_LIST_FOR(submod->data, pnode) {
1796
0
            ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
1797
0
            LY_CHECK_GOTO(ret, cleanup);
1798
0
        }
1799
1800
0
        LY_LIST_FOR((struct lysp_node *)submod->rpcs, pnode) {
1801
0
            ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
1802
0
            LY_CHECK_GOTO(ret, cleanup);
1803
0
        }
1804
1805
0
        LY_LIST_FOR((struct lysp_node *)submod->notifs, pnode) {
1806
0
            ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
1807
0
            LY_CHECK_GOTO(ret, cleanup);
1808
0
        }
1809
1810
0
        COMPILE_EXTS_GOTO(&ctx, submod->exts, mod_c->exts, mod_c, ret, cleanup);
1811
0
    }
1812
192k
    ctx.pmod = sp;
1813
1814
    /* validate non-instantiated groupings from the parsed schema,
1815
     * without it we would accept even the schemas with invalid grouping specification */
1816
192k
    ctx.compile_opts |= LYS_COMPILE_GROUPING;
1817
192k
    LY_LIST_FOR(sp->groupings, grp) {
1818
157k
        if (!(grp->flags & LYS_USED_GRP)) {
1819
232
            LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, grp), cleanup);
1820
231
        }
1821
157k
    }
1822
434k
    LY_LIST_FOR(sp->data, pnode) {
1823
434k
        LY_LIST_FOR((struct lysp_node_grp *)lysp_node_groupings(pnode), grp) {
1824
518
            if (!(grp->flags & LYS_USED_GRP)) {
1825
516
                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, grp), cleanup);
1826
509
            }
1827
518
        }
1828
434k
    }
1829
192k
    LY_ARRAY_FOR(sp->includes, u) {
1830
0
        submod = sp->includes[u].submodule;
1831
0
        ctx.pmod = (struct lysp_module *)submod;
1832
1833
0
        LY_LIST_FOR(submod->groupings, grp) {
1834
0
            if (!(grp->flags & LYS_USED_GRP)) {
1835
0
                LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, NULL, grp), cleanup);
1836
0
            }
1837
0
        }
1838
0
        LY_LIST_FOR(submod->data, pnode) {
1839
0
            LY_LIST_FOR((struct lysp_node_grp *)lysp_node_groupings(pnode), grp) {
1840
0
                if (!(grp->flags & LYS_USED_GRP)) {
1841
0
                    LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, grp), cleanup);
1842
0
                }
1843
0
            }
1844
0
        }
1845
0
    }
1846
192k
    ctx.pmod = sp;
1847
1848
192k
    ly_log_location_revert(0, 1, 0);
1849
1850
    /* finish compilation for all unresolved module items in the context */
1851
192k
    LY_CHECK_GOTO(ret = lys_compile_unres_mod(&ctx), cleanup);
1852
1853
192k
    if (mod->ctx->opts & LY_CTX_LYB_HASHES) {
1854
        /* generate schema hashes for all the schema nodes */
1855
0
        lysc_module_dfs_full(mod, lyb_cache_node_hash_cb, NULL);
1856
0
    }
1857
1858
194k
cleanup:
1859
194k
    ly_log_location_revert(0, 1, 0);
1860
194k
    lys_compile_unres_mod_erase(&ctx, ret);
1861
194k
    if (ret) {
1862
1.78k
        lysc_module_free(ctx.ctx, mod_c);
1863
1.78k
        mod->compiled = NULL;
1864
1.78k
    }
1865
194k
    return ret;
1866
192k
}
1867
1868
/**
1869
 * @brief Compile all extension definitions in a parsed module into the main module.
1870
 *
1871
 * @param[in] mod Module to use.
1872
 * @param[in] pmod Parsed (sub)module to use.
1873
 * @return LY_ERR value.
1874
 */
1875
static LY_ERR
1876
lys_compile_extensions_pmod(struct lys_module *mod, struct lysp_module *pmod)
1877
262k
{
1878
262k
    LY_ERR rc = LY_SUCCESS;
1879
262k
    struct lysc_ctx ctx = {0};
1880
262k
    LY_ARRAY_COUNT_TYPE u;
1881
262k
    struct lysp_ext *ep;
1882
262k
    struct lysc_ext *ec;
1883
1884
262k
    LYSC_CTX_INIT_PMOD(ctx, pmod, NULL);
1885
1886
262k
    LY_ARRAY_FOR(pmod->extensions, u) {
1887
107k
        ep = &pmod->extensions[u];
1888
1889
        /* allocate a new extension */
1890
107k
        LY_ARRAY_NEW_GOTO(mod->ctx, mod->extensions, ec, rc, cleanup);
1891
1892
        /* compile the extension definition */
1893
107k
        DUP_STRING_GOTO(ctx.ctx, ep->name, ec->name, rc, cleanup);
1894
107k
        DUP_STRING_GOTO(ctx.ctx, ep->argname, ec->argname, rc, cleanup);
1895
107k
        ec->module = mod;
1896
107k
        ec->plugin_ref = ep->plugin_ref;
1897
107k
    }
1898
1899
262k
cleanup:
1900
262k
    return rc;
1901
262k
}
1902
1903
/**
1904
 * @brief Compile all ext instances of extension definitions in a parsed module.
1905
 *
1906
 * @param[in] mod Module to use.
1907
 * @param[in] mod_ext_idx Index in ext of @p mod to start at.
1908
 * @param[in] pmod Parsed (sub)module to use.
1909
 * @return LY_ERR value.
1910
 */
1911
static LY_ERR
1912
lys_compile_extensions_ext_pmod(struct lys_module *mod, LY_ARRAY_COUNT_TYPE mod_ext_idx, struct lysp_module *pmod)
1913
262k
{
1914
262k
    LY_ERR rc = LY_SUCCESS;
1915
262k
    struct lysc_ctx ctx = {0};
1916
262k
    LY_ARRAY_COUNT_TYPE u;
1917
262k
    struct lysp_ext *ep;
1918
262k
    struct lysc_ext *ec;
1919
1920
262k
    LYSC_CTX_INIT_PMOD(ctx, pmod, NULL);
1921
1922
262k
    LY_ARRAY_FOR(pmod->extensions, u) {
1923
107k
        ep = &pmod->extensions[u];
1924
107k
        ec = &mod->extensions[mod_ext_idx];
1925
1926
107k
        lysc_update_path(&ctx, NULL, "{extension}");
1927
107k
        lysc_update_path(&ctx, NULL, ep->name);
1928
1929
        /* compile nested extensions */
1930
107k
        COMPILE_EXTS_GOTO(&ctx, ep->exts, ec->exts, ec, rc, next_line);
1931
107k
next_line:
1932
107k
        lysc_update_path(&ctx, NULL, NULL);
1933
107k
        lysc_update_path(&ctx, NULL, NULL);
1934
1935
107k
        LY_CHECK_GOTO(rc, cleanup);
1936
1937
107k
        ++mod_ext_idx;
1938
107k
    }
1939
1940
262k
cleanup:
1941
262k
    return rc;
1942
262k
}
1943
1944
LY_ERR
1945
lys_compile_extensions(struct lys_module *mod)
1946
262k
{
1947
262k
    LY_ERR rc = LY_SUCCESS;
1948
262k
    LY_ARRAY_COUNT_TYPE u, v;
1949
262k
    struct lysp_include *inc;
1950
1951
    /* compile all module and submodule extension definitions */
1952
262k
    LY_CHECK_GOTO(rc = lys_compile_extensions_pmod(mod, mod->parsed), cleanup);
1953
262k
    LY_ARRAY_FOR(mod->parsed->includes, u) {
1954
0
        LY_CHECK_GOTO(rc = lys_compile_extensions_pmod(mod, (struct lysp_module *)mod->parsed->includes[u].submodule),
1955
0
                cleanup);
1956
0
    }
1957
1958
    /* compile all nested extension instances, which can reference the compiled definitions,
1959
     * there is one extensions array in main mod for the parsed module and all submodules so we need a special index */
1960
262k
    v = 0;
1961
262k
    LY_CHECK_GOTO(rc = lys_compile_extensions_ext_pmod(mod, v, mod->parsed), cleanup);
1962
1963
262k
    v += LY_ARRAY_COUNT(mod->parsed->extensions);
1964
262k
    LY_ARRAY_FOR(mod->parsed->includes, u) {
1965
0
        inc = &mod->parsed->includes[u];
1966
0
        LY_CHECK_GOTO(rc = lys_compile_extensions_ext_pmod(mod, v, (struct lysp_module *)inc->submodule), cleanup);
1967
1968
0
        v += LY_ARRAY_COUNT(inc->submodule->extensions);
1969
0
    }
1970
1971
262k
    assert(v == LY_ARRAY_COUNT(mod->extensions));
1972
1973
262k
cleanup:
1974
262k
    return rc;
1975
262k
}
1976
1977
LY_ERR
1978
lys_compile_identities(struct lys_module *mod)
1979
262k
{
1980
262k
    LY_ERR rc = LY_SUCCESS;
1981
262k
    struct lysc_ctx ctx = {0};
1982
262k
    struct lysp_submodule *submod;
1983
262k
    LY_ARRAY_COUNT_TYPE u;
1984
1985
    /* pre-compile identities of the module and any submodules */
1986
262k
    rc = lys_identity_precompile(NULL, mod->ctx, mod->parsed, mod->parsed->identities, &mod->identities);
1987
262k
    LY_CHECK_GOTO(rc, cleanup);
1988
262k
    LY_ARRAY_FOR(mod->parsed->includes, u) {
1989
0
        submod = mod->parsed->includes[u].submodule;
1990
0
        rc = lys_identity_precompile(NULL, mod->ctx, (struct lysp_module *)submod, submod->identities, &mod->identities);
1991
0
        LY_CHECK_GOTO(rc, cleanup);
1992
0
    }
1993
1994
    /* prepare context */
1995
262k
    LYSC_CTX_INIT_PMOD(ctx, mod->parsed, NULL);
1996
1997
262k
    if (mod->parsed->identities) {
1998
46.5k
        rc = lys_compile_identities_derived(&ctx, mod->parsed->identities, &mod->identities);
1999
46.5k
        LY_CHECK_GOTO(rc, cleanup);
2000
46.5k
    }
2001
262k
    lysc_update_path(&ctx, NULL, "{submodule}");
2002
262k
    LY_ARRAY_FOR(mod->parsed->includes, u) {
2003
0
        submod = mod->parsed->includes[u].submodule;
2004
0
        if (submod->identities) {
2005
0
            ctx.pmod = (struct lysp_module *)submod;
2006
0
            lysc_update_path(&ctx, NULL, submod->name);
2007
0
            rc = lys_compile_identities_derived(&ctx, submod->identities, &mod->identities);
2008
0
            lysc_update_path(&ctx, NULL, NULL);
2009
0
        }
2010
2011
0
        if (rc) {
2012
0
            break;
2013
0
        }
2014
0
    }
2015
262k
    lysc_update_path(&ctx, NULL, NULL);
2016
2017
262k
cleanup:
2018
    /* always needed when using lysc_update_path() */
2019
262k
    ly_log_location_revert(0, 1, 0);
2020
262k
    return rc;
2021
262k
}
2022
2023
/**
2024
 * @brief Check whether a module does not have any (recursive) compiled import.
2025
 *
2026
 * @param[in] mod Module to examine.
2027
 * @return LY_SUCCESS on success.
2028
 * @return LY_ERECOMPILE on required recompilation of the dep set.
2029
 * @return LY_ERR on error.
2030
 */
2031
static LY_ERR
2032
lys_has_compiled_import_r(struct lys_module *mod)
2033
262k
{
2034
262k
    LY_ARRAY_COUNT_TYPE u;
2035
262k
    struct lys_module *m;
2036
2037
262k
    LY_ARRAY_FOR(mod->parsed->imports, u) {
2038
221k
        m = mod->parsed->imports[u].module;
2039
221k
        if (!m->implemented) {
2040
131k
            continue;
2041
131k
        }
2042
2043
89.7k
        if (!m->to_compile) {
2044
            /* module was not/will not be compiled in this compilation (so disabled nodes are not present) */
2045
11.0k
            m->to_compile = 1;
2046
11.0k
            return LY_ERECOMPILE;
2047
11.0k
        }
2048
2049
        /* recursive */
2050
78.7k
        LY_CHECK_RET(lys_has_compiled_import_r(m));
2051
78.7k
    }
2052
2053
251k
    return LY_SUCCESS;
2054
262k
}
2055
2056
LY_ERR
2057
lys_implement(struct lys_module *mod, const char **features, struct lys_glob_unres *unres)
2058
183k
{
2059
183k
    LY_ERR r;
2060
183k
    struct lys_module *m;
2061
2062
183k
    assert(!mod->implemented);
2063
2064
    /* check collision with other implemented revision */
2065
183k
    m = ly_ctx_get_module_implemented(mod->ctx, mod->name);
2066
183k
    if (m) {
2067
4
        assert(m != mod);
2068
4
        LOGERR(mod->ctx, LY_EDENIED, "Module \"%s@%s\" is already implemented in revision \"%s\".",
2069
4
                mod->name, mod->revision ? mod->revision : "<none>", m->revision ? m->revision : "<none>");
2070
4
        return LY_EDENIED;
2071
4
    }
2072
2073
    /* set features */
2074
183k
    r = lys_set_features(mod->parsed, features);
2075
183k
    if (r && (r != LY_EEXIST)) {
2076
0
        return r;
2077
0
    }
2078
2079
    /*
2080
     * mark the module implemented, which means
2081
     * 1) to (re)compile it only ::lys_compile() call is needed
2082
     * 2) its compilation will never cause new modules to be implemented (::lys_compile() does not return ::LY_ERECOMPILE)
2083
     *    but there can be some unres items added that do
2084
     */
2085
183k
    mod->implemented = 1;
2086
2087
    /* this module is compiled in this compilation */
2088
183k
    mod->to_compile = 1;
2089
2090
    /* add the module into newly implemented module set */
2091
183k
    LY_CHECK_RET(ly_set_add(&unres->implementing, mod, 1, NULL));
2092
2093
    /* mark target modules with our augments and deviations */
2094
183k
    LY_CHECK_RET(lys_precompile_augments_deviations(mod, unres));
2095
2096
    /* check whether this module may reference any modules compiled previously */
2097
183k
    LY_CHECK_RET(lys_has_compiled_import_r(mod));
2098
2099
172k
    return LY_SUCCESS;
2100
183k
}