blob: 73650d31cc860be3c799b21af4b3d20793651a87 [file] [log] [blame]
Radek Krejci19a96102018-11-15 13:38:09 +01001/**
2 * @file tree_schema.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Schema tree implementation
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
Radek Krejci535ea9f2020-05-29 16:01:05 +020015#define _GNU_SOURCE
Radek Krejci19a96102018-11-15 13:38:09 +010016
Radek Krejcie7b95092019-05-15 11:03:07 +020017#include <assert.h>
Radek Krejci19a96102018-11-15 13:38:09 +010018#include <ctype.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020019#include <stddef.h>
20#include <stdint.h>
Radek Krejci19a96102018-11-15 13:38:09 +010021#include <stdio.h>
Radek Krejcie7b95092019-05-15 11:03:07 +020022#include <stdlib.h>
23#include <string.h>
Radek Krejci19a96102018-11-15 13:38:09 +010024
Radek Krejci535ea9f2020-05-29 16:01:05 +020025#include "common.h"
Michal Vasko5aa44c02020-06-29 11:47:02 +020026#include "compat.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020027#include "context.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020028#include "dict.h"
29#include "log.h"
Radek Krejcif0e1ba52020-05-22 15:14:35 +020030#include "parser.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020031#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020032#include "path.h"
Radek Krejci0935f412019-08-20 16:15:18 +020033#include "plugins_exts.h"
Radek Krejci0935f412019-08-20 16:15:18 +020034#include "plugins_exts_internal.h"
Michal Vasko69730152020-10-09 16:30:07 +020035#include "plugins_types.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020036#include "set.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020037#include "tree.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020038#include "tree_data.h"
Michal Vasko7c8439f2020-08-05 13:25:19 +020039#include "tree_data_internal.h"
Radek Krejcie7b95092019-05-15 11:03:07 +020040#include "tree_schema.h"
Radek Krejci19a96102018-11-15 13:38:09 +010041#include "tree_schema_internal.h"
42#include "xpath.h"
43
Michal Vasko5fe75f12020-03-02 13:52:37 +010044static LY_ERR lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext,
Radek Krejci0f969882020-08-21 16:56:47 +020045 void *parent, LYEXT_PARENT parent_type, const struct lys_module *ext_mod);
Michal Vasko5fe75f12020-03-02 13:52:37 +010046
Michal Vasko7f45cf22020-10-01 12:49:44 +020047static LY_ERR lysp_qname_dup(const struct ly_ctx *ctx, struct lysp_qname *qname, const struct lysp_qname *orig_qname);
48
Radek Krejci19a96102018-11-15 13:38:09 +010049/**
50 * @brief Duplicate string into dictionary
51 * @param[in] CTX libyang context of the dictionary.
52 * @param[in] ORIG String to duplicate.
53 * @param[out] DUP Where to store the result.
54 */
Radek Krejci011e4aa2020-09-04 15:22:31 +020055#define DUP_STRING(CTX, ORIG, DUP, RET) if (ORIG) {RET = lydict_insert(CTX, ORIG, 0, &DUP);}
56
57#define DUP_STRING_GOTO(CTX, ORIG, DUP, RET, GOTO) if (ORIG) {LY_CHECK_GOTO(RET = lydict_insert(CTX, ORIG, 0, &DUP), GOTO);}
Radek Krejci19a96102018-11-15 13:38:09 +010058
Michal Vasko7f45cf22020-10-01 12:49:44 +020059#define DUP_ARRAY(CTX, ORIG_ARRAY, NEW_ARRAY, DUP_FUNC) \
60 if (ORIG_ARRAY) { \
61 LY_ARRAY_COUNT_TYPE u; \
62 LY_ARRAY_CREATE_RET(CTX, NEW_ARRAY, LY_ARRAY_COUNT(ORIG_ARRAY), LY_EMEM); \
63 LY_ARRAY_FOR(ORIG_ARRAY, u) { \
64 LY_ARRAY_INCREMENT(NEW_ARRAY); \
65 LY_CHECK_RET(DUP_FUNC(CTX, &(NEW_ARRAY)[u], &(ORIG_ARRAY)[u])); \
66 } \
67 }
68
Radek Krejciec4da802019-05-02 13:02:41 +020069#define COMPILE_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, ITER, FUNC, RET, GOTO) \
Radek Krejci19a96102018-11-15 13:38:09 +010070 if (ARRAY_P) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +020071 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_COUNT(ARRAY_P), RET, GOTO); \
72 LY_ARRAY_COUNT_TYPE __array_offset = LY_ARRAY_COUNT(ARRAY_C); \
73 for (ITER = 0; ITER < LY_ARRAY_COUNT(ARRAY_P); ++ITER) { \
Radek Krejci19a96102018-11-15 13:38:09 +010074 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejciec4da802019-05-02 13:02:41 +020075 RET = FUNC(CTX, &(ARRAY_P)[ITER], &(ARRAY_C)[ITER + __array_offset]); \
Radek Krejcid05cbd92018-12-05 14:26:40 +010076 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
77 } \
78 }
79
Michal Vasko7f45cf22020-10-01 12:49:44 +020080#define COMPILE_OP_ARRAY_GOTO(CTX, ARRAY_P, ARRAY_C, PARENT, ITER, FUNC, USES_STATUS, RET, GOTO) \
Radek Krejci6eeb58f2019-02-22 16:29:37 +010081 if (ARRAY_P) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +020082 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_COUNT(ARRAY_P), RET, GOTO); \
83 LY_ARRAY_COUNT_TYPE __array_offset = LY_ARRAY_COUNT(ARRAY_C); \
84 for (ITER = 0; ITER < LY_ARRAY_COUNT(ARRAY_P); ++ITER) { \
Radek Krejci6eeb58f2019-02-22 16:29:37 +010085 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejciec4da802019-05-02 13:02:41 +020086 RET = FUNC(CTX, &(ARRAY_P)[ITER], PARENT, &(ARRAY_C)[ITER + __array_offset], USES_STATUS); \
Michal Vasko7f45cf22020-10-01 12:49:44 +020087 if (RET == LY_EDENIED) { \
88 LY_ARRAY_DECREMENT(ARRAY_C); \
89 } else if (RET != LY_SUCCESS) { \
90 goto GOTO; \
91 } \
Radek Krejci6eeb58f2019-02-22 16:29:37 +010092 } \
93 }
94
Radek Krejci0935f412019-08-20 16:15:18 +020095#define COMPILE_EXTS_GOTO(CTX, EXTS_P, EXT_C, PARENT, PARENT_TYPE, RET, GOTO) \
96 if (EXTS_P) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +020097 LY_ARRAY_CREATE_GOTO((CTX)->ctx, EXT_C, LY_ARRAY_COUNT(EXTS_P), RET, GOTO); \
98 for (LY_ARRAY_COUNT_TYPE __exts_iter = 0, __array_offset = LY_ARRAY_COUNT(EXT_C); __exts_iter < LY_ARRAY_COUNT(EXTS_P); ++__exts_iter) { \
Radek Krejci0935f412019-08-20 16:15:18 +020099 LY_ARRAY_INCREMENT(EXT_C); \
Michal Vasko8d544252020-03-02 10:19:52 +0100100 RET = lys_compile_ext(CTX, &(EXTS_P)[__exts_iter], &(EXT_C)[__exts_iter + __array_offset], PARENT, PARENT_TYPE, NULL); \
Radek Krejci0935f412019-08-20 16:15:18 +0200101 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
102 } \
103 }
104
Radek Krejciec4da802019-05-02 13:02:41 +0200105#define COMPILE_ARRAY_UNIQUE_GOTO(CTX, ARRAY_P, ARRAY_C, ITER, FUNC, RET, GOTO) \
Radek Krejcid05cbd92018-12-05 14:26:40 +0100106 if (ARRAY_P) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200107 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, LY_ARRAY_COUNT(ARRAY_P), RET, GOTO); \
108 LY_ARRAY_COUNT_TYPE __array_offset = LY_ARRAY_COUNT(ARRAY_C); \
109 for (ITER = 0; ITER < LY_ARRAY_COUNT(ARRAY_P); ++ITER) { \
Radek Krejcid05cbd92018-12-05 14:26:40 +0100110 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejciec4da802019-05-02 13:02:41 +0200111 RET = FUNC(CTX, &(ARRAY_P)[ITER], ARRAY_C, &(ARRAY_C)[ITER + __array_offset]); \
Radek Krejci19a96102018-11-15 13:38:09 +0100112 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
113 } \
114 }
115
Radek Krejciec4da802019-05-02 13:02:41 +0200116#define COMPILE_MEMBER_GOTO(CTX, MEMBER_P, MEMBER_C, FUNC, RET, GOTO) \
Radek Krejci19a96102018-11-15 13:38:09 +0100117 if (MEMBER_P) { \
118 MEMBER_C = calloc(1, sizeof *(MEMBER_C)); \
119 LY_CHECK_ERR_GOTO(!(MEMBER_C), LOGMEM((CTX)->ctx); RET = LY_EMEM, GOTO); \
Radek Krejciec4da802019-05-02 13:02:41 +0200120 RET = FUNC(CTX, MEMBER_P, MEMBER_C); \
Radek Krejci19a96102018-11-15 13:38:09 +0100121 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
122 }
123
Radek Krejciec4da802019-05-02 13:02:41 +0200124#define COMPILE_MEMBER_ARRAY_GOTO(CTX, MEMBER_P, ARRAY_C, FUNC, RET, GOTO) \
Radek Krejci00b874b2019-02-12 10:54:50 +0100125 if (MEMBER_P) { \
126 LY_ARRAY_CREATE_GOTO((CTX)->ctx, ARRAY_C, 1, RET, GOTO); \
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200127 LY_ARRAY_COUNT_TYPE __array_offset = LY_ARRAY_COUNT(ARRAY_C); \
Radek Krejci00b874b2019-02-12 10:54:50 +0100128 LY_ARRAY_INCREMENT(ARRAY_C); \
Radek Krejciec4da802019-05-02 13:02:41 +0200129 RET = FUNC(CTX, MEMBER_P, &(ARRAY_C)[__array_offset]); \
Radek Krejci00b874b2019-02-12 10:54:50 +0100130 LY_CHECK_GOTO(RET != LY_SUCCESS, GOTO); \
131 }
132
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100133#define COMPILE_CHECK_UNIQUENESS_ARRAY(CTX, ARRAY, MEMBER, EXCL, STMT, IDENT) \
Radek Krejcid05cbd92018-12-05 14:26:40 +0100134 if (ARRAY) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200135 for (LY_ARRAY_COUNT_TYPE u__ = 0; u__ < LY_ARRAY_COUNT(ARRAY); ++u__) { \
Radek Krejci0af46292019-01-11 16:02:31 +0100136 if (&(ARRAY)[u__] != EXCL && (void*)((ARRAY)[u__].MEMBER) == (void*)(IDENT)) { \
Radek Krejcid05cbd92018-12-05 14:26:40 +0100137 LOGVAL((CTX)->ctx, LY_VLOG_STR, (CTX)->path, LY_VCODE_DUPIDENT, IDENT, STMT); \
138 return LY_EVALID; \
139 } \
140 } \
141 }
142
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100143#define COMPILE_CHECK_UNIQUENESS_PARRAY(CTX, ARRAY, MEMBER, EXCL, STMT, IDENT) \
144 if (ARRAY) { \
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200145 for (LY_ARRAY_COUNT_TYPE u__ = 0; u__ < LY_ARRAY_COUNT(ARRAY); ++u__) { \
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100146 if (&(ARRAY)[u__] != EXCL && (void*)((ARRAY)[u__]->MEMBER) == (void*)(IDENT)) { \
147 LOGVAL((CTX)->ctx, LY_VLOG_STR, (CTX)->path, LY_VCODE_DUPIDENT, IDENT, STMT); \
148 return LY_EVALID; \
149 } \
150 } \
151 }
152
153struct lysc_ext *
154lysc_ext_dup(struct lysc_ext *orig)
155{
156 ++orig->refcount;
157 return orig;
158}
159
Radek Krejci19a96102018-11-15 13:38:09 +0100160static struct lysc_ext_instance *
161lysc_ext_instance_dup(struct ly_ctx *ctx, struct lysc_ext_instance *orig)
162{
Michal Vasko6f4cbb62020-02-28 11:15:47 +0100163 /* TODO - extensions, increase refcount */
Radek Krejci19a96102018-11-15 13:38:09 +0100164 (void) ctx;
165 (void) orig;
166 return NULL;
167}
168
Michal Vasko7f45cf22020-10-01 12:49:44 +0200169/**
170 * @brief Add/replace a leaf default value in unres.
171 * Can also be used for a single leaf-list default value.
172 *
173 * @param[in] ctx Compile context.
174 * @param[in] leaf Leaf with the default value.
175 * @param[in] dflt Default value to use.
176 * @return LY_ERR value.
177 */
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200178static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +0200179lysc_unres_leaf_dflt_add(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt)
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200180{
Michal Vasko7f45cf22020-10-01 12:49:44 +0200181 struct lysc_unres_dflt *r = NULL;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200182 uint32_t i;
183
184 for (i = 0; i < ctx->dflts.count; ++i) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200185 if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->leaf == leaf) {
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200186 /* just replace the default */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200187 r = ctx->dflts.objs[i];
188 lysp_qname_free(ctx->ctx, r->dflt);
189 free(r->dflt);
190 break;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200191 }
192 }
Michal Vasko7f45cf22020-10-01 12:49:44 +0200193 if (!r) {
194 /* add new unres item */
195 r = calloc(1, sizeof *r);
196 LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
197 r->leaf = leaf;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200198
Michal Vasko7f45cf22020-10-01 12:49:44 +0200199 LY_CHECK_RET(ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST, NULL));
200 }
201
202 r->dflt = malloc(sizeof *r->dflt);
Michal Vaskoaf702452020-10-02 09:02:55 +0200203 LY_CHECK_GOTO(!r->dflt, error);
204 LY_CHECK_GOTO(lysp_qname_dup(ctx->ctx, r->dflt, dflt), error);
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200205
206 return LY_SUCCESS;
Michal Vaskoaf702452020-10-02 09:02:55 +0200207
208error:
209 free(r->dflt);
210 LOGMEM(ctx->ctx);
211 return LY_EMEM;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200212}
213
Radek Krejcib56c7502019-02-13 14:19:54 +0100214/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200215 * @brief Add/replace a leaf-list default value(s) in unres.
216 *
217 * @param[in] ctx Compile context.
218 * @param[in] llist Leaf-list with the default value.
219 * @param[in] dflts Sized array of the default values.
220 * @return LY_ERR value.
Radek Krejci474f9b82019-07-24 11:36:37 +0200221 */
222static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +0200223lysc_unres_llist_dflts_add(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflts)
Radek Krejci474f9b82019-07-24 11:36:37 +0200224{
Michal Vasko7f45cf22020-10-01 12:49:44 +0200225 struct lysc_unres_dflt *r = NULL;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200226 uint32_t i;
227
228 for (i = 0; i < ctx->dflts.count; ++i) {
Michal Vasko7f45cf22020-10-01 12:49:44 +0200229 if (((struct lysc_unres_dflt *)ctx->dflts.objs[i])->llist == llist) {
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200230 /* just replace the defaults */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200231 r = ctx->dflts.objs[i];
232 lysp_qname_free(ctx->ctx, r->dflt);
233 free(r->dflt);
234 r->dflt = NULL;
235 FREE_ARRAY(ctx->ctx, r->dflts, lysp_qname_free);
236 r->dflts = NULL;
237 break;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200238 }
239 }
Michal Vasko7f45cf22020-10-01 12:49:44 +0200240 if (!r) {
241 r = calloc(1, sizeof *r);
242 LY_CHECK_ERR_RET(!r, LOGMEM(ctx->ctx), LY_EMEM);
243 r->llist = llist;
Michal Vaskoba99a3e2020-08-18 15:50:05 +0200244
Michal Vasko7f45cf22020-10-01 12:49:44 +0200245 LY_CHECK_RET(ly_set_add(&ctx->dflts, r, LY_SET_OPT_USEASLIST, NULL));
246 }
247
248 DUP_ARRAY(ctx->ctx, dflts, r->dflts, lysp_qname_dup);
Radek Krejci474f9b82019-07-24 11:36:37 +0200249
250 return LY_SUCCESS;
251}
252
Radek Krejci474f9b82019-07-24 11:36:37 +0200253static void
Michal Vasko7f45cf22020-10-01 12:49:44 +0200254lysc_unres_dflt_free(const struct ly_ctx *ctx, struct lysc_unres_dflt *r)
Radek Krejci474f9b82019-07-24 11:36:37 +0200255{
Michal Vasko7f45cf22020-10-01 12:49:44 +0200256 assert(!r->dflt || !r->dflts);
257 if (r->dflt) {
258 lysp_qname_free((struct ly_ctx *)ctx, r->dflt);
259 free(r->dflt);
260 } else {
261 FREE_ARRAY((struct ly_ctx *)ctx, r->dflts, lysp_qname_free);
Radek Krejci474f9b82019-07-24 11:36:37 +0200262 }
Michal Vasko7f45cf22020-10-01 12:49:44 +0200263 free(r);
Radek Krejci474f9b82019-07-24 11:36:37 +0200264}
265
Radek Krejci0e59c312019-08-15 15:34:15 +0200266void
Radek Krejci327de162019-06-14 12:52:07 +0200267lysc_update_path(struct lysc_ctx *ctx, struct lysc_node *parent, const char *name)
268{
269 int len;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200270 uint8_t nextlevel = 0; /* 0 - no starttag, 1 - '/' starttag, 2 - '=' starttag + '}' endtag */
Radek Krejci327de162019-06-14 12:52:07 +0200271
272 if (!name) {
273 /* removing last path segment */
274 if (ctx->path[ctx->path_len - 1] == '}') {
Michal Vaskod989ba02020-08-24 10:59:24 +0200275 for ( ; ctx->path[ctx->path_len] != '=' && ctx->path[ctx->path_len] != '{'; --ctx->path_len) {}
Radek Krejci327de162019-06-14 12:52:07 +0200276 if (ctx->path[ctx->path_len] == '=') {
277 ctx->path[ctx->path_len++] = '}';
278 } else {
279 /* not a top-level special tag, remove also preceiding '/' */
280 goto remove_nodelevel;
281 }
282 } else {
283remove_nodelevel:
Michal Vaskod989ba02020-08-24 10:59:24 +0200284 for ( ; ctx->path[ctx->path_len] != '/'; --ctx->path_len) {}
Radek Krejci327de162019-06-14 12:52:07 +0200285 if (ctx->path_len == 0) {
286 /* top-level (last segment) */
Radek Krejciacc79042019-07-25 14:14:57 +0200287 ctx->path_len = 1;
Radek Krejci327de162019-06-14 12:52:07 +0200288 }
289 }
290 /* set new terminating NULL-byte */
291 ctx->path[ctx->path_len] = '\0';
292 } else {
293 if (ctx->path_len > 1) {
Michal Vasko69730152020-10-09 16:30:07 +0200294 if (!parent && (ctx->path[ctx->path_len - 1] == '}') && (ctx->path[ctx->path_len - 2] != '\'')) {
Radek Krejci327de162019-06-14 12:52:07 +0200295 /* extension of the special tag */
296 nextlevel = 2;
297 --ctx->path_len;
298 } else {
299 /* there is already some path, so add next level */
300 nextlevel = 1;
301 }
302 } /* else the path is just initiated with '/', so do not add additional slash in case of top-level nodes */
303
304 if (nextlevel != 2) {
Michal Vasko69730152020-10-09 16:30:07 +0200305 if ((parent && (parent->module == ctx->mod)) || (!parent && (ctx->path_len > 1) && (name[0] == '{'))) {
Radek Krejci327de162019-06-14 12:52:07 +0200306 /* module not changed, print the name unprefixed */
Radek Krejci70ee9152019-07-25 11:27:27 +0200307 len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "%s%s", nextlevel ? "/" : "", name);
Radek Krejci327de162019-06-14 12:52:07 +0200308 } else {
Radek Krejci70ee9152019-07-25 11:27:27 +0200309 len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "%s%s:%s", nextlevel ? "/" : "", ctx->mod->name, name);
Radek Krejci327de162019-06-14 12:52:07 +0200310 }
311 } else {
Radek Krejci70ee9152019-07-25 11:27:27 +0200312 len = snprintf(&ctx->path[ctx->path_len], LYSC_CTX_BUFSIZE - ctx->path_len, "='%s'}", name);
Radek Krejci327de162019-06-14 12:52:07 +0200313 }
Radek Krejci1deb5be2020-08-26 16:43:36 +0200314 if (len >= LYSC_CTX_BUFSIZE - (int)ctx->path_len) {
Radek Krejciacc79042019-07-25 14:14:57 +0200315 /* output truncated */
316 ctx->path_len = LYSC_CTX_BUFSIZE - 1;
317 } else {
318 ctx->path_len += len;
319 }
Radek Krejci327de162019-06-14 12:52:07 +0200320 }
321}
322
323/**
Radek Krejcib56c7502019-02-13 14:19:54 +0100324 * @brief Duplicate the compiled pattern structure.
325 *
326 * Instead of duplicating memory, the reference counter in the @p orig is increased.
327 *
328 * @param[in] orig The pattern structure to duplicate.
329 * @return The duplicated structure to use.
330 */
Michal Vasko22df3f02020-08-24 13:29:22 +0200331static struct lysc_pattern *
Radek Krejci19a96102018-11-15 13:38:09 +0100332lysc_pattern_dup(struct lysc_pattern *orig)
333{
334 ++orig->refcount;
335 return orig;
336}
337
Radek Krejcib56c7502019-02-13 14:19:54 +0100338/**
339 * @brief Duplicate the array of compiled patterns.
340 *
341 * The sized array itself is duplicated, but the pattern structures are just shadowed by increasing their reference counter.
342 *
343 * @param[in] ctx Libyang context for logging.
344 * @param[in] orig The patterns sized array to duplicate.
345 * @return New sized array as a copy of @p orig.
346 * @return NULL in case of memory allocation error.
347 */
Michal Vasko22df3f02020-08-24 13:29:22 +0200348static struct lysc_pattern **
Radek Krejci19a96102018-11-15 13:38:09 +0100349lysc_patterns_dup(struct ly_ctx *ctx, struct lysc_pattern **orig)
350{
Radek Krejcid05cbd92018-12-05 14:26:40 +0100351 struct lysc_pattern **dup = NULL;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200352 LY_ARRAY_COUNT_TYPE u;
Radek Krejci19a96102018-11-15 13:38:09 +0100353
Radek Krejcib56c7502019-02-13 14:19:54 +0100354 assert(orig);
355
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200356 LY_ARRAY_CREATE_RET(ctx, dup, LY_ARRAY_COUNT(orig), NULL);
Radek Krejci19a96102018-11-15 13:38:09 +0100357 LY_ARRAY_FOR(orig, u) {
358 dup[u] = lysc_pattern_dup(orig[u]);
359 LY_ARRAY_INCREMENT(dup);
360 }
361 return dup;
362}
363
Radek Krejcib56c7502019-02-13 14:19:54 +0100364/**
365 * @brief Duplicate compiled range structure.
366 *
367 * @param[in] ctx Libyang context for logging.
368 * @param[in] orig The range structure to be duplicated.
369 * @return New compiled range structure as a copy of @p orig.
370 * @return NULL in case of memory allocation error.
371 */
Michal Vasko22df3f02020-08-24 13:29:22 +0200372struct lysc_range *
Radek Krejci19a96102018-11-15 13:38:09 +0100373lysc_range_dup(struct ly_ctx *ctx, const struct lysc_range *orig)
374{
375 struct lysc_range *dup;
376 LY_ERR ret;
377
Radek Krejcib56c7502019-02-13 14:19:54 +0100378 assert(orig);
379
Radek Krejci19a96102018-11-15 13:38:09 +0100380 dup = calloc(1, sizeof *dup);
381 LY_CHECK_ERR_RET(!dup, LOGMEM(ctx), NULL);
382 if (orig->parts) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200383 LY_ARRAY_CREATE_GOTO(ctx, dup->parts, LY_ARRAY_COUNT(orig->parts), ret, cleanup);
384 LY_ARRAY_COUNT(dup->parts) = LY_ARRAY_COUNT(orig->parts);
385 memcpy(dup->parts, orig->parts, LY_ARRAY_COUNT(dup->parts) * sizeof *dup->parts);
Radek Krejci19a96102018-11-15 13:38:09 +0100386 }
Radek Krejci011e4aa2020-09-04 15:22:31 +0200387 DUP_STRING_GOTO(ctx, orig->eapptag, dup->eapptag, ret, cleanup);
388 DUP_STRING_GOTO(ctx, orig->emsg, dup->emsg, ret, cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +0100389 dup->exts = lysc_ext_instance_dup(ctx, orig->exts);
390
391 return dup;
392cleanup:
393 free(dup);
394 (void) ret; /* set but not used due to the return type */
395 return NULL;
396}
397
Radek Krejcib56c7502019-02-13 14:19:54 +0100398/**
399 * @brief Stack for processing if-feature expressions.
400 */
Radek Krejci19a96102018-11-15 13:38:09 +0100401struct iff_stack {
Radek Krejci1deb5be2020-08-26 16:43:36 +0200402 size_t size; /**< number of items in the stack */
403 size_t index; /**< first empty item */
404 uint8_t *stack; /**< stack - array of @ref ifftokens to create the if-feature expression in prefix format */
Radek Krejci19a96102018-11-15 13:38:09 +0100405};
406
Radek Krejcib56c7502019-02-13 14:19:54 +0100407/**
408 * @brief Add @ref ifftokens into the stack.
409 * @param[in] stack The if-feature stack to use.
410 * @param[in] value One of the @ref ifftokens to store in the stack.
411 * @return LY_EMEM in case of memory allocation error
412 * @return LY_ESUCCESS if the value successfully stored.
413 */
Radek Krejci19a96102018-11-15 13:38:09 +0100414static LY_ERR
415iff_stack_push(struct iff_stack *stack, uint8_t value)
416{
417 if (stack->index == stack->size) {
418 stack->size += 4;
419 stack->stack = ly_realloc(stack->stack, stack->size * sizeof *stack->stack);
420 LY_CHECK_ERR_RET(!stack->stack, LOGMEM(NULL); stack->size = 0, LY_EMEM);
421 }
422 stack->stack[stack->index++] = value;
423 return LY_SUCCESS;
424}
425
Radek Krejcib56c7502019-02-13 14:19:54 +0100426/**
427 * @brief Get (and remove) the last item form the stack.
428 * @param[in] stack The if-feature stack to use.
429 * @return The value from the top of the stack.
430 */
Radek Krejci19a96102018-11-15 13:38:09 +0100431static uint8_t
432iff_stack_pop(struct iff_stack *stack)
433{
Radek Krejcib56c7502019-02-13 14:19:54 +0100434 assert(stack && stack->index);
435
Radek Krejci19a96102018-11-15 13:38:09 +0100436 stack->index--;
437 return stack->stack[stack->index];
438}
439
Radek Krejcib56c7502019-02-13 14:19:54 +0100440/**
441 * @brief Clean up the stack.
442 * @param[in] stack The if-feature stack to use.
443 */
Radek Krejci19a96102018-11-15 13:38:09 +0100444static void
445iff_stack_clean(struct iff_stack *stack)
446{
447 stack->size = 0;
448 free(stack->stack);
449}
450
Radek Krejcib56c7502019-02-13 14:19:54 +0100451/**
452 * @brief Store the @ref ifftokens (@p op) on the given position in the 2bits array
453 * (libyang format of the if-feature expression).
454 * @param[in,out] list The 2bits array to modify.
455 * @param[in] op The operand (@ref ifftokens) to store.
456 * @param[in] pos Position (0-based) where to store the given @p op.
457 */
Radek Krejci19a96102018-11-15 13:38:09 +0100458static void
Radek Krejci1deb5be2020-08-26 16:43:36 +0200459iff_setop(uint8_t *list, uint8_t op, size_t pos)
Radek Krejci19a96102018-11-15 13:38:09 +0100460{
461 uint8_t *item;
462 uint8_t mask = 3;
463
Radek Krejci19a96102018-11-15 13:38:09 +0100464 assert(op <= 3); /* max 2 bits */
465
466 item = &list[pos / 4];
467 mask = mask << 2 * (pos % 4);
468 *item = (*item) & ~mask;
469 *item = (*item) | (op << 2 * (pos % 4));
470}
471
Radek Krejcib56c7502019-02-13 14:19:54 +0100472#define LYS_IFF_LP 0x04 /**< Additional, temporary, value of @ref ifftokens: ( */
473#define LYS_IFF_RP 0x08 /**< Additional, temporary, value of @ref ifftokens: ) */
Radek Krejci19a96102018-11-15 13:38:09 +0100474
Radek Krejci0af46292019-01-11 16:02:31 +0100475/**
476 * @brief Find a feature of the given name and referenced in the given module.
477 *
478 * If the compiled schema is available (the schema is implemented), the feature from the compiled schema is
479 * returned. Otherwise, the special array of pre-compiled features is used to search for the feature. Such
480 * features are always disabled (feature from not implemented schema cannot be enabled), but in case the schema
481 * will be made implemented in future (no matter if implicitly via augmenting/deviating it or explicitly via
482 * ly_ctx_module_implement()), the compilation of these feature structure is finished, but the pointers
483 * assigned till that time will be still valid.
484 *
485 * @param[in] mod Module where the feature was referenced (used to resolve prefix of the feature).
486 * @param[in] name Name of the feature including possible prefix.
487 * @param[in] len Length of the string representing the feature identifier in the name variable (mandatory!).
488 * @return Pointer to the feature structure if found, NULL otherwise.
489 */
Radek Krejci19a96102018-11-15 13:38:09 +0100490static struct lysc_feature *
Michal Vasko7f45cf22020-10-01 12:49:44 +0200491lys_feature_find(const struct lys_module *mod, const char *name, size_t len)
Radek Krejci19a96102018-11-15 13:38:09 +0100492{
493 size_t i;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200494 LY_ARRAY_COUNT_TYPE u;
Radek Krejci14915cc2020-09-14 17:28:13 +0200495 struct lysc_feature *f;
Radek Krejci19a96102018-11-15 13:38:09 +0100496
Radek Krejci120d8542020-08-12 09:29:16 +0200497 assert(mod);
498
Radek Krejci19a96102018-11-15 13:38:09 +0100499 for (i = 0; i < len; ++i) {
500 if (name[i] == ':') {
501 /* we have a prefixed feature */
Radek Krejci0af46292019-01-11 16:02:31 +0100502 mod = lys_module_find_prefix(mod, name, i);
Radek Krejci19a96102018-11-15 13:38:09 +0100503 LY_CHECK_RET(!mod, NULL);
504
505 name = &name[i + 1];
506 len = len - i - 1;
507 }
508 }
509
510 /* we have the correct module, get the feature */
Radek Krejci14915cc2020-09-14 17:28:13 +0200511 LY_ARRAY_FOR(mod->features, u) {
512 f = &mod->features[u];
Radek Krejci7f9b6512019-09-18 13:11:09 +0200513 if (!ly_strncmp(f->name, name, len)) {
Radek Krejci19a96102018-11-15 13:38:09 +0100514 return f;
515 }
516 }
517
518 return NULL;
519}
520
Michal Vasko8d544252020-03-02 10:19:52 +0100521/**
Michal Vasko5fe75f12020-03-02 13:52:37 +0100522 * @brief Fill in the prepared compiled extensions definition structure according to the parsed extension definition.
523 */
524static LY_ERR
525lys_compile_extension(struct lysc_ctx *ctx, const struct lys_module *ext_mod, struct lysp_ext *ext_p, struct lysc_ext **ext)
526{
527 LY_ERR ret = LY_SUCCESS;
528
529 if (!ext_p->compiled) {
530 lysc_update_path(ctx, NULL, "{extension}");
531 lysc_update_path(ctx, NULL, ext_p->name);
532
533 /* compile the extension definition */
534 ext_p->compiled = calloc(1, sizeof **ext);
535 ext_p->compiled->refcount = 1;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200536 DUP_STRING_GOTO(ctx->ctx, ext_p->name, ext_p->compiled->name, ret, done);
537 DUP_STRING_GOTO(ctx->ctx, ext_p->argument, ext_p->compiled->argument, ret, done);
Michal Vasko5fe75f12020-03-02 13:52:37 +0100538 ext_p->compiled->module = (struct lys_module *)ext_mod;
539 COMPILE_EXTS_GOTO(ctx, ext_p->exts, ext_p->compiled->exts, *ext, LYEXT_PAR_EXT, ret, done);
540
541 lysc_update_path(ctx, NULL, NULL);
542 lysc_update_path(ctx, NULL, NULL);
543
544 /* find extension definition plugin */
545 ext_p->compiled->plugin = lyext_get_plugin(ext_p->compiled);
546 }
547
548 *ext = lysc_ext_dup(ext_p->compiled);
549
550done:
551 return ret;
552}
553
554/**
Michal Vasko8d544252020-03-02 10:19:52 +0100555 * @brief Fill in the prepared compiled extension instance structure according to the parsed extension instance.
556 *
557 * @param[in] ctx Compilation context.
558 * @param[in] ext_p Parsed extension instance.
559 * @param[in,out] ext Prepared compiled extension instance.
560 * @param[in] parent Extension instance parent.
561 * @param[in] parent_type Extension instance parent type.
562 * @param[in] ext_mod Optional module with the extension instance extension definition, set only for internal annotations.
563 */
Radek Krejci19a96102018-11-15 13:38:09 +0100564static LY_ERR
Michal Vasko8d544252020-03-02 10:19:52 +0100565lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext, void *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200566 LYEXT_PARENT parent_type, const struct lys_module *ext_mod)
Radek Krejci19a96102018-11-15 13:38:09 +0100567{
Radek Krejci011e4aa2020-09-04 15:22:31 +0200568 LY_ERR ret = LY_SUCCESS;
Radek Krejci19a96102018-11-15 13:38:09 +0100569 const char *name;
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200570 size_t u;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200571 LY_ARRAY_COUNT_TYPE v;
Radek Krejci7c960162019-09-18 14:16:12 +0200572 const char *prefixed_name = NULL;
Radek Krejci19a96102018-11-15 13:38:09 +0100573
Radek Krejci011e4aa2020-09-04 15:22:31 +0200574 DUP_STRING(ctx->ctx, ext_p->argument, ext->argument, ret);
575 LY_CHECK_RET(ret);
576
Radek Krejci19a96102018-11-15 13:38:09 +0100577 ext->insubstmt = ext_p->insubstmt;
578 ext->insubstmt_index = ext_p->insubstmt_index;
Michal Vasko8ce51352020-10-06 14:07:24 +0200579 ext->module = ctx->mod;
Radek Krejci0935f412019-08-20 16:15:18 +0200580 ext->parent = parent;
581 ext->parent_type = parent_type;
Radek Krejci19a96102018-11-15 13:38:09 +0100582
Michal Vasko22df3f02020-08-24 13:29:22 +0200583 lysc_update_path(ctx, ext->parent_type == LYEXT_PAR_NODE ? (struct lysc_node *)ext->parent : NULL, "{extension}");
Radek Krejcif56e2a42019-09-09 14:15:25 +0200584
Radek Krejci19a96102018-11-15 13:38:09 +0100585 /* get module where the extension definition should be placed */
Radek Krejci1e008d22020-08-17 11:37:37 +0200586 for (u = strlen(ext_p->name); u && ext_p->name[u - 1] != ':'; --u) {}
Radek Krejci7c960162019-09-18 14:16:12 +0200587 if (ext_p->yin) {
588 /* YIN parser has to replace prefixes by the namespace - XML namespace/prefix pairs may differs form the YANG schema's
589 * namespace/prefix pair. YIN parser does not have the imports available, so mapping from XML namespace to the
590 * YANG (import) prefix must be done here. */
591 if (!ly_strncmp(ctx->mod_def->ns, ext_p->name, u - 1)) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200592 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, &ext_p->name[u], 0, &prefixed_name), cleanup);
Radek Krejci7c960162019-09-18 14:16:12 +0200593 u = 0;
Michal Vasko7c8439f2020-08-05 13:25:19 +0200594 } else {
595 assert(ctx->mod_def->parsed);
596 LY_ARRAY_FOR(ctx->mod_def->parsed->imports, v) {
597 if (!ly_strncmp(ctx->mod_def->parsed->imports[v].module->ns, ext_p->name, u - 1)) {
Radek Krejci7c960162019-09-18 14:16:12 +0200598 char *s;
Michal Vasko7c8439f2020-08-05 13:25:19 +0200599 LY_CHECK_ERR_GOTO(asprintf(&s, "%s:%s", ctx->mod_def->parsed->imports[v].prefix, &ext_p->name[u]) == -1,
Michal Vasko69730152020-10-09 16:30:07 +0200600 ret = LY_EMEM, cleanup);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200601 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->ctx, s, &prefixed_name), cleanup);
Michal Vasko7c8439f2020-08-05 13:25:19 +0200602 u = strlen(ctx->mod_def->parsed->imports[v].prefix) + 1; /* add semicolon */
Radek Krejci7c960162019-09-18 14:16:12 +0200603 break;
604 }
605 }
606 }
607 if (!prefixed_name) {
608 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +0200609 "Invalid XML prefix of \"%.*s\" namespace used for extension instance identifier.", u, ext_p->name);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200610 ret = LY_EVALID;
Radek Krejci7c960162019-09-18 14:16:12 +0200611 goto cleanup;
612 }
613 } else {
614 prefixed_name = ext_p->name;
615 }
616 lysc_update_path(ctx, NULL, prefixed_name);
617
Michal Vasko8d544252020-03-02 10:19:52 +0100618 if (!ext_mod) {
Radek Krejci63f55512020-05-20 14:37:18 +0200619 ext_mod = u ? lys_module_find_prefix(ctx->mod_def, prefixed_name, u - 1) : ctx->mod_def;
Michal Vasko8d544252020-03-02 10:19:52 +0100620 if (!ext_mod) {
621 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +0200622 "Invalid prefix \"%.*s\" used for extension instance identifier.", u, prefixed_name);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200623 ret = LY_EVALID;
Michal Vasko8d544252020-03-02 10:19:52 +0100624 goto cleanup;
625 } else if (!ext_mod->parsed->extensions) {
626 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
627 "Extension instance \"%s\" refers \"%s\" module that does not contain extension definitions.",
628 prefixed_name, ext_mod->name);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200629 ret = LY_EVALID;
Michal Vasko8d544252020-03-02 10:19:52 +0100630 goto cleanup;
631 }
Radek Krejci7c960162019-09-18 14:16:12 +0200632 }
633 name = &prefixed_name[u];
Radek Krejci0935f412019-08-20 16:15:18 +0200634
Michal Vasko5fe75f12020-03-02 13:52:37 +0100635 /* find the parsed extension definition there */
Radek Krejci7eb54ba2020-05-18 16:30:04 +0200636 LY_ARRAY_FOR(ext_mod->parsed->extensions, v) {
637 if (!strcmp(name, ext_mod->parsed->extensions[v].name)) {
Michal Vasko5fe75f12020-03-02 13:52:37 +0100638 /* compile extension definition and assign it */
Radek Krejci011e4aa2020-09-04 15:22:31 +0200639 LY_CHECK_GOTO(ret = lys_compile_extension(ctx, ext_mod, &ext_mod->parsed->extensions[v], &ext->def), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +0100640 break;
641 }
642 }
Radek Krejci7c960162019-09-18 14:16:12 +0200643 if (!ext->def) {
644 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +0200645 "Extension definition of extension instance \"%s\" not found.", prefixed_name);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200646 ret = LY_EVALID;
Radek Krejci7c960162019-09-18 14:16:12 +0200647 goto cleanup;
648 }
Radek Krejci0935f412019-08-20 16:15:18 +0200649
Radek Krejcif56e2a42019-09-09 14:15:25 +0200650 /* unify the parsed extension from YIN and YANG sources. Without extension definition, it is not possible
651 * to get extension's argument from YIN source, so it is stored as one of the substatements. Here we have
652 * to find it, mark it with LYS_YIN_ARGUMENT and store it in the compiled structure. */
Radek Krejci7c960162019-09-18 14:16:12 +0200653 if (ext_p->yin && ext->def->argument && !ext->argument) {
Radek Krejcif56e2a42019-09-09 14:15:25 +0200654 /* Schema was parsed from YIN and an argument is expected, ... */
655 struct lysp_stmt *stmt = NULL;
656
657 if (ext->def->flags & LYS_YINELEM_TRUE) {
658 /* ... argument was the first XML child element */
659 if (ext_p->child && !(ext_p->child->flags & LYS_YIN_ATTR)) {
660 /* TODO check namespace of the statement */
661 if (!strcmp(ext_p->child->stmt, ext->def->argument)) {
662 stmt = ext_p->child;
663 }
664 }
665 } else {
666 /* ... argument was one of the XML attributes which are represented as child stmt
667 * with LYS_YIN_ATTR flag */
668 for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) {
669 if (!strcmp(stmt->stmt, ext->def->argument)) {
670 /* this is the extension's argument */
Radek Krejcif56e2a42019-09-09 14:15:25 +0200671 break;
672 }
673 }
674 }
675 if (!stmt) {
676 /* missing extension's argument */
677 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +0200678 "Extension instance \"%s\" misses argument \"%s\".", prefixed_name, ext->def->argument);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200679 ret = LY_EVALID;
Radek Krejci7c960162019-09-18 14:16:12 +0200680 goto cleanup;
Radek Krejcif56e2a42019-09-09 14:15:25 +0200681
682 }
Radek Krejci011e4aa2020-09-04 15:22:31 +0200683 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, stmt->arg, 0, &ext->argument), cleanup);
Radek Krejcif56e2a42019-09-09 14:15:25 +0200684 stmt->flags |= LYS_YIN_ARGUMENT;
685 }
Radek Krejci7c960162019-09-18 14:16:12 +0200686 if (prefixed_name != ext_p->name) {
687 lydict_remove(ctx->ctx, ext_p->name);
688 ext_p->name = prefixed_name;
689 if (!ext_p->argument && ext->argument) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200690 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, ext->argument, 0, &ext_p->argument), cleanup);
Radek Krejci7c960162019-09-18 14:16:12 +0200691 }
692 }
Radek Krejcif56e2a42019-09-09 14:15:25 +0200693
Radek Krejci0935f412019-08-20 16:15:18 +0200694 if (ext->def->plugin && ext->def->plugin->compile) {
Radek Krejciad5963b2019-09-06 16:03:05 +0200695 if (ext->argument) {
Michal Vasko22df3f02020-08-24 13:29:22 +0200696 lysc_update_path(ctx, (struct lysc_node *)ext, ext->argument);
Radek Krejciad5963b2019-09-06 16:03:05 +0200697 }
Radek Krejci011e4aa2020-09-04 15:22:31 +0200698 LY_CHECK_GOTO(ret = ext->def->plugin->compile(ctx, ext_p, ext), cleanup);
Radek Krejciad5963b2019-09-06 16:03:05 +0200699 if (ext->argument) {
700 lysc_update_path(ctx, NULL, NULL);
701 }
Radek Krejci0935f412019-08-20 16:15:18 +0200702 }
Radek Krejcif56e2a42019-09-09 14:15:25 +0200703 ext_p->compiled = ext;
704
Radek Krejci7c960162019-09-18 14:16:12 +0200705cleanup:
Michal Vasko69730152020-10-09 16:30:07 +0200706 if (prefixed_name && (prefixed_name != ext_p->name)) {
Radek Krejci7c960162019-09-18 14:16:12 +0200707 lydict_remove(ctx->ctx, prefixed_name);
708 }
709
Radek Krejcif56e2a42019-09-09 14:15:25 +0200710 lysc_update_path(ctx, NULL, NULL);
711 lysc_update_path(ctx, NULL, NULL);
Radek Krejci0935f412019-08-20 16:15:18 +0200712
Radek Krejci7c960162019-09-18 14:16:12 +0200713 return ret;
Radek Krejci0935f412019-08-20 16:15:18 +0200714}
715
716/**
Radek Krejcib56c7502019-02-13 14:19:54 +0100717 * @brief Compile information from the if-feature statement
718 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +0200719 * @param[in] qname The if-feature argument to process. It is pointer-to-qname just to unify the compile functions.
Radek Krejcib56c7502019-02-13 14:19:54 +0100720 * @param[in,out] iff Prepared (empty) compiled if-feature structure to fill.
721 * @return LY_ERR value.
722 */
Radek Krejci19a96102018-11-15 13:38:09 +0100723static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +0200724lys_compile_iffeature(struct lysc_ctx *ctx, struct lysp_qname *qname, struct lysc_iffeature *iff)
Radek Krejci19a96102018-11-15 13:38:09 +0100725{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200726 LY_ERR rc = LY_SUCCESS;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200727 const char *c = qname->str;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200728 int64_t i, j;
729 int8_t op_len, last_not = 0, checkversion = 0;
730 LY_ARRAY_COUNT_TYPE f_size = 0, expr_size = 0, f_exp = 1;
Radek Krejci19a96102018-11-15 13:38:09 +0100731 uint8_t op;
732 struct iff_stack stack = {0, 0, NULL};
733 struct lysc_feature *f;
734
735 assert(c);
736
737 /* pre-parse the expression to get sizes for arrays, also do some syntax checks of the expression */
Radek Krejci1deb5be2020-08-26 16:43:36 +0200738 for (i = j = 0; c[i]; i++) {
Radek Krejci19a96102018-11-15 13:38:09 +0100739 if (c[i] == '(') {
740 j++;
741 checkversion = 1;
742 continue;
743 } else if (c[i] == ')') {
744 j--;
745 continue;
746 } else if (isspace(c[i])) {
747 checkversion = 1;
748 continue;
749 }
750
Radek Krejci1deb5be2020-08-26 16:43:36 +0200751 if (!strncmp(&c[i], "not", op_len = 3) || !strncmp(&c[i], "and", op_len = 3) || !strncmp(&c[i], "or", op_len = 2)) {
752 uint64_t spaces;
Michal Vasko2b7e5582020-10-07 12:31:23 +0200753 for (spaces = 0; c[i + op_len + spaces] && isspace(c[i + op_len + spaces]); spaces++) {}
Radek Krejci1deb5be2020-08-26 16:43:36 +0200754 if (c[i + op_len + spaces] == '\0') {
Radek Krejci19a96102018-11-15 13:38:09 +0100755 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +0200756 "Invalid value \"%s\" of if-feature - unexpected end of expression.", qname->str);
Radek Krejci19a96102018-11-15 13:38:09 +0100757 return LY_EVALID;
Radek Krejci1deb5be2020-08-26 16:43:36 +0200758 } else if (!isspace(c[i + op_len])) {
Radek Krejci19a96102018-11-15 13:38:09 +0100759 /* feature name starting with the not/and/or */
760 last_not = 0;
761 f_size++;
762 } else if (c[i] == 'n') { /* not operation */
763 if (last_not) {
764 /* double not */
765 expr_size = expr_size - 2;
766 last_not = 0;
767 } else {
768 last_not = 1;
769 }
770 } else { /* and, or */
Radek Krejci6788abc2019-06-14 13:56:49 +0200771 if (f_exp != f_size) {
772 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +0200773 "Invalid value \"%s\" of if-feature - missing feature/expression before \"%.*s\" operation.",
774 qname->str, op_len, &c[i]);
Radek Krejci6788abc2019-06-14 13:56:49 +0200775 return LY_EVALID;
776 }
Radek Krejci19a96102018-11-15 13:38:09 +0100777 f_exp++;
Radek Krejci6788abc2019-06-14 13:56:49 +0200778
Radek Krejci19a96102018-11-15 13:38:09 +0100779 /* not a not operation */
780 last_not = 0;
781 }
Radek Krejci1deb5be2020-08-26 16:43:36 +0200782 i += op_len;
Radek Krejci19a96102018-11-15 13:38:09 +0100783 } else {
784 f_size++;
785 last_not = 0;
786 }
787 expr_size++;
788
789 while (!isspace(c[i])) {
Michal Vasko69730152020-10-09 16:30:07 +0200790 if (!c[i] || (c[i] == ')') || (c[i] == '(')) {
Radek Krejci19a96102018-11-15 13:38:09 +0100791 i--;
792 break;
793 }
794 i++;
795 }
796 }
Radek Krejci6788abc2019-06-14 13:56:49 +0200797 if (j) {
Radek Krejci19a96102018-11-15 13:38:09 +0100798 /* not matching count of ( and ) */
799 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +0200800 "Invalid value \"%s\" of if-feature - non-matching opening and closing parentheses.", qname->str);
Radek Krejci19a96102018-11-15 13:38:09 +0100801 return LY_EVALID;
802 }
Radek Krejci6788abc2019-06-14 13:56:49 +0200803 if (f_exp != f_size) {
804 /* features do not match the needed arguments for the logical operations */
805 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +0200806 "Invalid value \"%s\" of if-feature - number of features in expression does not match "
807 "the required number of operands for the operations.", qname->str);
Radek Krejci6788abc2019-06-14 13:56:49 +0200808 return LY_EVALID;
809 }
Radek Krejci19a96102018-11-15 13:38:09 +0100810
Michal Vasko69730152020-10-09 16:30:07 +0200811 if (checkversion || (expr_size > 1)) {
Radek Krejci19a96102018-11-15 13:38:09 +0100812 /* check that we have 1.1 module */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200813 if (qname->mod->version != LYS_VERSION_1_1) {
Radek Krejci19a96102018-11-15 13:38:09 +0100814 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +0200815 "Invalid value \"%s\" of if-feature - YANG 1.1 expression in YANG 1.0 module.", qname->str);
Radek Krejci19a96102018-11-15 13:38:09 +0100816 return LY_EVALID;
817 }
818 }
819
820 /* allocate the memory */
821 LY_ARRAY_CREATE_RET(ctx->ctx, iff->features, f_size, LY_EMEM);
822 iff->expr = calloc((j = (expr_size / 4) + ((expr_size % 4) ? 1 : 0)), sizeof *iff->expr);
823 stack.stack = malloc(expr_size * sizeof *stack.stack);
Radek Krejci1deb5be2020-08-26 16:43:36 +0200824 LY_CHECK_ERR_GOTO(!stack.stack || !iff->expr, LOGMEM(ctx->ctx); rc = LY_EMEM, error);
Radek Krejci19a96102018-11-15 13:38:09 +0100825
826 stack.size = expr_size;
827 f_size--; expr_size--; /* used as indexes from now */
828
829 for (i--; i >= 0; i--) {
830 if (c[i] == ')') {
831 /* push it on stack */
832 iff_stack_push(&stack, LYS_IFF_RP);
833 continue;
834 } else if (c[i] == '(') {
835 /* pop from the stack into result all operators until ) */
Michal Vaskod989ba02020-08-24 10:59:24 +0200836 while ((op = iff_stack_pop(&stack)) != LYS_IFF_RP) {
Radek Krejci19a96102018-11-15 13:38:09 +0100837 iff_setop(iff->expr, op, expr_size--);
838 }
839 continue;
840 } else if (isspace(c[i])) {
841 continue;
842 }
843
844 /* end of operator or operand -> find beginning and get what is it */
845 j = i + 1;
846 while (i >= 0 && !isspace(c[i]) && c[i] != '(') {
847 i--;
848 }
849 i++; /* go back by one step */
850
851 if (!strncmp(&c[i], "not", 3) && isspace(c[i + 3])) {
Michal Vasko69730152020-10-09 16:30:07 +0200852 if (stack.index && (stack.stack[stack.index - 1] == LYS_IFF_NOT)) {
Radek Krejci19a96102018-11-15 13:38:09 +0100853 /* double not */
854 iff_stack_pop(&stack);
855 } else {
856 /* not has the highest priority, so do not pop from the stack
857 * as in case of AND and OR */
858 iff_stack_push(&stack, LYS_IFF_NOT);
859 }
860 } else if (!strncmp(&c[i], "and", 3) && isspace(c[i + 3])) {
861 /* as for OR - pop from the stack all operators with the same or higher
862 * priority and store them to the result, then push the AND to the stack */
863 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_AND) {
864 op = iff_stack_pop(&stack);
865 iff_setop(iff->expr, op, expr_size--);
866 }
867 iff_stack_push(&stack, LYS_IFF_AND);
868 } else if (!strncmp(&c[i], "or", 2) && isspace(c[i + 2])) {
869 while (stack.index && stack.stack[stack.index - 1] <= LYS_IFF_OR) {
870 op = iff_stack_pop(&stack);
871 iff_setop(iff->expr, op, expr_size--);
872 }
873 iff_stack_push(&stack, LYS_IFF_OR);
874 } else {
875 /* feature name, length is j - i */
876
877 /* add it to the expression */
878 iff_setop(iff->expr, LYS_IFF_F, expr_size--);
879
880 /* now get the link to the feature definition */
Michal Vasko7f45cf22020-10-01 12:49:44 +0200881 f = lys_feature_find(qname->mod, &c[i], j - i);
Radek Krejci0af46292019-01-11 16:02:31 +0100882 LY_CHECK_ERR_GOTO(!f, LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200883 "Invalid value \"%s\" of if-feature - unable to find feature \"%.*s\".", qname->str, j - i, &c[i]);
884 rc = LY_EVALID, error)
Radek Krejci19a96102018-11-15 13:38:09 +0100885 iff->features[f_size] = f;
886 LY_ARRAY_INCREMENT(iff->features);
887 f_size--;
888 }
889 }
890 while (stack.index) {
891 op = iff_stack_pop(&stack);
892 iff_setop(iff->expr, op, expr_size--);
893 }
894
895 if (++expr_size || ++f_size) {
896 /* not all expected operators and operands found */
897 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko7f45cf22020-10-01 12:49:44 +0200898 "Invalid value \"%s\" of if-feature - processing error.", qname->str);
Radek Krejci19a96102018-11-15 13:38:09 +0100899 rc = LY_EINT;
900 } else {
901 rc = LY_SUCCESS;
902 }
903
904error:
905 /* cleanup */
906 iff_stack_clean(&stack);
907
908 return rc;
909}
910
Radek Krejcib56c7502019-02-13 14:19:54 +0100911/**
Michal Vasko175012e2019-11-06 15:49:14 +0100912 * @brief Get the XPath context node for the given schema node.
913 * @param[in] start The schema node where the XPath expression appears.
914 * @return The context node to evaluate XPath expression in given schema node.
915 * @return NULL in case the context node is the root node.
916 */
917static struct lysc_node *
918lysc_xpath_context(struct lysc_node *start)
919{
Michal Vasko1bf09392020-03-27 12:38:10 +0100920 for (; start && !(start->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA | LYS_RPC | LYS_ACTION | LYS_NOTIF));
Radek Krejci1e008d22020-08-17 11:37:37 +0200921 start = start->parent) {}
Michal Vasko175012e2019-11-06 15:49:14 +0100922 return start;
923}
924
925/**
Radek Krejcib56c7502019-02-13 14:19:54 +0100926 * @brief Compile information from the when statement
Michal Vaskoceab6dd2020-10-09 16:53:36 +0200927 *
Radek Krejcib56c7502019-02-13 14:19:54 +0100928 * @param[in] ctx Compile context.
Michal Vaskoceab6dd2020-10-09 16:53:36 +0200929 * @param[in] when_p Parsed when structure.
930 * @param[in] flags Flags of the parsed node with the when statement.
931 * @param[in] ctx_node Context node for the when statement.
Radek Krejcib56c7502019-02-13 14:19:54 +0100932 * @param[out] when Pointer where to store pointer to the created compiled when structure.
933 * @return LY_ERR value.
934 */
Radek Krejci19a96102018-11-15 13:38:09 +0100935static LY_ERR
Michal Vaskoceab6dd2020-10-09 16:53:36 +0200936lys_compile_when_(struct lysc_ctx *ctx, struct lysp_when *when_p, uint16_t flags, const struct lysc_node *ctx_node,
937 struct lysc_when **when)
Radek Krejci19a96102018-11-15 13:38:09 +0100938{
Radek Krejci19a96102018-11-15 13:38:09 +0100939 LY_ERR ret = LY_SUCCESS;
940
Radek Krejci00b874b2019-02-12 10:54:50 +0100941 *when = calloc(1, sizeof **when);
Radek Krejcif03a9e22020-09-18 20:09:31 +0200942 LY_CHECK_ERR_RET(!(*when), LOGMEM(ctx->ctx), LY_EMEM);
Radek Krejci00b874b2019-02-12 10:54:50 +0100943 (*when)->refcount = 1;
Radek Krejcif03a9e22020-09-18 20:09:31 +0200944 LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, when_p->cond, 0, 1, &(*when)->cond));
Radek Krejcia0f704a2019-09-09 16:12:23 +0200945 (*when)->module = ctx->mod_def;
Michal Vaskoceab6dd2020-10-09 16:53:36 +0200946 (*when)->context = (struct lysc_node *)ctx_node;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200947 DUP_STRING_GOTO(ctx->ctx, when_p->dsc, (*when)->dsc, ret, done);
948 DUP_STRING_GOTO(ctx->ctx, when_p->ref, (*when)->ref, ret, done);
Radek Krejci0935f412019-08-20 16:15:18 +0200949 COMPILE_EXTS_GOTO(ctx, when_p->exts, (*when)->exts, (*when), LYEXT_PAR_WHEN, ret, done);
Michal Vasko175012e2019-11-06 15:49:14 +0100950 (*when)->flags = flags & LYS_STATUS_MASK;
Radek Krejci19a96102018-11-15 13:38:09 +0100951
952done:
953 return ret;
954}
955
Radek Krejcib56c7502019-02-13 14:19:54 +0100956/**
Michal Vaskoceab6dd2020-10-09 16:53:36 +0200957 * @brief Compile information from the when statement by either standard compilation or by reusing
958 * another compiled when structure.
959 *
960 * @param[in] ctx Compile context.
961 * @param[in] when_p Parsed when structure.
962 * @param[in] flags Flags of the parsed node with the when statement.
963 * @param[in] ctx_node Context node for the when statement.
964 * @param[in] node Compiled node to which add the compiled when.
965 * @param[in,out] when_c Optional, pointer to the previously compiled @p when_p to be reused. Set to NULL
966 * for the first call.
967 * @return LY_ERR value.
968 */
969static LY_ERR
970lys_compile_when(struct lysc_ctx *ctx, struct lysp_when *when_p, uint16_t flags, const struct lysc_node *ctx_node,
971 struct lysc_node *node, struct lysc_when **when_c)
972{
973 struct lysc_when **new_when, ***node_when;
974
975 assert(when_p);
976
977 /* get the when array */
978 if (node->nodetype & LYS_ACTION) {
979 node_when = &((struct lysc_action *)node)->when;
980 } else if (node->nodetype == LYS_NOTIF) {
981 node_when = &((struct lysc_notif *)node)->when;
982 } else {
983 node_when = &node->when;
984 }
985
986 /* create new when pointer */
987 LY_ARRAY_NEW_RET(ctx->ctx, *node_when, new_when, LY_EMEM);
988 if (!when_c || !(*when_c)) {
989 /* compile when */
990 LY_CHECK_RET(lys_compile_when_(ctx, when_p, flags, ctx_node, new_when));
991
992 if (!(ctx->options & LYSC_OPT_GROUPING)) {
993 /* do not check "when" semantics in a grouping */
994 LY_CHECK_RET(ly_set_add(&ctx->xpath, node, 0, NULL));
995 }
996
997 /* remember the compiled when for sharing */
998 if (when_c) {
999 *when_c = *new_when;
1000 }
1001 } else {
1002 /* use the previously compiled when */
1003 ++(*when_c)->refcount;
1004 *new_when = *when_c;
1005
1006 if (!(ctx->options & LYSC_OPT_GROUPING)) {
1007 /* in this case check "when" again for all children because of dummy node check */
1008 LY_CHECK_RET(ly_set_add(&ctx->xpath, node, 0, NULL));
1009 }
1010 }
1011
1012 return LY_SUCCESS;
1013}
1014
1015/**
Radek Krejcib56c7502019-02-13 14:19:54 +01001016 * @brief Compile information from the must statement
1017 * @param[in] ctx Compile context.
1018 * @param[in] must_p The parsed must statement structure.
Radek Krejcib56c7502019-02-13 14:19:54 +01001019 * @param[in,out] must Prepared (empty) compiled must structure to fill.
1020 * @return LY_ERR value.
1021 */
Radek Krejci19a96102018-11-15 13:38:09 +01001022static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02001023lys_compile_must(struct lysc_ctx *ctx, struct lysp_restr *must_p, struct lysc_must *must)
Radek Krejci19a96102018-11-15 13:38:09 +01001024{
Radek Krejci19a96102018-11-15 13:38:09 +01001025 LY_ERR ret = LY_SUCCESS;
1026
Michal Vasko7f45cf22020-10-01 12:49:44 +02001027 LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, must_p->arg.str, 0, 1, &must->cond));
1028 must->module = (struct lys_module *)must_p->arg.mod;
Radek Krejci011e4aa2020-09-04 15:22:31 +02001029 DUP_STRING_GOTO(ctx->ctx, must_p->eapptag, must->eapptag, ret, done);
1030 DUP_STRING_GOTO(ctx->ctx, must_p->emsg, must->emsg, ret, done);
1031 DUP_STRING_GOTO(ctx->ctx, must_p->dsc, must->dsc, ret, done);
1032 DUP_STRING_GOTO(ctx->ctx, must_p->ref, must->ref, ret, done);
Radek Krejci0935f412019-08-20 16:15:18 +02001033 COMPILE_EXTS_GOTO(ctx, must_p->exts, must->exts, must, LYEXT_PAR_MUST, ret, done);
Radek Krejci19a96102018-11-15 13:38:09 +01001034
1035done:
1036 return ret;
1037}
1038
Radek Krejcib56c7502019-02-13 14:19:54 +01001039/**
Michal Vasko7c8439f2020-08-05 13:25:19 +02001040 * @brief Compile information in the import statement - make sure there is the target module
Radek Krejcib56c7502019-02-13 14:19:54 +01001041 * @param[in] ctx Compile context.
Michal Vasko7c8439f2020-08-05 13:25:19 +02001042 * @param[in] imp_p The parsed import statement structure to fill the module to.
Radek Krejcib56c7502019-02-13 14:19:54 +01001043 * @return LY_ERR value.
1044 */
Radek Krejci19a96102018-11-15 13:38:09 +01001045static LY_ERR
Michal Vasko7c8439f2020-08-05 13:25:19 +02001046lys_compile_import(struct lysc_ctx *ctx, struct lysp_import *imp_p)
Radek Krejci19a96102018-11-15 13:38:09 +01001047{
Michal Vasko3a41dff2020-07-15 14:30:28 +02001048 const struct lys_module *mod = NULL;
Radek Krejci19a96102018-11-15 13:38:09 +01001049 LY_ERR ret = LY_SUCCESS;
1050
Radek Krejci7f2a5362018-11-28 13:05:37 +01001051 /* make sure that we have the parsed version (lysp_) of the imported module to import groupings or typedefs.
1052 * The compiled version is needed only for augments, deviates and leafrefs, so they are checked (and added,
Radek Krejci0e5d8382018-11-28 16:37:53 +01001053 * if needed) when these nodes are finally being instantiated and validated at the end of schema compilation. */
Michal Vasko7c8439f2020-08-05 13:25:19 +02001054 if (!imp_p->module->parsed) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01001055 /* try to use filepath if present */
Michal Vasko7c8439f2020-08-05 13:25:19 +02001056 if (imp_p->module->filepath) {
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001057 struct ly_in *in;
Michal Vasko7c8439f2020-08-05 13:25:19 +02001058 if (ly_in_new_filepath(imp_p->module->filepath, 0, &in)) {
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001059 LOGINT(ctx->ctx);
1060 } else {
Michal Vasko7c8439f2020-08-05 13:25:19 +02001061 LY_CHECK_RET(lys_parse(ctx->ctx, in, !strcmp(&imp_p->module->filepath[strlen(imp_p->module->filepath - 4)],
Michal Vasko69730152020-10-09 16:30:07 +02001062 ".yin") ? LYS_IN_YIN : LYS_IN_YANG, &mod));
Michal Vasko7c8439f2020-08-05 13:25:19 +02001063 if (mod != imp_p->module) {
Michal Vasko3a41dff2020-07-15 14:30:28 +02001064 LOGERR(ctx->ctx, LY_EINT, "Filepath \"%s\" of the module \"%s\" does not match.",
Michal Vasko69730152020-10-09 16:30:07 +02001065 imp_p->module->filepath, imp_p->module->name);
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001066 mod = NULL;
1067 }
Radek Krejci19a96102018-11-15 13:38:09 +01001068 }
Radek Krejcif0e1ba52020-05-22 15:14:35 +02001069 ly_in_free(in, 1);
Radek Krejci19a96102018-11-15 13:38:09 +01001070 }
1071 if (!mod) {
Michal Vasko7c8439f2020-08-05 13:25:19 +02001072 if (lysp_load_module(ctx->ctx, imp_p->module->name, imp_p->module->revision, 0, 1, (struct lys_module **)&mod)) {
Radek Krejci19a96102018-11-15 13:38:09 +01001073 LOGERR(ctx->ctx, LY_ENOTFOUND, "Unable to reload \"%s\" module to import it into \"%s\", source data not found.",
Michal Vasko69730152020-10-09 16:30:07 +02001074 imp_p->module->name, ctx->mod->name);
Radek Krejci19a96102018-11-15 13:38:09 +01001075 return LY_ENOTFOUND;
1076 }
1077 }
Radek Krejci19a96102018-11-15 13:38:09 +01001078 }
1079
Radek Krejci19a96102018-11-15 13:38:09 +01001080 return ret;
1081}
1082
Michal Vasko33ff9422020-07-03 09:50:39 +02001083LY_ERR
1084lys_identity_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lys_module *module,
Radek Krejci0f969882020-08-21 16:56:47 +02001085 struct lysp_ident *identities_p, struct lysc_ident **identities)
Radek Krejci19a96102018-11-15 13:38:09 +01001086{
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001087 LY_ARRAY_COUNT_TYPE offset = 0, u, v;
Michal Vasko33ff9422020-07-03 09:50:39 +02001088 struct lysc_ctx context = {0};
Radek Krejci19a96102018-11-15 13:38:09 +01001089 LY_ERR ret = LY_SUCCESS;
1090
Michal Vasko33ff9422020-07-03 09:50:39 +02001091 assert(ctx_sc || ctx);
Radek Krejci327de162019-06-14 12:52:07 +02001092
Michal Vasko33ff9422020-07-03 09:50:39 +02001093 if (!ctx_sc) {
1094 context.ctx = ctx;
1095 context.mod = module;
Radek Krejci120d8542020-08-12 09:29:16 +02001096 context.mod_def = module;
Michal Vasko33ff9422020-07-03 09:50:39 +02001097 context.path_len = 1;
1098 context.path[0] = '/';
1099 ctx_sc = &context;
1100 }
Radek Krejci19a96102018-11-15 13:38:09 +01001101
Michal Vasko33ff9422020-07-03 09:50:39 +02001102 if (!identities_p) {
1103 return LY_SUCCESS;
1104 }
1105 if (*identities) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001106 offset = LY_ARRAY_COUNT(*identities);
Michal Vasko33ff9422020-07-03 09:50:39 +02001107 }
1108
1109 lysc_update_path(ctx_sc, NULL, "{identity}");
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001110 LY_ARRAY_CREATE_RET(ctx_sc->ctx, *identities, LY_ARRAY_COUNT(identities_p), LY_EMEM);
Michal Vasko33ff9422020-07-03 09:50:39 +02001111 LY_ARRAY_FOR(identities_p, u) {
1112 lysc_update_path(ctx_sc, NULL, identities_p[u].name);
1113
1114 LY_ARRAY_INCREMENT(*identities);
1115 COMPILE_CHECK_UNIQUENESS_ARRAY(ctx_sc, *identities, name, &(*identities)[offset + u], "identity", identities_p[u].name);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001116 DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].name, (*identities)[offset + u].name, ret, done);
1117 DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].dsc, (*identities)[offset + u].dsc, ret, done);
1118 DUP_STRING_GOTO(ctx_sc->ctx, identities_p[u].ref, (*identities)[offset + u].ref, ret, done);
Michal Vasko33ff9422020-07-03 09:50:39 +02001119 (*identities)[offset + u].module = ctx_sc->mod;
1120 COMPILE_ARRAY_GOTO(ctx_sc, identities_p[u].iffeatures, (*identities)[offset + u].iffeatures, v,
Michal Vasko69730152020-10-09 16:30:07 +02001121 lys_compile_iffeature, ret, done);
Michal Vasko33ff9422020-07-03 09:50:39 +02001122 /* backlinks (derived) can be added no sooner than when all the identities in the current module are present */
1123 COMPILE_EXTS_GOTO(ctx_sc, identities_p[u].exts, (*identities)[offset + u].exts, &(*identities)[offset + u],
Michal Vasko69730152020-10-09 16:30:07 +02001124 LYEXT_PAR_IDENT, ret, done);
Michal Vasko33ff9422020-07-03 09:50:39 +02001125 (*identities)[offset + u].flags = identities_p[u].flags;
1126
1127 lysc_update_path(ctx_sc, NULL, NULL);
1128 }
1129 lysc_update_path(ctx_sc, NULL, NULL);
Radek Krejci19a96102018-11-15 13:38:09 +01001130done:
1131 return ret;
1132}
1133
Radek Krejcib56c7502019-02-13 14:19:54 +01001134/**
1135 * @brief Check circular dependency of identities - identity MUST NOT reference itself (via their base statement).
1136 *
1137 * The function works in the same way as lys_compile_feature_circular_check() with different structures and error messages.
1138 *
1139 * @param[in] ctx Compile context for logging.
1140 * @param[in] ident The base identity (its derived list is being extended by the identity being currently processed).
1141 * @param[in] derived The list of derived identities of the identity being currently processed (not the one provided as @p ident)
1142 * @return LY_SUCCESS if everything is ok.
1143 * @return LY_EVALID if the identity is derived from itself.
1144 */
Radek Krejci38222632019-02-12 16:55:05 +01001145static LY_ERR
1146lys_compile_identity_circular_check(struct lysc_ctx *ctx, struct lysc_ident *ident, struct lysc_ident **derived)
1147{
Radek Krejciba03a5a2020-08-27 14:40:41 +02001148 LY_ERR ret = LY_SUCCESS;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001149 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci38222632019-02-12 16:55:05 +01001150 struct ly_set recursion = {0};
1151 struct lysc_ident *drv;
1152
1153 if (!derived) {
1154 return LY_SUCCESS;
1155 }
1156
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001157 for (u = 0; u < LY_ARRAY_COUNT(derived); ++u) {
Radek Krejci38222632019-02-12 16:55:05 +01001158 if (ident == derived[u]) {
1159 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001160 "Identity \"%s\" is indirectly derived from itself.", ident->name);
Radek Krejciba03a5a2020-08-27 14:40:41 +02001161 ret = LY_EVALID;
Radek Krejci38222632019-02-12 16:55:05 +01001162 goto cleanup;
1163 }
Radek Krejciba03a5a2020-08-27 14:40:41 +02001164 ret = ly_set_add(&recursion, derived[u], 0, NULL);
1165 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci38222632019-02-12 16:55:05 +01001166 }
1167
1168 for (v = 0; v < recursion.count; ++v) {
1169 drv = recursion.objs[v];
1170 if (!drv->derived) {
1171 continue;
1172 }
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001173 for (u = 0; u < LY_ARRAY_COUNT(drv->derived); ++u) {
Radek Krejci38222632019-02-12 16:55:05 +01001174 if (ident == drv->derived[u]) {
1175 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001176 "Identity \"%s\" is indirectly derived from itself.", ident->name);
Radek Krejciba03a5a2020-08-27 14:40:41 +02001177 ret = LY_EVALID;
Radek Krejci38222632019-02-12 16:55:05 +01001178 goto cleanup;
1179 }
Radek Krejciba03a5a2020-08-27 14:40:41 +02001180 ret = ly_set_add(&recursion, drv->derived[u], 0, NULL);
1181 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci38222632019-02-12 16:55:05 +01001182 }
1183 }
Radek Krejci38222632019-02-12 16:55:05 +01001184
1185cleanup:
1186 ly_set_erase(&recursion, NULL);
1187 return ret;
1188}
1189
Radek Krejcia3045382018-11-22 14:30:31 +01001190/**
1191 * @brief Find and process the referenced base identities from another identity or identityref
1192 *
Radek Krejciaca74032019-06-04 08:53:06 +02001193 * For bases in identity set backlinks to them from the base identities. For identityref, store
Radek Krejcia3045382018-11-22 14:30:31 +01001194 * the array of pointers to the base identities. So one of the ident or bases parameter must be set
1195 * to distinguish these two use cases.
1196 *
1197 * @param[in] ctx Compile context, not only for logging but also to get the current module to resolve prefixes.
1198 * @param[in] bases_p Array of names (including prefix if necessary) of base identities.
Michal Vasko33ff9422020-07-03 09:50:39 +02001199 * @param[in] ident Referencing identity to work with, NULL for identityref.
Radek Krejcia3045382018-11-22 14:30:31 +01001200 * @param[in] bases Array of bases of identityref to fill in.
1201 * @return LY_ERR value.
1202 */
Radek Krejci19a96102018-11-15 13:38:09 +01001203static LY_ERR
Michal Vasko72619ce2020-10-06 14:05:32 +02001204lys_compile_identity_bases(struct lysc_ctx *ctx, const struct lys_module *context_module, const char **bases_p,
Radek Krejci0f969882020-08-21 16:56:47 +02001205 struct lysc_ident *ident, struct lysc_ident ***bases)
Radek Krejci19a96102018-11-15 13:38:09 +01001206{
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001207 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci19a96102018-11-15 13:38:09 +01001208 const char *s, *name;
Michal Vasko72619ce2020-10-06 14:05:32 +02001209 const struct lys_module *mod;
Radek Krejci80d281e2020-09-14 17:42:54 +02001210 struct lysc_ident **idref;
Radek Krejci555cb5b2018-11-16 14:54:33 +01001211
1212 assert(ident || bases);
1213
Michal Vasko69730152020-10-09 16:30:07 +02001214 if ((LY_ARRAY_COUNT(bases_p) > 1) && (ctx->mod_def->version < 2)) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01001215 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001216 "Multiple bases in %s are allowed only in YANG 1.1 modules.", ident ? "identity" : "identityref type");
Radek Krejci555cb5b2018-11-16 14:54:33 +01001217 return LY_EVALID;
1218 }
1219
Michal Vasko33ff9422020-07-03 09:50:39 +02001220 LY_ARRAY_FOR(bases_p, u) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01001221 s = strchr(bases_p[u], ':');
1222 if (s) {
1223 /* prefixed identity */
1224 name = &s[1];
Radek Krejci0a33b042020-05-27 10:05:06 +02001225 mod = lys_module_find_prefix(context_module, bases_p[u], s - bases_p[u]);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001226 } else {
1227 name = bases_p[u];
Radek Krejci0a33b042020-05-27 10:05:06 +02001228 mod = context_module;
Radek Krejci555cb5b2018-11-16 14:54:33 +01001229 }
1230 if (!mod) {
1231 if (ident) {
1232 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001233 "Invalid prefix used for base (%s) of identity \"%s\".", bases_p[u], ident->name);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001234 } else {
1235 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001236 "Invalid prefix used for base (%s) of identityref.", bases_p[u]);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001237 }
1238 return LY_EVALID;
1239 }
Michal Vasko33ff9422020-07-03 09:50:39 +02001240
Radek Krejci555cb5b2018-11-16 14:54:33 +01001241 idref = NULL;
Radek Krejci80d281e2020-09-14 17:42:54 +02001242 LY_ARRAY_FOR(mod->identities, v) {
1243 if (!strcmp(name, mod->identities[v].name)) {
Michal Vasko33ff9422020-07-03 09:50:39 +02001244 if (ident) {
Radek Krejci80d281e2020-09-14 17:42:54 +02001245 if (ident == &mod->identities[v]) {
Michal Vasko33ff9422020-07-03 09:50:39 +02001246 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001247 "Identity \"%s\" is derived from itself.", ident->name);
Michal Vasko33ff9422020-07-03 09:50:39 +02001248 return LY_EVALID;
Radek Krejci555cb5b2018-11-16 14:54:33 +01001249 }
Radek Krejci80d281e2020-09-14 17:42:54 +02001250 LY_CHECK_RET(lys_compile_identity_circular_check(ctx, &mod->identities[v], ident->derived));
Michal Vasko33ff9422020-07-03 09:50:39 +02001251 /* we have match! store the backlink */
Radek Krejci80d281e2020-09-14 17:42:54 +02001252 LY_ARRAY_NEW_RET(ctx->ctx, mod->identities[v].derived, idref, LY_EMEM);
Michal Vasko33ff9422020-07-03 09:50:39 +02001253 *idref = ident;
1254 } else {
1255 /* we have match! store the found identity */
1256 LY_ARRAY_NEW_RET(ctx->ctx, *bases, idref, LY_EMEM);
Radek Krejci80d281e2020-09-14 17:42:54 +02001257 *idref = &mod->identities[v];
Radek Krejci555cb5b2018-11-16 14:54:33 +01001258 }
Michal Vasko33ff9422020-07-03 09:50:39 +02001259 break;
Radek Krejci555cb5b2018-11-16 14:54:33 +01001260 }
1261 }
1262 if (!idref || !(*idref)) {
1263 if (ident) {
1264 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001265 "Unable to find base (%s) of identity \"%s\".", bases_p[u], ident->name);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001266 } else {
1267 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001268 "Unable to find base (%s) of identityref.", bases_p[u]);
Radek Krejci555cb5b2018-11-16 14:54:33 +01001269 }
1270 return LY_EVALID;
1271 }
1272 }
1273 return LY_SUCCESS;
1274}
1275
Radek Krejcia3045382018-11-22 14:30:31 +01001276/**
1277 * @brief For the given array of identities, set the backlinks from all their base identities.
1278 * @param[in] ctx Compile context, not only for logging but also to get the current module to resolve prefixes.
1279 * @param[in] idents_p Array of identities definitions from the parsed schema structure.
1280 * @param[in] idents Array of referencing identities to which the backlinks are supposed to be set.
1281 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
1282 */
Radek Krejci555cb5b2018-11-16 14:54:33 +01001283static LY_ERR
1284lys_compile_identities_derived(struct lysc_ctx *ctx, struct lysp_ident *idents_p, struct lysc_ident *idents)
1285{
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001286 LY_ARRAY_COUNT_TYPE u;
Radek Krejci19a96102018-11-15 13:38:09 +01001287
Michal Vasko33ff9422020-07-03 09:50:39 +02001288 lysc_update_path(ctx, NULL, "{identity}");
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001289 for (u = 0; u < LY_ARRAY_COUNT(idents_p); ++u) {
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001290 if (!idents_p[u].bases) {
Radek Krejci19a96102018-11-15 13:38:09 +01001291 continue;
1292 }
Radek Krejci7eb54ba2020-05-18 16:30:04 +02001293 lysc_update_path(ctx, NULL, idents[u].name);
Radek Krejci0a33b042020-05-27 10:05:06 +02001294 LY_CHECK_RET(lys_compile_identity_bases(ctx, idents[u].module, idents_p[u].bases, &idents[u], NULL));
Radek Krejci327de162019-06-14 12:52:07 +02001295 lysc_update_path(ctx, NULL, NULL);
Radek Krejci19a96102018-11-15 13:38:09 +01001296 }
Michal Vasko33ff9422020-07-03 09:50:39 +02001297 lysc_update_path(ctx, NULL, NULL);
Radek Krejci19a96102018-11-15 13:38:09 +01001298 return LY_SUCCESS;
1299}
1300
Radek Krejci0af46292019-01-11 16:02:31 +01001301LY_ERR
Michal Vasko33ff9422020-07-03 09:50:39 +02001302lys_feature_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lys_module *module,
Radek Krejci0f969882020-08-21 16:56:47 +02001303 struct lysp_feature *features_p, struct lysc_feature **features)
Radek Krejci0af46292019-01-11 16:02:31 +01001304{
Radek Krejci011e4aa2020-09-04 15:22:31 +02001305 LY_ERR ret = LY_SUCCESS;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001306 LY_ARRAY_COUNT_TYPE offset = 0, u;
Radek Krejci0af46292019-01-11 16:02:31 +01001307 struct lysc_ctx context = {0};
1308
Radek Krejci327de162019-06-14 12:52:07 +02001309 assert(ctx_sc || ctx);
1310
1311 if (!ctx_sc) {
1312 context.ctx = ctx;
1313 context.mod = module;
1314 context.path_len = 1;
1315 context.path[0] = '/';
1316 ctx_sc = &context;
1317 }
Radek Krejci0af46292019-01-11 16:02:31 +01001318
1319 if (!features_p) {
1320 return LY_SUCCESS;
1321 }
1322 if (*features) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001323 offset = LY_ARRAY_COUNT(*features);
Radek Krejci0af46292019-01-11 16:02:31 +01001324 }
1325
Radek Krejci327de162019-06-14 12:52:07 +02001326 lysc_update_path(ctx_sc, NULL, "{feature}");
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001327 LY_ARRAY_CREATE_RET(ctx_sc->ctx, *features, LY_ARRAY_COUNT(features_p), LY_EMEM);
Radek Krejci0af46292019-01-11 16:02:31 +01001328 LY_ARRAY_FOR(features_p, u) {
Radek Krejci327de162019-06-14 12:52:07 +02001329 lysc_update_path(ctx_sc, NULL, features_p[u].name);
1330
Radek Krejci0af46292019-01-11 16:02:31 +01001331 LY_ARRAY_INCREMENT(*features);
Michal Vasko6f4cbb62020-02-28 11:15:47 +01001332 COMPILE_CHECK_UNIQUENESS_ARRAY(ctx_sc, *features, name, &(*features)[offset + u], "feature", features_p[u].name);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001333 DUP_STRING_GOTO(ctx_sc->ctx, features_p[u].name, (*features)[offset + u].name, ret, done);
1334 DUP_STRING_GOTO(ctx_sc->ctx, features_p[u].dsc, (*features)[offset + u].dsc, ret, done);
1335 DUP_STRING_GOTO(ctx_sc->ctx, features_p[u].ref, (*features)[offset + u].ref, ret, done);
Radek Krejci0af46292019-01-11 16:02:31 +01001336 (*features)[offset + u].flags = features_p[u].flags;
Radek Krejci327de162019-06-14 12:52:07 +02001337 (*features)[offset + u].module = ctx_sc->mod;
1338
1339 lysc_update_path(ctx_sc, NULL, NULL);
Radek Krejci0af46292019-01-11 16:02:31 +01001340 }
Radek Krejci327de162019-06-14 12:52:07 +02001341 lysc_update_path(ctx_sc, NULL, NULL);
Radek Krejci0af46292019-01-11 16:02:31 +01001342
Radek Krejci011e4aa2020-09-04 15:22:31 +02001343done:
1344 return ret;
Radek Krejci0af46292019-01-11 16:02:31 +01001345}
1346
Radek Krejcia3045382018-11-22 14:30:31 +01001347/**
Radek Krejci09a1fc52019-02-13 10:55:17 +01001348 * @brief Check circular dependency of features - feature MUST NOT reference itself (via their if-feature statement).
Radek Krejcib56c7502019-02-13 14:19:54 +01001349 *
1350 * The function works in the same way as lys_compile_identity_circular_check() with different structures and error messages.
1351 *
Radek Krejci09a1fc52019-02-13 10:55:17 +01001352 * @param[in] ctx Compile context for logging.
Radek Krejcib56c7502019-02-13 14:19:54 +01001353 * @param[in] feature The feature referenced in if-feature statement (its depfeatures list is being extended by the feature
1354 * being currently processed).
1355 * @param[in] depfeatures The list of depending features of the feature being currently processed (not the one provided as @p feature)
Radek Krejci09a1fc52019-02-13 10:55:17 +01001356 * @return LY_SUCCESS if everything is ok.
1357 * @return LY_EVALID if the feature references indirectly itself.
1358 */
1359static LY_ERR
1360lys_compile_feature_circular_check(struct lysc_ctx *ctx, struct lysc_feature *feature, struct lysc_feature **depfeatures)
1361{
Radek Krejciba03a5a2020-08-27 14:40:41 +02001362 LY_ERR ret = LY_SUCCESS;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001363 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci09a1fc52019-02-13 10:55:17 +01001364 struct ly_set recursion = {0};
1365 struct lysc_feature *drv;
1366
1367 if (!depfeatures) {
1368 return LY_SUCCESS;
1369 }
1370
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001371 for (u = 0; u < LY_ARRAY_COUNT(depfeatures); ++u) {
Radek Krejci09a1fc52019-02-13 10:55:17 +01001372 if (feature == depfeatures[u]) {
1373 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001374 "Feature \"%s\" is indirectly referenced from itself.", feature->name);
Radek Krejciba03a5a2020-08-27 14:40:41 +02001375 ret = LY_EVALID;
Radek Krejci09a1fc52019-02-13 10:55:17 +01001376 goto cleanup;
1377 }
Radek Krejciba03a5a2020-08-27 14:40:41 +02001378 ret = ly_set_add(&recursion, depfeatures[u], 0, NULL);
1379 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci09a1fc52019-02-13 10:55:17 +01001380 }
1381
1382 for (v = 0; v < recursion.count; ++v) {
1383 drv = recursion.objs[v];
1384 if (!drv->depfeatures) {
1385 continue;
1386 }
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001387 for (u = 0; u < LY_ARRAY_COUNT(drv->depfeatures); ++u) {
Radek Krejci09a1fc52019-02-13 10:55:17 +01001388 if (feature == drv->depfeatures[u]) {
1389 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001390 "Feature \"%s\" is indirectly referenced from itself.", feature->name);
Radek Krejciba03a5a2020-08-27 14:40:41 +02001391 ret = LY_EVALID;
Radek Krejci09a1fc52019-02-13 10:55:17 +01001392 goto cleanup;
1393 }
Radek Krejciba03a5a2020-08-27 14:40:41 +02001394 ly_set_add(&recursion, drv->depfeatures[u], 0, NULL);
1395 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci09a1fc52019-02-13 10:55:17 +01001396 }
1397 }
Radek Krejci09a1fc52019-02-13 10:55:17 +01001398
1399cleanup:
1400 ly_set_erase(&recursion, NULL);
1401 return ret;
1402}
1403
1404/**
Radek Krejci0af46292019-01-11 16:02:31 +01001405 * @brief Create pre-compiled features array.
1406 *
1407 * See lys_feature_precompile() for more details.
1408 *
Radek Krejcia3045382018-11-22 14:30:31 +01001409 * @param[in] ctx Compile context.
1410 * @param[in] feature_p Parsed feature definition to compile.
Radek Krejci0af46292019-01-11 16:02:31 +01001411 * @param[in,out] features List of already (pre)compiled features to find the corresponding precompiled feature structure.
Radek Krejcia3045382018-11-22 14:30:31 +01001412 * @return LY_ERR value.
1413 */
Radek Krejci19a96102018-11-15 13:38:09 +01001414static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02001415lys_feature_precompile_finish(struct lysc_ctx *ctx, struct lysp_feature *feature_p, struct lysc_feature *features)
Radek Krejci19a96102018-11-15 13:38:09 +01001416{
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001417 LY_ARRAY_COUNT_TYPE u, v, x;
Radek Krejci0af46292019-01-11 16:02:31 +01001418 struct lysc_feature *feature, **df;
Radek Krejci19a96102018-11-15 13:38:09 +01001419 LY_ERR ret = LY_SUCCESS;
Radek Krejci19a96102018-11-15 13:38:09 +01001420
Radek Krejci0af46292019-01-11 16:02:31 +01001421 /* find the preprecompiled feature */
1422 LY_ARRAY_FOR(features, x) {
1423 if (strcmp(features[x].name, feature_p->name)) {
1424 continue;
1425 }
1426 feature = &features[x];
Radek Krejci327de162019-06-14 12:52:07 +02001427 lysc_update_path(ctx, NULL, "{feature}");
1428 lysc_update_path(ctx, NULL, feature_p->name);
Radek Krejci19a96102018-11-15 13:38:09 +01001429
Radek Krejci0af46292019-01-11 16:02:31 +01001430 /* finish compilation started in lys_feature_precompile() */
Radek Krejci0935f412019-08-20 16:15:18 +02001431 COMPILE_EXTS_GOTO(ctx, feature_p->exts, feature->exts, feature, LYEXT_PAR_FEATURE, ret, done);
Radek Krejciec4da802019-05-02 13:02:41 +02001432 COMPILE_ARRAY_GOTO(ctx, feature_p->iffeatures, feature->iffeatures, u, lys_compile_iffeature, ret, done);
Radek Krejci0af46292019-01-11 16:02:31 +01001433 if (feature->iffeatures) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001434 for (u = 0; u < LY_ARRAY_COUNT(feature->iffeatures); ++u) {
Radek Krejci0af46292019-01-11 16:02:31 +01001435 if (feature->iffeatures[u].features) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001436 for (v = 0; v < LY_ARRAY_COUNT(feature->iffeatures[u].features); ++v) {
Radek Krejci09a1fc52019-02-13 10:55:17 +01001437 /* check for circular dependency - direct reference first,... */
1438 if (feature == feature->iffeatures[u].features[v]) {
1439 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02001440 "Feature \"%s\" is referenced from itself.", feature->name);
Radek Krejci09a1fc52019-02-13 10:55:17 +01001441 return LY_EVALID;
1442 }
1443 /* ... and indirect circular reference */
1444 LY_CHECK_RET(lys_compile_feature_circular_check(ctx, feature->iffeatures[u].features[v], feature->depfeatures));
1445
Radek Krejci0af46292019-01-11 16:02:31 +01001446 /* add itself into the dependants list */
1447 LY_ARRAY_NEW_RET(ctx->ctx, feature->iffeatures[u].features[v]->depfeatures, df, LY_EMEM);
1448 *df = feature;
1449 }
Radek Krejci19a96102018-11-15 13:38:09 +01001450 }
Radek Krejci19a96102018-11-15 13:38:09 +01001451 }
1452 }
Radek Krejci327de162019-06-14 12:52:07 +02001453 lysc_update_path(ctx, NULL, NULL);
1454 lysc_update_path(ctx, NULL, NULL);
Michal Vasko69730152020-10-09 16:30:07 +02001455done:
Radek Krejci0af46292019-01-11 16:02:31 +01001456 return ret;
Radek Krejci19a96102018-11-15 13:38:09 +01001457 }
Radek Krejci0af46292019-01-11 16:02:31 +01001458
1459 LOGINT(ctx->ctx);
1460 return LY_EINT;
Radek Krejci19a96102018-11-15 13:38:09 +01001461}
1462
Radek Krejcib56c7502019-02-13 14:19:54 +01001463/**
1464 * @brief Revert compiled list of features back to the precompiled state.
1465 *
1466 * Function is needed in case the compilation failed and the schema is expected to revert back to the non-compiled status.
Radek Krejcib56c7502019-02-13 14:19:54 +01001467 *
1468 * @param[in] ctx Compilation context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02001469 * @param[in] mod The module structure with the features to decompile.
Radek Krejcib56c7502019-02-13 14:19:54 +01001470 */
Radek Krejci95710c92019-02-11 15:49:55 +01001471static void
1472lys_feature_precompile_revert(struct lysc_ctx *ctx, struct lys_module *mod)
1473{
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001474 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci95710c92019-02-11 15:49:55 +01001475
Michal Vasko33ff9422020-07-03 09:50:39 +02001476 /* in the dis_features list, remove all the parts (from finished compiling process)
Radek Krejci95710c92019-02-11 15:49:55 +01001477 * which may points into the data being freed here */
Radek Krejci14915cc2020-09-14 17:28:13 +02001478 LY_ARRAY_FOR(mod->features, u) {
1479 LY_ARRAY_FOR(mod->features[u].iffeatures, v) {
1480 lysc_iffeature_free(ctx->ctx, &mod->features[u].iffeatures[v]);
Radek Krejci95710c92019-02-11 15:49:55 +01001481 }
Radek Krejci14915cc2020-09-14 17:28:13 +02001482 LY_ARRAY_FREE(mod->features[u].iffeatures);
1483 mod->features[u].iffeatures = NULL;
Radek Krejci95710c92019-02-11 15:49:55 +01001484
Radek Krejci14915cc2020-09-14 17:28:13 +02001485 LY_ARRAY_FOR(mod->features[u].exts, v) {
1486 lysc_ext_instance_free(ctx->ctx, &(mod->features[u].exts)[v]);
Radek Krejci95710c92019-02-11 15:49:55 +01001487 }
Radek Krejci14915cc2020-09-14 17:28:13 +02001488 LY_ARRAY_FREE(mod->features[u].exts);
1489 mod->features[u].exts = NULL;
Radek Krejci95710c92019-02-11 15:49:55 +01001490 }
1491}
1492
Radek Krejcia3045382018-11-22 14:30:31 +01001493/**
1494 * @brief Validate and normalize numeric value from a range definition.
1495 * @param[in] ctx Compile context.
1496 * @param[in] basetype Base YANG built-in type of the node connected with the range restriction. Actually only LY_TYPE_DEC64 is important to
1497 * allow processing of the fractions. The fraction point is extracted from the value which is then normalize according to given frdigits into
1498 * valcopy to allow easy parsing and storing of the value. libyang stores decimal number without the decimal point which is always recovered from
1499 * the known fraction-digits value. So, with fraction-digits 2, number 3.14 is stored as 314 and number 1 is stored as 100.
1500 * @param[in] frdigits The fraction-digits of the type in case of LY_TYPE_DEC64.
1501 * @param[in] value String value of the range boundary.
1502 * @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.
1503 * @param[out] valcopy NULL-terminated string with the numeric value to parse and store.
1504 * @return LY_ERR value - LY_SUCCESS, LY_EMEM, LY_EVALID (no number) or LY_EINVAL (decimal64 not matching fraction-digits value).
1505 */
Radek Krejcie88beef2019-05-30 15:47:19 +02001506LY_ERR
Radek Krejci6cba4292018-11-15 17:33:29 +01001507range_part_check_value_syntax(struct lysc_ctx *ctx, LY_DATA_TYPE basetype, uint8_t frdigits, const char *value, size_t *len, char **valcopy)
Radek Krejci19a96102018-11-15 13:38:09 +01001508{
Radek Krejci6cba4292018-11-15 17:33:29 +01001509 size_t fraction = 0, size;
1510
Radek Krejci19a96102018-11-15 13:38:09 +01001511 *len = 0;
1512
1513 assert(value);
1514 /* parse value */
1515 if (!isdigit(value[*len]) && (value[*len] != '-') && (value[*len] != '+')) {
1516 return LY_EVALID;
1517 }
1518
1519 if ((value[*len] == '-') || (value[*len] == '+')) {
1520 ++(*len);
1521 }
1522
1523 while (isdigit(value[*len])) {
1524 ++(*len);
1525 }
1526
1527 if ((basetype != LY_TYPE_DEC64) || (value[*len] != '.') || !isdigit(value[*len + 1])) {
Radek Krejci6cba4292018-11-15 17:33:29 +01001528 if (basetype == LY_TYPE_DEC64) {
1529 goto decimal;
1530 } else {
1531 *valcopy = strndup(value, *len);
1532 return LY_SUCCESS;
1533 }
Radek Krejci19a96102018-11-15 13:38:09 +01001534 }
1535 fraction = *len;
1536
1537 ++(*len);
1538 while (isdigit(value[*len])) {
1539 ++(*len);
1540 }
1541
Radek Krejci6cba4292018-11-15 17:33:29 +01001542 if (basetype == LY_TYPE_DEC64) {
1543decimal:
1544 assert(frdigits);
Radek Krejci943177f2019-06-14 16:32:43 +02001545 if (fraction && (*len - 1 - fraction > frdigits)) {
Radek Krejci6cba4292018-11-15 17:33:29 +01001546 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001547 "Range boundary \"%.*s\" of decimal64 type exceeds defined number (%u) of fraction digits.",
1548 *len, value, frdigits);
Radek Krejci6cba4292018-11-15 17:33:29 +01001549 return LY_EINVAL;
1550 }
1551 if (fraction) {
1552 size = (*len) + (frdigits - ((*len) - 1 - fraction));
1553 } else {
1554 size = (*len) + frdigits + 1;
1555 }
1556 *valcopy = malloc(size * sizeof **valcopy);
Radek Krejci19a96102018-11-15 13:38:09 +01001557 LY_CHECK_ERR_RET(!(*valcopy), LOGMEM(ctx->ctx), LY_EMEM);
1558
Radek Krejci6cba4292018-11-15 17:33:29 +01001559 (*valcopy)[size - 1] = '\0';
1560 if (fraction) {
1561 memcpy(&(*valcopy)[0], &value[0], fraction);
1562 memcpy(&(*valcopy)[fraction], &value[fraction + 1], (*len) - 1 - (fraction));
1563 memset(&(*valcopy)[(*len) - 1], '0', frdigits - ((*len) - 1 - fraction));
1564 } else {
1565 memcpy(&(*valcopy)[0], &value[0], *len);
1566 memset(&(*valcopy)[*len], '0', frdigits);
1567 }
Radek Krejci19a96102018-11-15 13:38:09 +01001568 }
1569 return LY_SUCCESS;
1570}
1571
Radek Krejcia3045382018-11-22 14:30:31 +01001572/**
1573 * @brief Check that values in range are in ascendant order.
1574 * @param[in] unsigned_value Flag to note that we are working with unsigned values.
Radek Krejci5969f272018-11-23 10:03:58 +01001575 * @param[in] max Flag to distinguish if checking min or max value. min value must be strictly higher than previous,
1576 * max can be also equal.
Radek Krejcia3045382018-11-22 14:30:31 +01001577 * @param[in] value Current value to check.
1578 * @param[in] prev_value The last seen value.
1579 * @return LY_SUCCESS or LY_EEXIST for invalid order.
1580 */
Radek Krejci19a96102018-11-15 13:38:09 +01001581static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02001582range_part_check_ascendancy(ly_bool unsigned_value, ly_bool max, int64_t value, int64_t prev_value)
Radek Krejci19a96102018-11-15 13:38:09 +01001583{
1584 if (unsigned_value) {
Michal Vasko69730152020-10-09 16:30:07 +02001585 if ((max && ((uint64_t)prev_value > (uint64_t)value)) || (!max && ((uint64_t)prev_value >= (uint64_t)value))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001586 return LY_EEXIST;
1587 }
1588 } else {
Michal Vasko69730152020-10-09 16:30:07 +02001589 if ((max && (prev_value > value)) || (!max && (prev_value >= value))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001590 return LY_EEXIST;
1591 }
1592 }
1593 return LY_SUCCESS;
1594}
1595
Radek Krejcia3045382018-11-22 14:30:31 +01001596/**
1597 * @brief Set min/max value of the range part.
1598 * @param[in] ctx Compile context.
1599 * @param[in] part Range part structure to fill.
1600 * @param[in] max Flag to distinguish if storing min or max value.
1601 * @param[in] prev The last seen value to check that all values in range are specified in ascendant order.
1602 * @param[in] basetype Type of the value to get know implicit min/max values and other checking rules.
1603 * @param[in] first Flag for the first value of the range to avoid ascendancy order.
1604 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
1605 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
Radek Krejci5969f272018-11-23 10:03:58 +01001606 * @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.
Radek Krejcia3045382018-11-22 14:30:31 +01001607 * @param[in,out] value Numeric range value to be stored, if not provided the type's min/max value is set.
1608 * @return LY_ERR value - LY_SUCCESS, LY_EDENIED (value brokes type's boundaries), LY_EVALID (not a number),
1609 * LY_EEXIST (value is smaller than the previous one), LY_EINVAL (decimal64 value does not corresponds with the
1610 * frdigits value), LY_EMEM.
1611 */
Radek Krejci19a96102018-11-15 13:38:09 +01001612static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02001613range_part_minmax(struct lysc_ctx *ctx, struct lysc_range_part *part, ly_bool max, int64_t prev, LY_DATA_TYPE basetype,
1614 ly_bool first, ly_bool length_restr, uint8_t frdigits, struct lysc_range *base_range, const char **value)
Radek Krejci19a96102018-11-15 13:38:09 +01001615{
1616 LY_ERR ret = LY_SUCCESS;
1617 char *valcopy = NULL;
1618 size_t len;
1619
1620 if (value) {
Radek Krejci6cba4292018-11-15 17:33:29 +01001621 ret = range_part_check_value_syntax(ctx, basetype, frdigits, *value, &len, &valcopy);
Radek Krejci5969f272018-11-23 10:03:58 +01001622 LY_CHECK_GOTO(ret, finalize);
1623 }
1624 if (!valcopy && base_range) {
1625 if (max) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001626 part->max_64 = base_range->parts[LY_ARRAY_COUNT(base_range->parts) - 1].max_64;
Radek Krejci5969f272018-11-23 10:03:58 +01001627 } else {
1628 part->min_64 = base_range->parts[0].min_64;
1629 }
1630 if (!first) {
1631 ret = range_part_check_ascendancy(basetype <= LY_TYPE_STRING ? 1 : 0, max, max ? part->max_64 : part->min_64, prev);
1632 }
1633 goto finalize;
Radek Krejci19a96102018-11-15 13:38:09 +01001634 }
1635
1636 switch (basetype) {
Radek Krejci19a96102018-11-15 13:38:09 +01001637 case LY_TYPE_INT8: /* range */
1638 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001639 ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-128), INT64_C(127), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci19a96102018-11-15 13:38:09 +01001640 } else if (max) {
1641 part->max_64 = INT64_C(127);
1642 } else {
1643 part->min_64 = INT64_C(-128);
1644 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001645 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001646 ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001647 }
1648 break;
1649 case LY_TYPE_INT16: /* range */
1650 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001651 ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-32768), INT64_C(32767), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci19a96102018-11-15 13:38:09 +01001652 } else if (max) {
1653 part->max_64 = INT64_C(32767);
1654 } else {
1655 part->min_64 = INT64_C(-32768);
1656 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001657 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001658 ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001659 }
1660 break;
1661 case LY_TYPE_INT32: /* range */
1662 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001663 ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-2147483648), INT64_C(2147483647), 10, max ? &part->max_64 : &part->min_64);
Radek Krejci19a96102018-11-15 13:38:09 +01001664 } else if (max) {
1665 part->max_64 = INT64_C(2147483647);
1666 } else {
1667 part->min_64 = INT64_C(-2147483648);
1668 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001669 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001670 ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001671 }
1672 break;
1673 case LY_TYPE_INT64: /* range */
Radek Krejci25cfef72018-11-23 14:15:52 +01001674 case LY_TYPE_DEC64: /* range */
Radek Krejci19a96102018-11-15 13:38:09 +01001675 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001676 ret = ly_parse_int(valcopy, strlen(valcopy), INT64_C(-9223372036854775807) - INT64_C(1), INT64_C(9223372036854775807), 10,
Michal Vasko69730152020-10-09 16:30:07 +02001677 max ? &part->max_64 : &part->min_64);
Radek Krejci19a96102018-11-15 13:38:09 +01001678 } else if (max) {
1679 part->max_64 = INT64_C(9223372036854775807);
1680 } else {
1681 part->min_64 = INT64_C(-9223372036854775807) - INT64_C(1);
1682 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001683 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001684 ret = range_part_check_ascendancy(0, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001685 }
1686 break;
1687 case LY_TYPE_UINT8: /* range */
1688 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001689 ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(255), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci19a96102018-11-15 13:38:09 +01001690 } else if (max) {
1691 part->max_u64 = UINT64_C(255);
1692 } else {
1693 part->min_u64 = UINT64_C(0);
1694 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001695 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001696 ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001697 }
1698 break;
1699 case LY_TYPE_UINT16: /* range */
1700 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001701 ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(65535), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci19a96102018-11-15 13:38:09 +01001702 } else if (max) {
1703 part->max_u64 = UINT64_C(65535);
1704 } else {
1705 part->min_u64 = UINT64_C(0);
1706 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001707 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001708 ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001709 }
1710 break;
1711 case LY_TYPE_UINT32: /* range */
1712 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001713 ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(4294967295), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci19a96102018-11-15 13:38:09 +01001714 } else if (max) {
1715 part->max_u64 = UINT64_C(4294967295);
1716 } else {
1717 part->min_u64 = UINT64_C(0);
1718 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001719 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001720 ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001721 }
1722 break;
1723 case LY_TYPE_UINT64: /* range */
Radek Krejci19a96102018-11-15 13:38:09 +01001724 case LY_TYPE_STRING: /* length */
Radek Krejci25cfef72018-11-23 14:15:52 +01001725 case LY_TYPE_BINARY: /* length */
Radek Krejci19a96102018-11-15 13:38:09 +01001726 if (valcopy) {
Radek Krejci249973a2019-06-10 10:50:54 +02001727 ret = ly_parse_uint(valcopy, strlen(valcopy), UINT64_C(18446744073709551615), 10, max ? &part->max_u64 : &part->min_u64);
Radek Krejci19a96102018-11-15 13:38:09 +01001728 } else if (max) {
1729 part->max_u64 = UINT64_C(18446744073709551615);
1730 } else {
1731 part->min_u64 = UINT64_C(0);
1732 }
Radek Krejci6cba4292018-11-15 17:33:29 +01001733 if (!ret && !first) {
Radek Krejci5969f272018-11-23 10:03:58 +01001734 ret = range_part_check_ascendancy(1, max, max ? part->max_64 : part->min_64, prev);
Radek Krejci19a96102018-11-15 13:38:09 +01001735 }
1736 break;
1737 default:
1738 LOGINT(ctx->ctx);
1739 ret = LY_EINT;
1740 }
1741
Radek Krejci5969f272018-11-23 10:03:58 +01001742finalize:
Radek Krejci19a96102018-11-15 13:38:09 +01001743 if (ret == LY_EDENIED) {
1744 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001745 "Invalid %s restriction - value \"%s\" does not fit the type limitations.",
1746 length_restr ? "length" : "range", valcopy ? valcopy : *value);
Radek Krejci19a96102018-11-15 13:38:09 +01001747 } else if (ret == LY_EVALID) {
1748 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001749 "Invalid %s restriction - invalid value \"%s\".",
1750 length_restr ? "length" : "range", valcopy ? valcopy : *value);
Radek Krejci19a96102018-11-15 13:38:09 +01001751 } else if (ret == LY_EEXIST) {
1752 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001753 "Invalid %s restriction - values are not in ascending order (%s).",
1754 length_restr ? "length" : "range",
Radek Krejci0f969882020-08-21 16:56:47 +02001755 (valcopy && basetype != LY_TYPE_DEC64) ? valcopy : value ? *value : max ? "max" : "min");
Radek Krejci19a96102018-11-15 13:38:09 +01001756 } else if (!ret && value) {
1757 *value = *value + len;
1758 }
1759 free(valcopy);
1760 return ret;
1761}
1762
Radek Krejcia3045382018-11-22 14:30:31 +01001763/**
1764 * @brief Compile the parsed range restriction.
1765 * @param[in] ctx Compile context.
1766 * @param[in] range_p Parsed range structure to compile.
1767 * @param[in] basetype Base YANG built-in type of the node with the range restriction.
1768 * @param[in] length_restr Flag to distinguish between range and length restrictions. Only for logging.
1769 * @param[in] frdigits The fraction-digits value in case of LY_TYPE_DEC64 basetype.
1770 * @param[in] base_range Range restriction of the type from which the current type is derived. The current
1771 * range restriction must be more restrictive than the base_range.
1772 * @param[in,out] range Pointer to the created current range structure.
1773 * @return LY_ERR value.
1774 */
Radek Krejci19a96102018-11-15 13:38:09 +01001775static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +02001776lys_compile_type_range(struct lysc_ctx *ctx, struct lysp_restr *range_p, LY_DATA_TYPE basetype, ly_bool length_restr,
Radek Krejci0f969882020-08-21 16:56:47 +02001777 uint8_t frdigits, struct lysc_range *base_range, struct lysc_range **range)
Radek Krejci19a96102018-11-15 13:38:09 +01001778{
1779 LY_ERR ret = LY_EVALID;
1780 const char *expr;
1781 struct lysc_range_part *parts = NULL, *part;
Radek Krejci857189e2020-09-01 13:26:36 +02001782 ly_bool range_expected = 0, uns;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001783 LY_ARRAY_COUNT_TYPE parts_done = 0, u, v;
Radek Krejci19a96102018-11-15 13:38:09 +01001784
1785 assert(range);
1786 assert(range_p);
1787
Michal Vasko7f45cf22020-10-01 12:49:44 +02001788 expr = range_p->arg.str;
Michal Vaskod989ba02020-08-24 10:59:24 +02001789 while (1) {
Radek Krejci19a96102018-11-15 13:38:09 +01001790 if (isspace(*expr)) {
1791 ++expr;
1792 } else if (*expr == '\0') {
1793 if (range_expected) {
1794 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001795 "Invalid %s restriction - unexpected end of the expression after \"..\" (%s).",
1796 length_restr ? "length" : "range", range_p->arg);
Radek Krejci19a96102018-11-15 13:38:09 +01001797 goto cleanup;
Michal Vasko69730152020-10-09 16:30:07 +02001798 } else if (!parts || (parts_done == LY_ARRAY_COUNT(parts))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001799 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001800 "Invalid %s restriction - unexpected end of the expression (%s).",
1801 length_restr ? "length" : "range", range_p->arg);
Radek Krejci19a96102018-11-15 13:38:09 +01001802 goto cleanup;
1803 }
1804 parts_done++;
1805 break;
1806 } else if (!strncmp(expr, "min", 3)) {
1807 if (parts) {
1808 /* min cannot be used elsewhere than in the first part */
1809 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001810 "Invalid %s restriction - unexpected data before min keyword (%.*s).", length_restr ? "length" : "range",
1811 expr - range_p->arg.str, range_p->arg.str);
Radek Krejci19a96102018-11-15 13:38:09 +01001812 goto cleanup;
1813 }
1814 expr += 3;
1815
1816 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
Radek Krejci5969f272018-11-23 10:03:58 +01001817 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, 0, basetype, 1, length_restr, frdigits, base_range, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001818 part->max_64 = part->min_64;
1819 } else if (*expr == '|') {
1820 if (!parts || range_expected) {
1821 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001822 "Invalid %s restriction - unexpected beginning of the expression (%s).", length_restr ? "length" : "range", expr);
Radek Krejci19a96102018-11-15 13:38:09 +01001823 goto cleanup;
1824 }
1825 expr++;
1826 parts_done++;
1827 /* process next part of the expression */
1828 } else if (!strncmp(expr, "..", 2)) {
1829 expr += 2;
1830 while (isspace(*expr)) {
1831 expr++;
1832 }
Michal Vasko69730152020-10-09 16:30:07 +02001833 if (!parts || (LY_ARRAY_COUNT(parts) == parts_done)) {
Radek Krejci19a96102018-11-15 13:38:09 +01001834 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001835 "Invalid %s restriction - unexpected \"..\" without a lower bound.", length_restr ? "length" : "range");
Radek Krejci19a96102018-11-15 13:38:09 +01001836 goto cleanup;
1837 }
1838 /* continue expecting the upper boundary */
1839 range_expected = 1;
1840 } else if (isdigit(*expr) || (*expr == '-') || (*expr == '+')) {
1841 /* number */
1842 if (range_expected) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001843 part = &parts[LY_ARRAY_COUNT(parts) - 1];
Radek Krejci5969f272018-11-23 10:03:58 +01001844 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, NULL, &expr), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001845 range_expected = 0;
1846 } else {
1847 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001848 LY_CHECK_GOTO(range_part_minmax(ctx, part, 0, parts_done ? parts[LY_ARRAY_COUNT(parts) - 2].max_64 : 0,
Michal Vasko69730152020-10-09 16:30:07 +02001849 basetype, parts_done ? 0 : 1, length_restr, frdigits, NULL, &expr), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001850 part->max_64 = part->min_64;
1851 }
1852
1853 /* continue with possible another expression part */
1854 } else if (!strncmp(expr, "max", 3)) {
1855 expr += 3;
1856 while (isspace(*expr)) {
1857 expr++;
1858 }
1859 if (*expr != '\0') {
1860 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data after max keyword (%s).",
Michal Vasko69730152020-10-09 16:30:07 +02001861 length_restr ? "length" : "range", expr);
Radek Krejci19a96102018-11-15 13:38:09 +01001862 goto cleanup;
1863 }
1864 if (range_expected) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001865 part = &parts[LY_ARRAY_COUNT(parts) - 1];
Radek Krejci5969f272018-11-23 10:03:58 +01001866 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, part->min_64, basetype, 0, length_restr, frdigits, base_range, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001867 range_expected = 0;
1868 } else {
1869 LY_ARRAY_NEW_GOTO(ctx->ctx, parts, part, ret, cleanup);
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001870 LY_CHECK_GOTO(range_part_minmax(ctx, part, 1, parts_done ? parts[LY_ARRAY_COUNT(parts) - 2].max_64 : 0,
Michal Vasko69730152020-10-09 16:30:07 +02001871 basetype, parts_done ? 0 : 1, length_restr, frdigits, base_range, NULL), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001872 part->min_64 = part->max_64;
1873 }
1874 } else {
1875 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s restriction - unexpected data (%s).",
Michal Vasko69730152020-10-09 16:30:07 +02001876 length_restr ? "length" : "range", expr);
Radek Krejci19a96102018-11-15 13:38:09 +01001877 goto cleanup;
1878 }
1879 }
1880
1881 /* check with the previous range/length restriction */
1882 if (base_range) {
1883 switch (basetype) {
1884 case LY_TYPE_BINARY:
1885 case LY_TYPE_UINT8:
1886 case LY_TYPE_UINT16:
1887 case LY_TYPE_UINT32:
1888 case LY_TYPE_UINT64:
1889 case LY_TYPE_STRING:
1890 uns = 1;
1891 break;
1892 case LY_TYPE_DEC64:
1893 case LY_TYPE_INT8:
1894 case LY_TYPE_INT16:
1895 case LY_TYPE_INT32:
1896 case LY_TYPE_INT64:
1897 uns = 0;
1898 break;
1899 default:
1900 LOGINT(ctx->ctx);
1901 ret = LY_EINT;
1902 goto cleanup;
1903 }
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001904 for (u = v = 0; u < parts_done && v < LY_ARRAY_COUNT(base_range->parts); ++u) {
Michal Vasko69730152020-10-09 16:30:07 +02001905 if ((uns && (parts[u].min_u64 < base_range->parts[v].min_u64)) || (!uns && (parts[u].min_64 < base_range->parts[v].min_64))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001906 goto baseerror;
1907 }
1908 /* current lower bound is not lower than the base */
1909 if (base_range->parts[v].min_64 == base_range->parts[v].max_64) {
1910 /* base has single value */
1911 if (base_range->parts[v].min_64 == parts[u].min_64) {
1912 /* both lower bounds are the same */
1913 if (parts[u].min_64 != parts[u].max_64) {
1914 /* current continues with a range */
1915 goto baseerror;
1916 } else {
1917 /* equal single values, move both forward */
1918 ++v;
1919 continue;
1920 }
1921 } else {
1922 /* base is single value lower than current range, so the
1923 * value from base range is removed in the current,
1924 * move only base and repeat checking */
1925 ++v;
1926 --u;
1927 continue;
1928 }
1929 } else {
1930 /* base is the range */
1931 if (parts[u].min_64 == parts[u].max_64) {
1932 /* current is a single value */
Michal Vasko69730152020-10-09 16:30:07 +02001933 if ((uns && (parts[u].max_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].max_64 > base_range->parts[v].max_64))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001934 /* current is behind the base range, so base range is omitted,
1935 * move the base and keep the current for further check */
1936 ++v;
1937 --u;
1938 } /* else it is within the base range, so move the current, but keep the base */
1939 continue;
1940 } else {
1941 /* both are ranges - check the higher bound, the lower was already checked */
Michal Vasko69730152020-10-09 16:30:07 +02001942 if ((uns && (parts[u].max_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].max_64 > base_range->parts[v].max_64))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001943 /* higher bound is higher than the current higher bound */
Michal Vasko69730152020-10-09 16:30:07 +02001944 if ((uns && (parts[u].min_u64 > base_range->parts[v].max_u64)) || (!uns && (parts[u].min_64 > base_range->parts[v].max_64))) {
Radek Krejci19a96102018-11-15 13:38:09 +01001945 /* but the current lower bound is also higher, so the base range is omitted,
1946 * continue with the same current, but move the base */
1947 --u;
1948 ++v;
1949 continue;
1950 }
1951 /* current range starts within the base range but end behind it */
1952 goto baseerror;
1953 } else {
1954 /* current range is smaller than the base,
1955 * move current, but stay with the base */
1956 continue;
1957 }
1958 }
1959 }
1960 }
1961 if (u != parts_done) {
1962baseerror:
1963 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02001964 "Invalid %s restriction - the derived restriction (%s) is not equally or more limiting.",
1965 length_restr ? "length" : "range", range_p->arg);
Radek Krejci19a96102018-11-15 13:38:09 +01001966 goto cleanup;
1967 }
1968 }
1969
1970 if (!(*range)) {
1971 *range = calloc(1, sizeof **range);
1972 LY_CHECK_ERR_RET(!(*range), LOGMEM(ctx->ctx), LY_EMEM);
1973 }
1974
Radek Krejcic8b31002019-01-08 10:24:45 +01001975 /* we rewrite the following values as the types chain is being processed */
Radek Krejci19a96102018-11-15 13:38:09 +01001976 if (range_p->eapptag) {
1977 lydict_remove(ctx->ctx, (*range)->eapptag);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001978 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->eapptag, 0, &(*range)->eapptag), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001979 }
1980 if (range_p->emsg) {
1981 lydict_remove(ctx->ctx, (*range)->emsg);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001982 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->emsg, 0, &(*range)->emsg), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01001983 }
Radek Krejcic8b31002019-01-08 10:24:45 +01001984 if (range_p->dsc) {
1985 lydict_remove(ctx->ctx, (*range)->dsc);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001986 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->dsc, 0, &(*range)->dsc), cleanup);
Radek Krejcic8b31002019-01-08 10:24:45 +01001987 }
1988 if (range_p->ref) {
1989 lydict_remove(ctx->ctx, (*range)->ref);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001990 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, range_p->ref, 0, &(*range)->ref), cleanup);
Radek Krejcic8b31002019-01-08 10:24:45 +01001991 }
Radek Krejci19a96102018-11-15 13:38:09 +01001992 /* extensions are taken only from the last range by the caller */
1993
1994 (*range)->parts = parts;
1995 parts = NULL;
1996 ret = LY_SUCCESS;
1997cleanup:
Radek Krejci19a96102018-11-15 13:38:09 +01001998 LY_ARRAY_FREE(parts);
1999
2000 return ret;
2001}
2002
2003/**
2004 * @brief Checks pattern syntax.
2005 *
Michal Vasko03ff5a72019-09-11 13:49:33 +02002006 * @param[in] ctx Context.
2007 * @param[in] log_path Path for logging errors.
Radek Krejci19a96102018-11-15 13:38:09 +01002008 * @param[in] pattern Pattern to check.
Radek Krejci54579462019-04-30 12:47:06 +02002009 * @param[in,out] pcre2_code Compiled PCRE2 pattern. If NULL, the compiled information used to validate pattern are freed.
Radek Krejcia3045382018-11-22 14:30:31 +01002010 * @return LY_ERR value - LY_SUCCESS, LY_EMEM, LY_EVALID.
Radek Krejci19a96102018-11-15 13:38:09 +01002011 */
Michal Vasko03ff5a72019-09-11 13:49:33 +02002012LY_ERR
2013lys_compile_type_pattern_check(struct ly_ctx *ctx, const char *log_path, const char *pattern, pcre2_code **code)
Radek Krejci19a96102018-11-15 13:38:09 +01002014{
Radek Krejci1deb5be2020-08-26 16:43:36 +02002015 size_t idx, idx2, start, end, size, brack;
Radek Krejci19a96102018-11-15 13:38:09 +01002016 char *perl_regex, *ptr;
Radek Krejci54579462019-04-30 12:47:06 +02002017 int err_code;
2018 const char *orig_ptr;
2019 PCRE2_SIZE err_offset;
2020 pcre2_code *code_local;
Michal Vasko69730152020-10-09 16:30:07 +02002021
Radek Krejci19a96102018-11-15 13:38:09 +01002022#define URANGE_LEN 19
2023 char *ublock2urange[][2] = {
2024 {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
2025 {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
2026 {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
2027 {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
2028 {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
2029 {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
2030 {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
2031 {"Greek", "[\\x{0370}-\\x{03FF}]"},
2032 {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
2033 {"Armenian", "[\\x{0530}-\\x{058F}]"},
2034 {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
2035 {"Arabic", "[\\x{0600}-\\x{06FF}]"},
2036 {"Syriac", "[\\x{0700}-\\x{074F}]"},
2037 {"Thaana", "[\\x{0780}-\\x{07BF}]"},
2038 {"Devanagari", "[\\x{0900}-\\x{097F}]"},
2039 {"Bengali", "[\\x{0980}-\\x{09FF}]"},
2040 {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
2041 {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
2042 {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
2043 {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
2044 {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
2045 {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
2046 {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
2047 {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
2048 {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
2049 {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
2050 {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
2051 {"Myanmar", "[\\x{1000}-\\x{109F}]"},
2052 {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
2053 {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
2054 {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
2055 {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
2056 {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
2057 {"Ogham", "[\\x{1680}-\\x{169F}]"},
2058 {"Runic", "[\\x{16A0}-\\x{16FF}]"},
2059 {"Khmer", "[\\x{1780}-\\x{17FF}]"},
2060 {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
2061 {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
2062 {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
2063 {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
2064 {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
2065 {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
2066 {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
2067 {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
2068 {"NumberForms", "[\\x{2150}-\\x{218F}]"},
2069 {"Arrows", "[\\x{2190}-\\x{21FF}]"},
2070 {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
2071 {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
2072 {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
2073 {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
2074 {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
2075 {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
2076 {"BlockElements", "[\\x{2580}-\\x{259F}]"},
2077 {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
2078 {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
2079 {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
2080 {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
2081 {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
2082 {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
2083 {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
2084 {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
2085 {"Hiragana", "[\\x{3040}-\\x{309F}]"},
2086 {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
2087 {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
2088 {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
2089 {"Kanbun", "[\\x{3190}-\\x{319F}]"},
2090 {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
2091 {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
2092 {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
2093 {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
2094 {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
2095 {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
2096 {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
2097 {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
2098 {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
2099 {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
2100 {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
2101 {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
2102 {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
2103 {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
2104 {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
2105 {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
2106 {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
2107 {NULL, NULL}
2108 };
2109
2110 /* adjust the expression to a Perl equivalent
2111 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs */
2112
Michal Vasko40a00082020-05-27 15:20:01 +02002113 /* allocate space for the transformed pattern */
2114 size = strlen(pattern) + 1;
2115 perl_regex = malloc(size);
Michal Vasko03ff5a72019-09-11 13:49:33 +02002116 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx), LY_EMEM);
Radek Krejci19a96102018-11-15 13:38:09 +01002117 perl_regex[0] = '\0';
2118
Michal Vasko40a00082020-05-27 15:20:01 +02002119 /* we need to replace all "$" and "^" (that are not in "[]") with "\$" and "\^" */
2120 brack = 0;
2121 idx = 0;
2122 orig_ptr = pattern;
2123 while (orig_ptr[0]) {
2124 switch (orig_ptr[0]) {
2125 case '$':
2126 case '^':
2127 if (!brack) {
2128 /* make space for the extra character */
2129 ++size;
2130 perl_regex = ly_realloc(perl_regex, size);
2131 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx), LY_EMEM);
Radek Krejci19a96102018-11-15 13:38:09 +01002132
Michal Vasko40a00082020-05-27 15:20:01 +02002133 /* print escape slash */
2134 perl_regex[idx] = '\\';
2135 ++idx;
2136 }
2137 break;
2138 case '[':
2139 /* must not be escaped */
2140 if ((orig_ptr == pattern) || (orig_ptr[-1] != '\\')) {
2141 ++brack;
2142 }
2143 break;
2144 case ']':
2145 if ((orig_ptr == pattern) || (orig_ptr[-1] != '\\')) {
2146 /* pattern was checked and compiled already */
2147 assert(brack);
2148 --brack;
2149 }
2150 break;
2151 default:
2152 break;
Radek Krejci19a96102018-11-15 13:38:09 +01002153 }
Michal Vasko40a00082020-05-27 15:20:01 +02002154
2155 /* copy char */
2156 perl_regex[idx] = orig_ptr[0];
2157
2158 ++idx;
2159 ++orig_ptr;
Radek Krejci19a96102018-11-15 13:38:09 +01002160 }
Michal Vasko40a00082020-05-27 15:20:01 +02002161 perl_regex[idx] = '\0';
Radek Krejci19a96102018-11-15 13:38:09 +01002162
2163 /* substitute Unicode Character Blocks with exact Character Ranges */
2164 while ((ptr = strstr(perl_regex, "\\p{Is"))) {
2165 start = ptr - perl_regex;
2166
2167 ptr = strchr(ptr, '}');
2168 if (!ptr) {
Michal Vasko03ff5a72019-09-11 13:49:33 +02002169 LOGVAL(ctx, LY_VLOG_STR, log_path, LY_VCODE_INREGEXP,
Michal Vasko69730152020-10-09 16:30:07 +02002170 pattern, perl_regex + start + 2, "unterminated character property");
Radek Krejci19a96102018-11-15 13:38:09 +01002171 free(perl_regex);
2172 return LY_EVALID;
2173 }
2174 end = (ptr - perl_regex) + 1;
2175
2176 /* need more space */
2177 if (end - start < URANGE_LEN) {
2178 perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (URANGE_LEN - (end - start)) + 1);
Michal Vasko03ff5a72019-09-11 13:49:33 +02002179 LY_CHECK_ERR_RET(!perl_regex, LOGMEM(ctx); free(perl_regex), LY_EMEM);
Radek Krejci19a96102018-11-15 13:38:09 +01002180 }
2181
2182 /* find our range */
2183 for (idx = 0; ublock2urange[idx][0]; ++idx) {
2184 if (!strncmp(perl_regex + start + 5, ublock2urange[idx][0], strlen(ublock2urange[idx][0]))) {
2185 break;
2186 }
2187 }
2188 if (!ublock2urange[idx][0]) {
Michal Vasko03ff5a72019-09-11 13:49:33 +02002189 LOGVAL(ctx, LY_VLOG_STR, log_path, LY_VCODE_INREGEXP,
Michal Vasko69730152020-10-09 16:30:07 +02002190 pattern, perl_regex + start + 5, "unknown block name");
Radek Krejci19a96102018-11-15 13:38:09 +01002191 free(perl_regex);
2192 return LY_EVALID;
2193 }
2194
2195 /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
Michal Vasko40a00082020-05-27 15:20:01 +02002196 for (idx2 = 0, idx = 0; idx2 < start; ++idx2) {
Radek Krejci19a96102018-11-15 13:38:09 +01002197 if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
Michal Vasko40a00082020-05-27 15:20:01 +02002198 ++idx;
Radek Krejci19a96102018-11-15 13:38:09 +01002199 }
2200 if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
Michal Vasko40a00082020-05-27 15:20:01 +02002201 --idx;
Radek Krejci19a96102018-11-15 13:38:09 +01002202 }
2203 }
Michal Vasko40a00082020-05-27 15:20:01 +02002204 if (idx) {
Radek Krejci19a96102018-11-15 13:38:09 +01002205 /* skip brackets */
2206 memmove(perl_regex + start + (URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
2207 memcpy(perl_regex + start, ublock2urange[idx][1] + 1, URANGE_LEN - 2);
2208 } else {
2209 memmove(perl_regex + start + URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
2210 memcpy(perl_regex + start, ublock2urange[idx][1], URANGE_LEN);
2211 }
2212 }
2213
2214 /* must return 0, already checked during parsing */
Radek Krejci5819f7c2019-05-31 14:53:29 +02002215 code_local = pcre2_compile((PCRE2_SPTR)perl_regex, PCRE2_ZERO_TERMINATED,
Michal Vasko69730152020-10-09 16:30:07 +02002216 PCRE2_UTF | PCRE2_ANCHORED | PCRE2_ENDANCHORED | PCRE2_DOLLAR_ENDONLY | PCRE2_NO_AUTO_CAPTURE,
2217 &err_code, &err_offset, NULL);
Radek Krejci54579462019-04-30 12:47:06 +02002218 if (!code_local) {
2219 PCRE2_UCHAR err_msg[256] = {0};
2220 pcre2_get_error_message(err_code, err_msg, 256);
Michal Vasko03ff5a72019-09-11 13:49:33 +02002221 LOGVAL(ctx, LY_VLOG_STR, log_path, LY_VCODE_INREGEXP, pattern, perl_regex + err_offset, err_msg);
Radek Krejci19a96102018-11-15 13:38:09 +01002222 free(perl_regex);
2223 return LY_EVALID;
2224 }
2225 free(perl_regex);
2226
Radek Krejci54579462019-04-30 12:47:06 +02002227 if (code) {
2228 *code = code_local;
Radek Krejci19a96102018-11-15 13:38:09 +01002229 } else {
Radek Krejci54579462019-04-30 12:47:06 +02002230 free(code_local);
Radek Krejci19a96102018-11-15 13:38:09 +01002231 }
2232
2233 return LY_SUCCESS;
2234
2235#undef URANGE_LEN
2236}
2237
Radek Krejcia3045382018-11-22 14:30:31 +01002238/**
2239 * @brief Compile parsed pattern restriction in conjunction with the patterns from base type.
2240 * @param[in] ctx Compile context.
2241 * @param[in] patterns_p Array of parsed patterns from the current type to compile.
Radek Krejcia3045382018-11-22 14:30:31 +01002242 * @param[in] base_patterns Compiled patterns from the type from which the current type is derived.
2243 * Patterns from the base type are inherited to have all the patterns that have to match at one place.
2244 * @param[out] patterns Pointer to the storage for the patterns of the current type.
2245 * @return LY_ERR LY_SUCCESS, LY_EMEM, LY_EVALID.
2246 */
Radek Krejci19a96102018-11-15 13:38:09 +01002247static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02002248lys_compile_type_patterns(struct lysc_ctx *ctx, struct lysp_restr *patterns_p,
Radek Krejci0f969882020-08-21 16:56:47 +02002249 struct lysc_pattern **base_patterns, struct lysc_pattern ***patterns)
Radek Krejci19a96102018-11-15 13:38:09 +01002250{
2251 struct lysc_pattern **pattern;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002252 LY_ARRAY_COUNT_TYPE u;
Radek Krejci19a96102018-11-15 13:38:09 +01002253 LY_ERR ret = LY_SUCCESS;
2254
2255 /* first, copy the patterns from the base type */
2256 if (base_patterns) {
2257 *patterns = lysc_patterns_dup(ctx->ctx, base_patterns);
2258 LY_CHECK_ERR_RET(!(*patterns), LOGMEM(ctx->ctx), LY_EMEM);
2259 }
2260
2261 LY_ARRAY_FOR(patterns_p, u) {
2262 LY_ARRAY_NEW_RET(ctx->ctx, (*patterns), pattern, LY_EMEM);
2263 *pattern = calloc(1, sizeof **pattern);
2264 ++(*pattern)->refcount;
2265
Michal Vasko7f45cf22020-10-01 12:49:44 +02002266 ret = lys_compile_type_pattern_check(ctx->ctx, ctx->path, &patterns_p[u].arg.str[1], &(*pattern)->code);
Radek Krejci19a96102018-11-15 13:38:09 +01002267 LY_CHECK_RET(ret);
Radek Krejci19a96102018-11-15 13:38:09 +01002268
Michal Vasko7f45cf22020-10-01 12:49:44 +02002269 if (patterns_p[u].arg.str[0] == 0x15) {
Radek Krejci19a96102018-11-15 13:38:09 +01002270 (*pattern)->inverted = 1;
2271 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02002272 DUP_STRING_GOTO(ctx->ctx, &patterns_p[u].arg.str[1], (*pattern)->expr, ret, done);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002273 DUP_STRING_GOTO(ctx->ctx, patterns_p[u].eapptag, (*pattern)->eapptag, ret, done);
2274 DUP_STRING_GOTO(ctx->ctx, patterns_p[u].emsg, (*pattern)->emsg, ret, done);
2275 DUP_STRING_GOTO(ctx->ctx, patterns_p[u].dsc, (*pattern)->dsc, ret, done);
2276 DUP_STRING_GOTO(ctx->ctx, patterns_p[u].ref, (*pattern)->ref, ret, done);
Radek Krejci0935f412019-08-20 16:15:18 +02002277 COMPILE_EXTS_GOTO(ctx, patterns_p[u].exts, (*pattern)->exts, (*pattern), LYEXT_PAR_PATTERN, ret, done);
Radek Krejci19a96102018-11-15 13:38:09 +01002278 }
2279done:
2280 return ret;
2281}
2282
Radek Krejcia3045382018-11-22 14:30:31 +01002283/**
2284 * @brief map of the possible restrictions combination for the specific built-in type.
2285 */
Radek Krejci19a96102018-11-15 13:38:09 +01002286static uint16_t type_substmt_map[LY_DATA_TYPE_COUNT] = {
2287 0 /* LY_TYPE_UNKNOWN */,
2288 LYS_SET_LENGTH /* LY_TYPE_BINARY */,
Radek Krejci5969f272018-11-23 10:03:58 +01002289 LYS_SET_RANGE /* LY_TYPE_UINT8 */,
2290 LYS_SET_RANGE /* LY_TYPE_UINT16 */,
2291 LYS_SET_RANGE /* LY_TYPE_UINT32 */,
2292 LYS_SET_RANGE /* LY_TYPE_UINT64 */,
2293 LYS_SET_LENGTH | LYS_SET_PATTERN /* LY_TYPE_STRING */,
Radek Krejci19a96102018-11-15 13:38:09 +01002294 LYS_SET_BIT /* LY_TYPE_BITS */,
2295 0 /* LY_TYPE_BOOL */,
2296 LYS_SET_FRDIGITS | LYS_SET_RANGE /* LY_TYPE_DEC64 */,
2297 0 /* LY_TYPE_EMPTY */,
2298 LYS_SET_ENUM /* LY_TYPE_ENUM */,
2299 LYS_SET_BASE /* LY_TYPE_IDENT */,
2300 LYS_SET_REQINST /* LY_TYPE_INST */,
2301 LYS_SET_REQINST | LYS_SET_PATH /* LY_TYPE_LEAFREF */,
Radek Krejci19a96102018-11-15 13:38:09 +01002302 LYS_SET_TYPE /* LY_TYPE_UNION */,
2303 LYS_SET_RANGE /* LY_TYPE_INT8 */,
Radek Krejci19a96102018-11-15 13:38:09 +01002304 LYS_SET_RANGE /* LY_TYPE_INT16 */,
Radek Krejci19a96102018-11-15 13:38:09 +01002305 LYS_SET_RANGE /* LY_TYPE_INT32 */,
Radek Krejci5969f272018-11-23 10:03:58 +01002306 LYS_SET_RANGE /* LY_TYPE_INT64 */
2307};
2308
2309/**
2310 * @brief stringification of the YANG built-in data types
2311 */
Michal Vasko69730152020-10-09 16:30:07 +02002312const char *ly_data_type2str[LY_DATA_TYPE_COUNT] = {
2313 "unknown", "binary", "8bit unsigned integer", "16bit unsigned integer",
Radek Krejci5969f272018-11-23 10:03:58 +01002314 "32bit unsigned integer", "64bit unsigned integer", "string", "bits", "boolean", "decimal64", "empty", "enumeration",
Michal Vasko69730152020-10-09 16:30:07 +02002315 "identityref", "instance-identifier", "leafref", "union", "8bit integer", "16bit integer", "32bit integer", "64bit integer"
2316};
Radek Krejci19a96102018-11-15 13:38:09 +01002317
Radek Krejcia3045382018-11-22 14:30:31 +01002318/**
2319 * @brief Compile parsed type's enum structures (for enumeration and bits types).
2320 * @param[in] ctx Compile context.
2321 * @param[in] enums_p Array of the parsed enum structures to compile.
2322 * @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.
Radek Krejcia3045382018-11-22 14:30:31 +01002323 * @param[in] base_enums Array of the compiled enums information from the (latest) base type to check if the current enums are compatible.
2324 * @param[out] enums Newly created array of the compiled enums information for the current type.
2325 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
2326 */
Radek Krejci19a96102018-11-15 13:38:09 +01002327static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02002328lys_compile_type_enums(struct lysc_ctx *ctx, struct lysp_type_enum *enums_p, LY_DATA_TYPE basetype,
Radek Krejci0f969882020-08-21 16:56:47 +02002329 struct lysc_type_bitenum_item *base_enums, struct lysc_type_bitenum_item **enums)
Radek Krejci19a96102018-11-15 13:38:09 +01002330{
2331 LY_ERR ret = LY_SUCCESS;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002332 LY_ARRAY_COUNT_TYPE u, v, match = 0;
Radek Krejci19a96102018-11-15 13:38:09 +01002333 int32_t value = 0;
2334 uint32_t position = 0;
Radek Krejci693262f2019-04-29 15:23:20 +02002335 struct lysc_type_bitenum_item *e, storage;
Radek Krejci19a96102018-11-15 13:38:09 +01002336
Michal Vasko69730152020-10-09 16:30:07 +02002337 if (base_enums && (ctx->mod_def->version < 2)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002338 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "%s type can be subtyped only in YANG 1.1 modules.",
Michal Vasko69730152020-10-09 16:30:07 +02002339 basetype == LY_TYPE_ENUM ? "Enumeration" : "Bits");
Radek Krejci19a96102018-11-15 13:38:09 +01002340 return LY_EVALID;
2341 }
2342
2343 LY_ARRAY_FOR(enums_p, u) {
2344 LY_ARRAY_NEW_RET(ctx->ctx, *enums, e, LY_EMEM);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002345 DUP_STRING_GOTO(ctx->ctx, enums_p[u].name, e->name, ret, done);
2346 DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->dsc, ret, done);
2347 DUP_STRING_GOTO(ctx->ctx, enums_p[u].ref, e->ref, ret, done);
Radek Krejci693262f2019-04-29 15:23:20 +02002348 e->flags = enums_p[u].flags & LYS_FLAGS_COMPILED_MASK;
Radek Krejci19a96102018-11-15 13:38:09 +01002349 if (base_enums) {
2350 /* check the enum/bit presence in the base type - the set of enums/bits in the derived type must be a subset */
2351 LY_ARRAY_FOR(base_enums, v) {
2352 if (!strcmp(e->name, base_enums[v].name)) {
2353 break;
2354 }
2355 }
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002356 if (v == LY_ARRAY_COUNT(base_enums)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002357 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002358 "Invalid %s - derived type adds new item \"%s\".",
2359 basetype == LY_TYPE_ENUM ? "enumeration" : "bits", e->name);
Radek Krejci19a96102018-11-15 13:38:09 +01002360 return LY_EVALID;
2361 }
2362 match = v;
2363 }
2364
2365 if (basetype == LY_TYPE_ENUM) {
Radek Krejci693262f2019-04-29 15:23:20 +02002366 e->flags |= LYS_ISENUM;
Radek Krejci19a96102018-11-15 13:38:09 +01002367 if (enums_p[u].flags & LYS_SET_VALUE) {
2368 e->value = (int32_t)enums_p[u].value;
Michal Vasko69730152020-10-09 16:30:07 +02002369 if (!u || (e->value >= value)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002370 value = e->value + 1;
2371 }
2372 /* check collision with other values */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002373 for (v = 0; v < LY_ARRAY_COUNT(*enums) - 1; ++v) {
Radek Krejci19a96102018-11-15 13:38:09 +01002374 if (e->value == (*enums)[v].value) {
2375 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002376 "Invalid enumeration - value %d collide in items \"%s\" and \"%s\".",
2377 e->value, e->name, (*enums)[v].name);
Radek Krejci19a96102018-11-15 13:38:09 +01002378 return LY_EVALID;
2379 }
2380 }
2381 } else if (base_enums) {
2382 /* inherit the assigned value */
2383 e->value = base_enums[match].value;
Michal Vasko69730152020-10-09 16:30:07 +02002384 if (!u || (e->value >= value)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002385 value = e->value + 1;
2386 }
2387 } else {
2388 /* assign value automatically */
Michal Vasko69730152020-10-09 16:30:07 +02002389 if (u && (value == INT32_MIN)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002390 /* counter overflow */
2391 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002392 "Invalid enumeration - it is not possible to auto-assign enum value for "
2393 "\"%s\" since the highest value is already 2147483647.", e->name);
Radek Krejci19a96102018-11-15 13:38:09 +01002394 return LY_EVALID;
2395 }
2396 e->value = value++;
2397 }
2398 } else { /* LY_TYPE_BITS */
2399 if (enums_p[u].flags & LYS_SET_VALUE) {
2400 e->value = (int32_t)enums_p[u].value;
Michal Vasko69730152020-10-09 16:30:07 +02002401 if (!u || ((uint32_t)e->value >= position)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002402 position = (uint32_t)e->value + 1;
2403 }
2404 /* check collision with other values */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002405 for (v = 0; v < LY_ARRAY_COUNT(*enums) - 1; ++v) {
Radek Krejci19a96102018-11-15 13:38:09 +01002406 if (e->value == (*enums)[v].value) {
2407 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002408 "Invalid bits - position %u collide in items \"%s\" and \"%s\".",
Radek Krejci0f969882020-08-21 16:56:47 +02002409 (uint32_t)e->value, e->name, (*enums)[v].name);
Radek Krejci19a96102018-11-15 13:38:09 +01002410 return LY_EVALID;
2411 }
2412 }
2413 } else if (base_enums) {
2414 /* inherit the assigned value */
2415 e->value = base_enums[match].value;
Michal Vasko69730152020-10-09 16:30:07 +02002416 if (!u || ((uint32_t)e->value >= position)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002417 position = (uint32_t)e->value + 1;
2418 }
2419 } else {
2420 /* assign value automatically */
Michal Vasko69730152020-10-09 16:30:07 +02002421 if (u && (position == 0)) {
Radek Krejci19a96102018-11-15 13:38:09 +01002422 /* counter overflow */
2423 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002424 "Invalid bits - it is not possible to auto-assign bit position for "
2425 "\"%s\" since the highest value is already 4294967295.", e->name);
Radek Krejci19a96102018-11-15 13:38:09 +01002426 return LY_EVALID;
2427 }
2428 e->value = position++;
2429 }
2430 }
2431
2432 if (base_enums) {
2433 /* the assigned values must not change from the derived type */
2434 if (e->value != base_enums[match].value) {
2435 if (basetype == LY_TYPE_ENUM) {
2436 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002437 "Invalid enumeration - value of the item \"%s\" has changed from %d to %d in the derived type.",
2438 e->name, base_enums[match].value, e->value);
Radek Krejci19a96102018-11-15 13:38:09 +01002439 } else {
2440 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002441 "Invalid bits - position of the item \"%s\" has changed from %u to %u in the derived type.",
2442 e->name, (uint32_t)base_enums[match].value, (uint32_t)e->value);
Radek Krejci19a96102018-11-15 13:38:09 +01002443 }
2444 return LY_EVALID;
2445 }
2446 }
2447
Radek Krejciec4da802019-05-02 13:02:41 +02002448 COMPILE_ARRAY_GOTO(ctx, enums_p[u].iffeatures, e->iffeatures, v, lys_compile_iffeature, ret, done);
Radek Krejci0935f412019-08-20 16:15:18 +02002449 COMPILE_EXTS_GOTO(ctx, enums_p[u].exts, e->exts, e, basetype == LY_TYPE_ENUM ? LYEXT_PAR_TYPE_ENUM : LYEXT_PAR_TYPE_BIT, ret, done);
Radek Krejci19a96102018-11-15 13:38:09 +01002450
2451 if (basetype == LY_TYPE_BITS) {
2452 /* keep bits ordered by position */
Radek Krejci1e008d22020-08-17 11:37:37 +02002453 for (v = u; v && (*enums)[v - 1].value > e->value; --v) {}
Radek Krejci19a96102018-11-15 13:38:09 +01002454 if (v != u) {
2455 memcpy(&storage, e, sizeof *e);
2456 memmove(&(*enums)[v + 1], &(*enums)[v], (u - v) * sizeof **enums);
2457 memcpy(&(*enums)[v], &storage, sizeof storage);
2458 }
2459 }
2460 }
2461
2462done:
2463 return ret;
2464}
2465
Radek Krejcia3045382018-11-22 14:30:31 +01002466/**
2467 * @brief Parse path-arg (leafref). Get tokens of the path by repetitive calls of the function.
2468 *
2469 * path-arg = absolute-path / relative-path
2470 * absolute-path = 1*("/" (node-identifier *path-predicate))
2471 * relative-path = 1*(".." "/") descendant-path
2472 *
2473 * @param[in,out] path Path to parse.
2474 * @param[out] prefix Prefix of the token, NULL if there is not any.
2475 * @param[out] pref_len Length of the prefix, 0 if there is not any.
2476 * @param[out] name Name of the token.
2477 * @param[out] nam_len Length of the name.
2478 * @param[out] parent_times Number of leading ".." in the path. Must be 0 on the first call,
2479 * must not be changed between consecutive calls. -1 if the
2480 * path is absolute.
2481 * @param[out] has_predicate Flag to mark whether there is a predicate specified.
2482 * @return LY_ERR value: LY_SUCCESS or LY_EINVAL in case of invalid character in the path.
2483 */
Radek Krejci2d7a47b2019-05-16 13:34:10 +02002484LY_ERR
Radek Krejcia3045382018-11-22 14:30:31 +01002485lys_path_token(const char **path, const char **prefix, size_t *prefix_len, const char **name, size_t *name_len,
Radek Krejci857189e2020-09-01 13:26:36 +02002486 int32_t *parent_times, ly_bool *has_predicate)
Radek Krejcia3045382018-11-22 14:30:31 +01002487{
Radek Krejci1deb5be2020-08-26 16:43:36 +02002488 int32_t par_times = 0;
Radek Krejcia3045382018-11-22 14:30:31 +01002489
2490 assert(path && *path);
2491 assert(parent_times);
2492 assert(prefix);
2493 assert(prefix_len);
2494 assert(name);
2495 assert(name_len);
2496 assert(has_predicate);
2497
2498 *prefix = NULL;
2499 *prefix_len = 0;
2500 *name = NULL;
2501 *name_len = 0;
2502 *has_predicate = 0;
2503
2504 if (!*parent_times) {
2505 if (!strncmp(*path, "..", 2)) {
2506 *path += 2;
2507 ++par_times;
2508 while (!strncmp(*path, "/..", 3)) {
2509 *path += 3;
2510 ++par_times;
2511 }
2512 }
2513 if (par_times) {
2514 *parent_times = par_times;
2515 } else {
2516 *parent_times = -1;
2517 }
2518 }
2519
2520 if (**path != '/') {
2521 return LY_EINVAL;
2522 }
2523 /* skip '/' */
2524 ++(*path);
2525
2526 /* node-identifier ([prefix:]name) */
Radek Krejcib4a4a272019-06-10 12:44:52 +02002527 LY_CHECK_RET(ly_parse_nodeid(path, prefix, prefix_len, name, name_len));
Radek Krejcia3045382018-11-22 14:30:31 +01002528
Michal Vasko69730152020-10-09 16:30:07 +02002529 if (((**path == '/') && (*path)[1]) || !**path) {
Radek Krejcia3045382018-11-22 14:30:31 +01002530 /* path continues by another token or this is the last token */
2531 return LY_SUCCESS;
2532 } else if ((*path)[0] != '[') {
2533 /* unexpected character */
2534 return LY_EINVAL;
2535 } else {
2536 /* predicate starting with [ */
2537 *has_predicate = 1;
2538 return LY_SUCCESS;
2539 }
2540}
2541
2542/**
Radek Krejci58d171e2018-11-23 13:50:55 +01002543 * @brief Check the features used in if-feature statements applicable to the leafref and its target.
2544 *
2545 * The set of features used for target must be a subset of features used for the leafref.
2546 * This is not a perfect, we should compare the truth tables but it could require too much resources
2547 * and RFC 7950 does not require it explicitely, so we simplify that.
2548 *
2549 * @param[in] refnode The leafref node.
2550 * @param[in] target Tha target node of the leafref.
2551 * @return LY_SUCCESS or LY_EVALID;
2552 */
2553static LY_ERR
2554lys_compile_leafref_features_validate(const struct lysc_node *refnode, const struct lysc_node *target)
2555{
2556 LY_ERR ret = LY_EVALID;
2557 const struct lysc_node *iter;
Radek Krejci1deb5be2020-08-26 16:43:36 +02002558 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci58d171e2018-11-23 13:50:55 +01002559 struct ly_set features = {0};
2560
2561 for (iter = refnode; iter; iter = iter->parent) {
Radek Krejci056d0a82018-12-06 16:57:25 +01002562 if (iter->iffeatures) {
2563 LY_ARRAY_FOR(iter->iffeatures, u) {
2564 LY_ARRAY_FOR(iter->iffeatures[u].features, v) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02002565 LY_CHECK_GOTO(ly_set_add(&features, iter->iffeatures[u].features[v], 0, NULL), cleanup);
Radek Krejci58d171e2018-11-23 13:50:55 +01002566 }
2567 }
2568 }
2569 }
2570
2571 /* we should have, in features set, a superset of features applicable to the target node.
Radek Krejciba03a5a2020-08-27 14:40:41 +02002572 * If the feature is not present, we don;t have a subset of features applicable
Radek Krejci58d171e2018-11-23 13:50:55 +01002573 * to the leafref itself. */
Radek Krejci58d171e2018-11-23 13:50:55 +01002574 for (iter = target; iter; iter = iter->parent) {
Radek Krejci056d0a82018-12-06 16:57:25 +01002575 if (iter->iffeatures) {
2576 LY_ARRAY_FOR(iter->iffeatures, u) {
2577 LY_ARRAY_FOR(iter->iffeatures[u].features, v) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02002578 if (!ly_set_contains(&features, iter->iffeatures[u].features[v], NULL)) {
2579 /* feature not present */
Radek Krejci58d171e2018-11-23 13:50:55 +01002580 goto cleanup;
2581 }
2582 }
2583 }
2584 }
2585 }
2586 ret = LY_SUCCESS;
2587
2588cleanup:
2589 ly_set_erase(&features, NULL);
2590 return ret;
2591}
2592
Michal Vasko7f45cf22020-10-01 12:49:44 +02002593static LY_ERR lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags,
Radek Krejci0f969882020-08-21 16:56:47 +02002594 struct lysp_module *context_mod, const char *context_name, struct lysp_type *type_p,
Michal Vasko7f45cf22020-10-01 12:49:44 +02002595 struct lysc_type **type, const char **units, struct lysp_qname **dflt);
Radek Krejcia3045382018-11-22 14:30:31 +01002596
Radek Krejcia3045382018-11-22 14:30:31 +01002597/**
2598 * @brief The core of the lys_compile_type() - compile information about the given type (from typedef or leaf/leaf-list).
2599 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02002600 * @param[in] context_pnode Schema node where the type/typedef is placed to correctly find the base types.
Radek Krejcicdfecd92018-11-26 11:27:32 +01002601 * @param[in] context_flags Flags of the context node or the referencing typedef to correctly check status of referencing and referenced objects.
2602 * @param[in] context_mod Module of the context node or the referencing typedef to correctly check status of referencing and referenced objects.
2603 * @param[in] context_name Name of the context node or referencing typedef for logging.
Radek Krejcia3045382018-11-22 14:30:31 +01002604 * @param[in] type_p Parsed type to compile.
2605 * @param[in] basetype Base YANG built-in type of the type to compile.
Radek Krejcia3045382018-11-22 14:30:31 +01002606 * @param[in] tpdfname Name of the type's typedef, serves as a flag - if it is leaf/leaf-list's type, it is NULL.
2607 * @param[in] base The latest base (compiled) type from which the current type is being derived.
2608 * @param[out] type Newly created type structure with the filled information about the type.
2609 * @return LY_ERR value.
2610 */
Radek Krejci19a96102018-11-15 13:38:09 +01002611static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02002612lys_compile_type_(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags,
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002613 struct lysp_module *context_mod, const char *context_name, struct lysp_type *type_p, LY_DATA_TYPE basetype,
2614 const char *tpdfname, struct lysc_type *base, struct lysc_type **type)
Radek Krejcic5c27e52018-11-15 14:38:11 +01002615{
2616 LY_ERR ret = LY_SUCCESS;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002617 struct lysc_type_bin *bin;
2618 struct lysc_type_num *num;
2619 struct lysc_type_str *str;
2620 struct lysc_type_bits *bits;
2621 struct lysc_type_enum *enumeration;
Radek Krejci6cba4292018-11-15 17:33:29 +01002622 struct lysc_type_dec *dec;
Radek Krejci555cb5b2018-11-16 14:54:33 +01002623 struct lysc_type_identityref *idref;
Michal Vasko004d3152020-06-11 19:59:22 +02002624 struct lysc_type_leafref *lref;
Radek Krejcicdfecd92018-11-26 11:27:32 +01002625 struct lysc_type_union *un, *un_aux;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002626
2627 switch (basetype) {
2628 case LY_TYPE_BINARY:
Michal Vasko22df3f02020-08-24 13:29:22 +02002629 bin = (struct lysc_type_bin *)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002630
2631 /* RFC 7950 9.8.1, 9.4.4 - length, number of octets it contains */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002632 if (type_p->length) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02002633 LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002634 base ? ((struct lysc_type_bin *)base)->length : NULL, &bin->length));
Radek Krejcic5c27e52018-11-15 14:38:11 +01002635 if (!tpdfname) {
Michal Vasko1734be92020-09-22 08:55:10 +02002636 COMPILE_EXTS_GOTO(ctx, type_p->length->exts, bin->length->exts, bin->length, LYEXT_PAR_LENGTH, ret, cleanup);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002637 }
2638 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002639 break;
2640 case LY_TYPE_BITS:
2641 /* RFC 7950 9.7 - bits */
Michal Vasko22df3f02020-08-24 13:29:22 +02002642 bits = (struct lysc_type_bits *)(*type);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002643 if (type_p->bits) {
Radek Krejciec4da802019-05-02 13:02:41 +02002644 LY_CHECK_RET(lys_compile_type_enums(ctx, type_p->bits, basetype,
Michal Vasko69730152020-10-09 16:30:07 +02002645 base ? (struct lysc_type_bitenum_item *)((struct lysc_type_bits *)base)->bits : NULL,
Michal Vasko22df3f02020-08-24 13:29:22 +02002646 (struct lysc_type_bitenum_item **)&bits->bits));
Radek Krejcic5c27e52018-11-15 14:38:11 +01002647 }
2648
Radek Krejci555cb5b2018-11-16 14:54:33 +01002649 if (!base && !type_p->flags) {
Radek Krejcic5c27e52018-11-15 14:38:11 +01002650 /* type derived from bits built-in type must contain at least one bit */
Radek Krejci6cba4292018-11-15 17:33:29 +01002651 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002652 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type ", tpdfname);
Radek Krejci6cba4292018-11-15 17:33:29 +01002653 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002654 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "bit", "bits type", "");
Radek Krejcic5c27e52018-11-15 14:38:11 +01002655 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002656 return LY_EVALID;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002657 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002658 break;
Radek Krejci6cba4292018-11-15 17:33:29 +01002659 case LY_TYPE_DEC64:
Radek Krejci115a74d2020-08-14 22:18:12 +02002660 dec = (struct lysc_type_dec *)(*type);
Radek Krejci6cba4292018-11-15 17:33:29 +01002661
2662 /* RFC 7950 9.3.4 - fraction-digits */
Radek Krejci555cb5b2018-11-16 14:54:33 +01002663 if (!base) {
Radek Krejci643c8242018-11-15 17:51:11 +01002664 if (!type_p->fraction_digits) {
2665 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002666 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type ", tpdfname);
Radek Krejci643c8242018-11-15 17:51:11 +01002667 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002668 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "fraction-digits", "decimal64 type", "");
Radek Krejci643c8242018-11-15 17:51:11 +01002669 }
2670 return LY_EVALID;
2671 }
Radek Krejci115a74d2020-08-14 22:18:12 +02002672 dec->fraction_digits = type_p->fraction_digits;
2673 } else {
2674 if (type_p->fraction_digits) {
2675 /* fraction digits is prohibited in types not directly derived from built-in decimal64 */
2676 if (tpdfname) {
2677 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002678 "Invalid fraction-digits substatement for type \"%s\" not directly derived from decimal64 built-in type.",
2679 tpdfname);
Radek Krejci115a74d2020-08-14 22:18:12 +02002680 } else {
2681 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002682 "Invalid fraction-digits substatement for type not directly derived from decimal64 built-in type.");
Radek Krejci115a74d2020-08-14 22:18:12 +02002683 }
2684 return LY_EVALID;
Radek Krejci6cba4292018-11-15 17:33:29 +01002685 }
Radek Krejci115a74d2020-08-14 22:18:12 +02002686 dec->fraction_digits = ((struct lysc_type_dec *)base)->fraction_digits;
Radek Krejci6cba4292018-11-15 17:33:29 +01002687 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002688
2689 /* RFC 7950 9.2.4 - range */
2690 if (type_p->range) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02002691 LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, dec->fraction_digits,
Michal Vasko69730152020-10-09 16:30:07 +02002692 base ? ((struct lysc_type_dec *)base)->range : NULL, &dec->range));
Radek Krejci6cba4292018-11-15 17:33:29 +01002693 if (!tpdfname) {
Michal Vasko1734be92020-09-22 08:55:10 +02002694 COMPILE_EXTS_GOTO(ctx, type_p->range->exts, dec->range->exts, dec->range, LYEXT_PAR_RANGE, ret, cleanup);
Radek Krejci6cba4292018-11-15 17:33:29 +01002695 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002696 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002697 break;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002698 case LY_TYPE_STRING:
Michal Vasko22df3f02020-08-24 13:29:22 +02002699 str = (struct lysc_type_str *)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002700
2701 /* RFC 7950 9.4.4 - length */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002702 if (type_p->length) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02002703 LY_CHECK_RET(lys_compile_type_range(ctx, type_p->length, basetype, 1, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002704 base ? ((struct lysc_type_str *)base)->length : NULL, &str->length));
Radek Krejcic5c27e52018-11-15 14:38:11 +01002705 if (!tpdfname) {
Michal Vasko1734be92020-09-22 08:55:10 +02002706 COMPILE_EXTS_GOTO(ctx, type_p->length->exts, str->length->exts, str->length, LYEXT_PAR_LENGTH, ret, cleanup);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002707 }
Michal Vasko22df3f02020-08-24 13:29:22 +02002708 } else if (base && ((struct lysc_type_str *)base)->length) {
2709 str->length = lysc_range_dup(ctx->ctx, ((struct lysc_type_str *)base)->length);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002710 }
2711
2712 /* RFC 7950 9.4.5 - pattern */
2713 if (type_p->patterns) {
Radek Krejciec4da802019-05-02 13:02:41 +02002714 LY_CHECK_RET(lys_compile_type_patterns(ctx, type_p->patterns,
Michal Vasko69730152020-10-09 16:30:07 +02002715 base ? ((struct lysc_type_str *)base)->patterns : NULL, &str->patterns));
Michal Vasko22df3f02020-08-24 13:29:22 +02002716 } else if (base && ((struct lysc_type_str *)base)->patterns) {
2717 str->patterns = lysc_patterns_dup(ctx->ctx, ((struct lysc_type_str *)base)->patterns);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002718 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002719 break;
2720 case LY_TYPE_ENUM:
Michal Vasko22df3f02020-08-24 13:29:22 +02002721 enumeration = (struct lysc_type_enum *)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002722
2723 /* RFC 7950 9.6 - enum */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002724 if (type_p->enums) {
Radek Krejciec4da802019-05-02 13:02:41 +02002725 LY_CHECK_RET(lys_compile_type_enums(ctx, type_p->enums, basetype,
Michal Vasko69730152020-10-09 16:30:07 +02002726 base ? ((struct lysc_type_enum *)base)->enums : NULL, &enumeration->enums));
Radek Krejcic5c27e52018-11-15 14:38:11 +01002727 }
2728
Radek Krejci555cb5b2018-11-16 14:54:33 +01002729 if (!base && !type_p->flags) {
Radek Krejcic5c27e52018-11-15 14:38:11 +01002730 /* type derived from enumerations built-in type must contain at least one enum */
Radek Krejci6cba4292018-11-15 17:33:29 +01002731 if (tpdfname) {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002732 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type ", tpdfname);
Radek Krejci6cba4292018-11-15 17:33:29 +01002733 } else {
Radek Krejci555cb5b2018-11-16 14:54:33 +01002734 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "enum", "enumeration type", "");
Radek Krejcic5c27e52018-11-15 14:38:11 +01002735 }
Radek Krejci6cba4292018-11-15 17:33:29 +01002736 return LY_EVALID;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002737 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002738 break;
2739 case LY_TYPE_INT8:
2740 case LY_TYPE_UINT8:
2741 case LY_TYPE_INT16:
2742 case LY_TYPE_UINT16:
2743 case LY_TYPE_INT32:
2744 case LY_TYPE_UINT32:
2745 case LY_TYPE_INT64:
2746 case LY_TYPE_UINT64:
Michal Vasko22df3f02020-08-24 13:29:22 +02002747 num = (struct lysc_type_num *)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002748
2749 /* RFC 6020 9.2.4 - range */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002750 if (type_p->range) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02002751 LY_CHECK_RET(lys_compile_type_range(ctx, type_p->range, basetype, 0, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002752 base ? ((struct lysc_type_num *)base)->range : NULL, &num->range));
Radek Krejcic5c27e52018-11-15 14:38:11 +01002753 if (!tpdfname) {
Michal Vasko1734be92020-09-22 08:55:10 +02002754 COMPILE_EXTS_GOTO(ctx, type_p->range->exts, num->range->exts, num->range, LYEXT_PAR_RANGE, ret, cleanup);
Radek Krejcic5c27e52018-11-15 14:38:11 +01002755 }
2756 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002757 break;
Radek Krejci555cb5b2018-11-16 14:54:33 +01002758 case LY_TYPE_IDENT:
Michal Vasko22df3f02020-08-24 13:29:22 +02002759 idref = (struct lysc_type_identityref *)(*type);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002760
2761 /* RFC 7950 9.10.2 - base */
2762 if (type_p->bases) {
2763 if (base) {
2764 /* only the directly derived identityrefs can contain base specification */
2765 if (tpdfname) {
2766 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002767 "Invalid base substatement for the type \"%s\" not directly derived from identityref built-in type.",
2768 tpdfname);
Radek Krejci555cb5b2018-11-16 14:54:33 +01002769 } else {
2770 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002771 "Invalid base substatement for the type not directly derived from identityref built-in type.");
Radek Krejci555cb5b2018-11-16 14:54:33 +01002772 }
2773 return LY_EVALID;
2774 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002775 LY_CHECK_RET(lys_compile_identity_bases(ctx, type_p->mod, type_p->bases, NULL, &idref->bases));
Radek Krejci555cb5b2018-11-16 14:54:33 +01002776 }
2777
2778 if (!base && !type_p->flags) {
2779 /* type derived from identityref built-in type must contain at least one base */
2780 if (tpdfname) {
2781 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type ", tpdfname);
2782 } else {
2783 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "base", "identityref type", "");
Radek Krejci555cb5b2018-11-16 14:54:33 +01002784 }
2785 return LY_EVALID;
2786 }
Radek Krejci555cb5b2018-11-16 14:54:33 +01002787 break;
Radek Krejcia3045382018-11-22 14:30:31 +01002788 case LY_TYPE_LEAFREF:
Michal Vasko22df3f02020-08-24 13:29:22 +02002789 lref = (struct lysc_type_leafref *)*type;
Michal Vasko004d3152020-06-11 19:59:22 +02002790
Radek Krejcia3045382018-11-22 14:30:31 +01002791 /* RFC 7950 9.9.3 - require-instance */
2792 if (type_p->flags & LYS_SET_REQINST) {
Radek Krejci0bcdaed2019-01-10 10:21:34 +01002793 if (context_mod->mod->version < LYS_VERSION_1_1) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01002794 if (tpdfname) {
2795 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02002796 "Leafref type \"%s\" can be restricted by require-instance statement only in YANG 1.1 modules.", tpdfname);
Radek Krejci9bb94eb2018-12-04 16:48:35 +01002797 } else {
2798 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02002799 "Leafref type can be restricted by require-instance statement only in YANG 1.1 modules.");
Radek Krejci9bb94eb2018-12-04 16:48:35 +01002800 }
2801 return LY_EVALID;
2802 }
Michal Vasko004d3152020-06-11 19:59:22 +02002803 lref->require_instance = type_p->require_instance;
Radek Krejci412ddfa2018-11-23 11:44:11 +01002804 } else if (base) {
2805 /* inherit */
Michal Vasko004d3152020-06-11 19:59:22 +02002806 lref->require_instance = ((struct lysc_type_leafref *)base)->require_instance;
Radek Krejcia3045382018-11-22 14:30:31 +01002807 } else {
2808 /* default is true */
Michal Vasko004d3152020-06-11 19:59:22 +02002809 lref->require_instance = 1;
Radek Krejcia3045382018-11-22 14:30:31 +01002810 }
2811 if (type_p->path) {
Michal Vasko1734be92020-09-22 08:55:10 +02002812 LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, type_p->path, &lref->path));
Michal Vaskoe9c050f2020-10-06 14:01:23 +02002813 lref->path_mod = type_p->mod;
Radek Krejcia3045382018-11-22 14:30:31 +01002814 } else if (base) {
Michal Vasko1734be92020-09-22 08:55:10 +02002815 LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)base)->path, &lref->path));
Michal Vasko72619ce2020-10-06 14:05:32 +02002816 lref->path_mod = ((struct lysc_type_leafref *)base)->path_mod;
Radek Krejcia3045382018-11-22 14:30:31 +01002817 } else if (tpdfname) {
2818 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type ", tpdfname);
2819 return LY_EVALID;
2820 } else {
2821 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "path", "leafref type", "");
Radek Krejcia3045382018-11-22 14:30:31 +01002822 return LY_EVALID;
2823 }
Radek Krejcia3045382018-11-22 14:30:31 +01002824 break;
Radek Krejci16c0f822018-11-16 10:46:10 +01002825 case LY_TYPE_INST:
2826 /* RFC 7950 9.9.3 - require-instance */
2827 if (type_p->flags & LYS_SET_REQINST) {
Michal Vasko22df3f02020-08-24 13:29:22 +02002828 ((struct lysc_type_instanceid *)(*type))->require_instance = type_p->require_instance;
Radek Krejci16c0f822018-11-16 10:46:10 +01002829 } else {
2830 /* default is true */
Michal Vasko22df3f02020-08-24 13:29:22 +02002831 ((struct lysc_type_instanceid *)(*type))->require_instance = 1;
Radek Krejci16c0f822018-11-16 10:46:10 +01002832 }
Radek Krejci16c0f822018-11-16 10:46:10 +01002833 break;
Radek Krejcicdfecd92018-11-26 11:27:32 +01002834 case LY_TYPE_UNION:
Michal Vasko22df3f02020-08-24 13:29:22 +02002835 un = (struct lysc_type_union *)(*type);
Radek Krejcicdfecd92018-11-26 11:27:32 +01002836
2837 /* RFC 7950 7.4 - type */
2838 if (type_p->types) {
2839 if (base) {
2840 /* only the directly derived union can contain types specification */
2841 if (tpdfname) {
2842 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002843 "Invalid type substatement for the type \"%s\" not directly derived from union built-in type.",
2844 tpdfname);
Radek Krejcicdfecd92018-11-26 11:27:32 +01002845 } else {
2846 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG,
Michal Vasko69730152020-10-09 16:30:07 +02002847 "Invalid type substatement for the type not directly derived from union built-in type.");
Radek Krejcicdfecd92018-11-26 11:27:32 +01002848 }
2849 return LY_EVALID;
2850 }
2851 /* compile the type */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002852 LY_ARRAY_CREATE_RET(ctx->ctx, un->types, LY_ARRAY_COUNT(type_p->types), LY_EVALID);
2853 for (LY_ARRAY_COUNT_TYPE u = 0, additional = 0; u < LY_ARRAY_COUNT(type_p->types); ++u) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02002854 LY_CHECK_RET(lys_compile_type(ctx, context_pnode, context_flags, context_mod, context_name,
Michal Vasko69730152020-10-09 16:30:07 +02002855 &type_p->types[u], &un->types[u + additional], NULL, NULL));
Radek Krejcicdfecd92018-11-26 11:27:32 +01002856 if (un->types[u + additional]->basetype == LY_TYPE_UNION) {
2857 /* add space for additional types from the union subtype */
2858 un_aux = (struct lysc_type_union *)un->types[u + additional];
Michal Vasko22df3f02020-08-24 13:29:22 +02002859 LY_ARRAY_RESIZE_ERR_RET(ctx->ctx, un->types, (*((uint64_t *)(type_p->types) - 1)) + additional + LY_ARRAY_COUNT(un_aux->types) - 1,
Michal Vasko69730152020-10-09 16:30:07 +02002860 lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux), LY_EMEM);
Radek Krejcicdfecd92018-11-26 11:27:32 +01002861
2862 /* copy subtypes of the subtype union */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002863 for (LY_ARRAY_COUNT_TYPE v = 0; v < LY_ARRAY_COUNT(un_aux->types); ++v) {
Radek Krejcicdfecd92018-11-26 11:27:32 +01002864 if (un_aux->types[v]->basetype == LY_TYPE_LEAFREF) {
2865 /* duplicate the whole structure because of the instance-specific path resolving for realtype */
2866 un->types[u + additional] = calloc(1, sizeof(struct lysc_type_leafref));
Michal Vasko22df3f02020-08-24 13:29:22 +02002867 LY_CHECK_ERR_RET(!un->types[u + additional], LOGMEM(ctx->ctx); lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux), LY_EMEM);
Michal Vasko004d3152020-06-11 19:59:22 +02002868 lref = (struct lysc_type_leafref *)un->types[u + additional];
2869
2870 lref->basetype = LY_TYPE_LEAFREF;
Michal Vasko1734be92020-09-22 08:55:10 +02002871 LY_CHECK_RET(lyxp_expr_dup(ctx->ctx, ((struct lysc_type_leafref *)un_aux->types[v])->path, &lref->path));
Michal Vasko004d3152020-06-11 19:59:22 +02002872 lref->refcount = 1;
Michal Vasko22df3f02020-08-24 13:29:22 +02002873 lref->require_instance = ((struct lysc_type_leafref *)un_aux->types[v])->require_instance;
Michal Vasko72619ce2020-10-06 14:05:32 +02002874 lref->path_mod = ((struct lysc_type_leafref *)un_aux->types[v])->path_mod;
Radek Krejcicdfecd92018-11-26 11:27:32 +01002875 /* TODO extensions */
2876
2877 } else {
2878 un->types[u + additional] = un_aux->types[v];
2879 ++un_aux->types[v]->refcount;
2880 }
2881 ++additional;
2882 LY_ARRAY_INCREMENT(un->types);
2883 }
2884 /* compensate u increment in main loop */
2885 --additional;
2886
2887 /* free the replaced union subtype */
Michal Vasko22df3f02020-08-24 13:29:22 +02002888 lysc_type_free(ctx->ctx, (struct lysc_type *)un_aux);
Radek Krejcicdfecd92018-11-26 11:27:32 +01002889 } else {
2890 LY_ARRAY_INCREMENT(un->types);
2891 }
Radek Krejcicdfecd92018-11-26 11:27:32 +01002892 }
2893 }
2894
2895 if (!base && !type_p->flags) {
2896 /* type derived from union built-in type must contain at least one type */
2897 if (tpdfname) {
2898 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "type", "union type ", tpdfname);
2899 } else {
2900 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_MISSCHILDSTMT, "type", "union type", "");
Radek Krejcicdfecd92018-11-26 11:27:32 +01002901 }
2902 return LY_EVALID;
2903 }
Radek Krejcicdfecd92018-11-26 11:27:32 +01002904 break;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002905 case LY_TYPE_BOOL:
2906 case LY_TYPE_EMPTY:
2907 case LY_TYPE_UNKNOWN: /* just to complete switch */
2908 break;
2909 }
Michal Vasko1734be92020-09-22 08:55:10 +02002910
2911 if (tpdfname) {
2912 switch (basetype) {
2913 case LY_TYPE_BINARY:
2914 type_p->compiled = *type;
2915 *type = calloc(1, sizeof(struct lysc_type_bin));
2916 break;
2917 case LY_TYPE_BITS:
2918 type_p->compiled = *type;
2919 *type = calloc(1, sizeof(struct lysc_type_bits));
2920 break;
2921 case LY_TYPE_DEC64:
2922 type_p->compiled = *type;
2923 *type = calloc(1, sizeof(struct lysc_type_dec));
2924 break;
2925 case LY_TYPE_STRING:
2926 type_p->compiled = *type;
2927 *type = calloc(1, sizeof(struct lysc_type_str));
2928 break;
2929 case LY_TYPE_ENUM:
2930 type_p->compiled = *type;
2931 *type = calloc(1, sizeof(struct lysc_type_enum));
2932 break;
2933 case LY_TYPE_INT8:
2934 case LY_TYPE_UINT8:
2935 case LY_TYPE_INT16:
2936 case LY_TYPE_UINT16:
2937 case LY_TYPE_INT32:
2938 case LY_TYPE_UINT32:
2939 case LY_TYPE_INT64:
2940 case LY_TYPE_UINT64:
2941 type_p->compiled = *type;
2942 *type = calloc(1, sizeof(struct lysc_type_num));
2943 break;
2944 case LY_TYPE_IDENT:
2945 type_p->compiled = *type;
2946 *type = calloc(1, sizeof(struct lysc_type_identityref));
2947 break;
2948 case LY_TYPE_LEAFREF:
2949 type_p->compiled = *type;
2950 *type = calloc(1, sizeof(struct lysc_type_leafref));
2951 break;
2952 case LY_TYPE_INST:
2953 type_p->compiled = *type;
2954 *type = calloc(1, sizeof(struct lysc_type_instanceid));
2955 break;
2956 case LY_TYPE_UNION:
2957 type_p->compiled = *type;
2958 *type = calloc(1, sizeof(struct lysc_type_union));
2959 break;
2960 case LY_TYPE_BOOL:
2961 case LY_TYPE_EMPTY:
2962 case LY_TYPE_UNKNOWN: /* just to complete switch */
2963 break;
2964 }
2965 }
Radek Krejcic5c27e52018-11-15 14:38:11 +01002966 LY_CHECK_ERR_RET(!(*type), LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko1734be92020-09-22 08:55:10 +02002967
2968cleanup:
Radek Krejcic5c27e52018-11-15 14:38:11 +01002969 return ret;
2970}
2971
Radek Krejcia3045382018-11-22 14:30:31 +01002972/**
2973 * @brief Compile information about the leaf/leaf-list's type.
2974 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02002975 * @param[in] context_pnode Schema node where the type/typedef is placed to correctly find the base types.
Radek Krejcicdfecd92018-11-26 11:27:32 +01002976 * @param[in] context_flags Flags of the context node or the referencing typedef to correctly check status of referencing and referenced objects.
2977 * @param[in] context_mod Module of the context node or the referencing typedef to correctly check status of referencing and referenced objects.
2978 * @param[in] context_name Name of the context node or referencing typedef for logging.
2979 * @param[in] type_p Parsed type to compile.
Radek Krejcia3045382018-11-22 14:30:31 +01002980 * @param[out] type Newly created (or reused with increased refcount) type structure with the filled information about the type.
Radek Krejcicdfecd92018-11-26 11:27:32 +01002981 * @param[out] units Storage for inheriting units value from the typedefs the current type derives from.
Michal Vaskoba99a3e2020-08-18 15:50:05 +02002982 * @param[out] dflt Default value for the type.
Radek Krejcia3045382018-11-22 14:30:31 +01002983 * @return LY_ERR value.
2984 */
Radek Krejcic5c27e52018-11-15 14:38:11 +01002985static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02002986lys_compile_type(struct lysc_ctx *ctx, struct lysp_node *context_pnode, uint16_t context_flags,
Radek Krejci0f969882020-08-21 16:56:47 +02002987 struct lysp_module *context_mod, const char *context_name, struct lysp_type *type_p,
Michal Vasko7f45cf22020-10-01 12:49:44 +02002988 struct lysc_type **type, const char **units, struct lysp_qname **dflt)
Radek Krejci19a96102018-11-15 13:38:09 +01002989{
2990 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +02002991 ly_bool dummyloops = 0;
Radek Krejci19a96102018-11-15 13:38:09 +01002992 struct type_context {
2993 const struct lysp_tpdf *tpdf;
2994 struct lysp_node *node;
2995 struct lysp_module *mod;
Radek Krejci99b5b2a2019-04-30 16:57:04 +02002996 } *tctx, *tctx_prev = NULL, *tctx_iter;
Radek Krejci19a96102018-11-15 13:38:09 +01002997 LY_DATA_TYPE basetype = LY_TYPE_UNKNOWN;
Radek Krejcic5c27e52018-11-15 14:38:11 +01002998 struct lysc_type *base = NULL, *prev_type;
Radek Krejci19a96102018-11-15 13:38:09 +01002999 struct ly_set tpdf_chain = {0};
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003000
Radek Krejci19a96102018-11-15 13:38:09 +01003001 (*type) = NULL;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003002 if (dflt) {
3003 *dflt = NULL;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003004 }
Radek Krejci19a96102018-11-15 13:38:09 +01003005
3006 tctx = calloc(1, sizeof *tctx);
3007 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003008 for (ret = lysp_type_find(type_p->name, context_pnode, ctx->mod_def->parsed,
Michal Vasko69730152020-10-09 16:30:07 +02003009 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod);
Radek Krejci19a96102018-11-15 13:38:09 +01003010 ret == LY_SUCCESS;
3011 ret = lysp_type_find(tctx_prev->tpdf->type.name, tctx_prev->node, tctx_prev->mod,
Michal Vasko69730152020-10-09 16:30:07 +02003012 &basetype, &tctx->tpdf, &tctx->node, &tctx->mod)) {
Radek Krejci19a96102018-11-15 13:38:09 +01003013 if (basetype) {
3014 break;
3015 }
3016
3017 /* check status */
Radek Krejcicdfecd92018-11-26 11:27:32 +01003018 ret = lysc_check_status(ctx, context_flags, context_mod, context_name,
Michal Vasko69730152020-10-09 16:30:07 +02003019 tctx->tpdf->flags, tctx->mod, tctx->node ? tctx->node->name : tctx->tpdf->name);
Radek Krejci87e25252020-09-15 13:28:31 +02003020 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01003021
Radek Krejcicdfecd92018-11-26 11:27:32 +01003022 if (units && !*units) {
3023 /* inherit units */
Radek Krejci87e25252020-09-15 13:28:31 +02003024 DUP_STRING(ctx->ctx, tctx->tpdf->units, *units, ret);
3025 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
Radek Krejcicdfecd92018-11-26 11:27:32 +01003026 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02003027 if (dflt && !*dflt && tctx->tpdf->dflt.str) {
Radek Krejcicdfecd92018-11-26 11:27:32 +01003028 /* inherit default */
Michal Vasko7f45cf22020-10-01 12:49:44 +02003029 *dflt = (struct lysp_qname *)&tctx->tpdf->dflt;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02003030 assert((*dflt)->mod);
Radek Krejcicdfecd92018-11-26 11:27:32 +01003031 }
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003032 if (dummyloops && (!units || *units) && dflt && *dflt) {
Michal Vasko22df3f02020-08-24 13:29:22 +02003033 basetype = ((struct type_context *)tpdf_chain.objs[tpdf_chain.count - 1])->tpdf->type.compiled->basetype;
Radek Krejcicdfecd92018-11-26 11:27:32 +01003034 break;
3035 }
3036
Radek Krejci19a96102018-11-15 13:38:09 +01003037 if (tctx->tpdf->type.compiled) {
Radek Krejcicdfecd92018-11-26 11:27:32 +01003038 /* it is not necessary to continue, the rest of the chain was already compiled,
3039 * but we still may need to inherit default and units values, so start dummy loops */
Radek Krejci19a96102018-11-15 13:38:09 +01003040 basetype = tctx->tpdf->type.compiled->basetype;
Radek Krejciba03a5a2020-08-27 14:40:41 +02003041 ret = ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST, NULL);
Radek Krejci87e25252020-09-15 13:28:31 +02003042 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003043
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003044 if ((units && !*units) || (dflt && !*dflt)) {
Radek Krejcicdfecd92018-11-26 11:27:32 +01003045 dummyloops = 1;
3046 goto preparenext;
3047 } else {
3048 tctx = NULL;
3049 break;
3050 }
Radek Krejci19a96102018-11-15 13:38:09 +01003051 }
3052
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003053 /* circular typedef reference detection */
Radek Krejci1deb5be2020-08-26 16:43:36 +02003054 for (uint32_t u = 0; u < tpdf_chain.count; u++) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003055 /* local part */
Michal Vasko22df3f02020-08-24 13:29:22 +02003056 tctx_iter = (struct type_context *)tpdf_chain.objs[u];
Michal Vasko69730152020-10-09 16:30:07 +02003057 if ((tctx_iter->mod == tctx->mod) && (tctx_iter->node == tctx->node) && (tctx_iter->tpdf == tctx->tpdf)) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003058 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003059 "Invalid \"%s\" type reference - circular chain of types detected.", tctx->tpdf->name);
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003060 free(tctx);
3061 ret = LY_EVALID;
3062 goto cleanup;
3063 }
3064 }
Radek Krejci1deb5be2020-08-26 16:43:36 +02003065 for (uint32_t u = 0; u < ctx->tpdf_chain.count; u++) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003066 /* global part for unions corner case */
Michal Vasko22df3f02020-08-24 13:29:22 +02003067 tctx_iter = (struct type_context *)ctx->tpdf_chain.objs[u];
Michal Vasko69730152020-10-09 16:30:07 +02003068 if ((tctx_iter->mod == tctx->mod) && (tctx_iter->node == tctx->node) && (tctx_iter->tpdf == tctx->tpdf)) {
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003069 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003070 "Invalid \"%s\" type reference - circular chain of types detected.", tctx->tpdf->name);
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003071 free(tctx);
3072 ret = LY_EVALID;
3073 goto cleanup;
3074 }
3075 }
3076
Radek Krejci19a96102018-11-15 13:38:09 +01003077 /* store information for the following processing */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003078 ret = ly_set_add(&tpdf_chain, tctx, LY_SET_OPT_USEASLIST, NULL);
Radek Krejci87e25252020-09-15 13:28:31 +02003079 LY_CHECK_ERR_GOTO(ret, free(tctx), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01003080
Radek Krejcicdfecd92018-11-26 11:27:32 +01003081preparenext:
Radek Krejci19a96102018-11-15 13:38:09 +01003082 /* prepare next loop */
3083 tctx_prev = tctx;
3084 tctx = calloc(1, sizeof *tctx);
3085 LY_CHECK_ERR_RET(!tctx, LOGMEM(ctx->ctx), LY_EMEM);
3086 }
3087 free(tctx);
3088
3089 /* allocate type according to the basetype */
3090 switch (basetype) {
3091 case LY_TYPE_BINARY:
3092 *type = calloc(1, sizeof(struct lysc_type_bin));
Radek Krejci19a96102018-11-15 13:38:09 +01003093 break;
3094 case LY_TYPE_BITS:
3095 *type = calloc(1, sizeof(struct lysc_type_bits));
Radek Krejci19a96102018-11-15 13:38:09 +01003096 break;
3097 case LY_TYPE_BOOL:
3098 case LY_TYPE_EMPTY:
3099 *type = calloc(1, sizeof(struct lysc_type));
3100 break;
3101 case LY_TYPE_DEC64:
3102 *type = calloc(1, sizeof(struct lysc_type_dec));
3103 break;
3104 case LY_TYPE_ENUM:
3105 *type = calloc(1, sizeof(struct lysc_type_enum));
Radek Krejci19a96102018-11-15 13:38:09 +01003106 break;
3107 case LY_TYPE_IDENT:
3108 *type = calloc(1, sizeof(struct lysc_type_identityref));
3109 break;
3110 case LY_TYPE_INST:
3111 *type = calloc(1, sizeof(struct lysc_type_instanceid));
3112 break;
3113 case LY_TYPE_LEAFREF:
3114 *type = calloc(1, sizeof(struct lysc_type_leafref));
3115 break;
3116 case LY_TYPE_STRING:
3117 *type = calloc(1, sizeof(struct lysc_type_str));
Radek Krejci19a96102018-11-15 13:38:09 +01003118 break;
3119 case LY_TYPE_UNION:
3120 *type = calloc(1, sizeof(struct lysc_type_union));
3121 break;
3122 case LY_TYPE_INT8:
3123 case LY_TYPE_UINT8:
3124 case LY_TYPE_INT16:
3125 case LY_TYPE_UINT16:
3126 case LY_TYPE_INT32:
3127 case LY_TYPE_UINT32:
3128 case LY_TYPE_INT64:
3129 case LY_TYPE_UINT64:
3130 *type = calloc(1, sizeof(struct lysc_type_num));
Radek Krejci19a96102018-11-15 13:38:09 +01003131 break;
3132 case LY_TYPE_UNKNOWN:
3133 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003134 "Referenced type \"%s\" not found.", tctx_prev ? tctx_prev->tpdf->type.name : type_p->name);
Radek Krejci19a96102018-11-15 13:38:09 +01003135 ret = LY_EVALID;
3136 goto cleanup;
3137 }
3138 LY_CHECK_ERR_GOTO(!(*type), LOGMEM(ctx->ctx), cleanup);
Radek Krejcicdfecd92018-11-26 11:27:32 +01003139 if (~type_substmt_map[basetype] & type_p->flags) {
Radek Krejci19a96102018-11-15 13:38:09 +01003140 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type restrictions for %s type.",
Michal Vasko69730152020-10-09 16:30:07 +02003141 ly_data_type2str[basetype]);
Radek Krejci19a96102018-11-15 13:38:09 +01003142 free(*type);
3143 (*type) = NULL;
3144 ret = LY_EVALID;
3145 goto cleanup;
3146 }
3147
3148 /* get restrictions from the referred typedefs */
Radek Krejci1deb5be2020-08-26 16:43:36 +02003149 for (uint32_t u = tpdf_chain.count - 1; u + 1 > 0; --u) {
Michal Vasko22df3f02020-08-24 13:29:22 +02003150 tctx = (struct type_context *)tpdf_chain.objs[u];
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003151
3152 /* remember the typedef context for circular check */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003153 ret = ly_set_add(&ctx->tpdf_chain, tctx, LY_SET_OPT_USEASLIST, NULL);
3154 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003155
Radek Krejci43699232018-11-23 14:59:46 +01003156 if (tctx->tpdf->type.compiled) {
Radek Krejci19a96102018-11-15 13:38:09 +01003157 base = tctx->tpdf->type.compiled;
3158 continue;
Michal Vasko69730152020-10-09 16:30:07 +02003159 } else if ((basetype != LY_TYPE_LEAFREF) && (u != tpdf_chain.count - 1) && !(tctx->tpdf->type.flags)) {
Radek Krejci19a96102018-11-15 13:38:09 +01003160 /* no change, just use the type information from the base */
Michal Vasko22df3f02020-08-24 13:29:22 +02003161 base = ((struct lysp_tpdf *)tctx->tpdf)->type.compiled = ((struct type_context *)tpdf_chain.objs[u + 1])->tpdf->type.compiled;
Radek Krejci19a96102018-11-15 13:38:09 +01003162 ++base->refcount;
3163 continue;
3164 }
3165
3166 ++(*type)->refcount;
Radek Krejci43699232018-11-23 14:59:46 +01003167 if (~type_substmt_map[basetype] & tctx->tpdf->type.flags) {
3168 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid type \"%s\" restriction(s) for %s type.",
Michal Vasko69730152020-10-09 16:30:07 +02003169 tctx->tpdf->name, ly_data_type2str[basetype]);
Radek Krejci43699232018-11-23 14:59:46 +01003170 ret = LY_EVALID;
3171 goto cleanup;
Michal Vasko69730152020-10-09 16:30:07 +02003172 } else if ((basetype == LY_TYPE_EMPTY) && tctx->tpdf->dflt.str) {
Radek Krejci43699232018-11-23 14:59:46 +01003173 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003174 "Invalid type \"%s\" - \"empty\" type must not have a default value (%s).",
3175 tctx->tpdf->name, tctx->tpdf->dflt.str);
Radek Krejci43699232018-11-23 14:59:46 +01003176 ret = LY_EVALID;
3177 goto cleanup;
3178 }
3179
Radek Krejci19a96102018-11-15 13:38:09 +01003180 (*type)->basetype = basetype;
Radek Krejcie7b95092019-05-15 11:03:07 +02003181 /* TODO user type plugins */
3182 (*type)->plugin = &ly_builtin_type_plugins[basetype];
Radek Krejcic5c27e52018-11-15 14:38:11 +01003183 prev_type = *type;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02003184 ret = lys_compile_type_(ctx, tctx->node, tctx->tpdf->flags, tctx->mod, tctx->tpdf->name,
3185 &((struct lysp_tpdf *)tctx->tpdf)->type, basetype, tctx->tpdf->name, base, type);
Radek Krejcic5c27e52018-11-15 14:38:11 +01003186 LY_CHECK_GOTO(ret, cleanup);
3187 base = prev_type;
Radek Krejci19a96102018-11-15 13:38:09 +01003188 }
Radek Krejci99b5b2a2019-04-30 16:57:04 +02003189 /* remove the processed typedef contexts from the stack for circular check */
3190 ctx->tpdf_chain.count = ctx->tpdf_chain.count - tpdf_chain.count;
Radek Krejci19a96102018-11-15 13:38:09 +01003191
Radek Krejcic5c27e52018-11-15 14:38:11 +01003192 /* process the type definition in leaf */
Michal Vasko69730152020-10-09 16:30:07 +02003193 if (type_p->flags || !base || (basetype == LY_TYPE_LEAFREF)) {
Radek Krejcia3045382018-11-22 14:30:31 +01003194 /* get restrictions from the node itself */
Radek Krejci19a96102018-11-15 13:38:09 +01003195 (*type)->basetype = basetype;
Radek Krejcie7b95092019-05-15 11:03:07 +02003196 /* TODO user type plugins */
3197 (*type)->plugin = &ly_builtin_type_plugins[basetype];
Radek Krejci19a96102018-11-15 13:38:09 +01003198 ++(*type)->refcount;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02003199 ret = lys_compile_type_(ctx, context_pnode, context_flags, context_mod, context_name, type_p, basetype, NULL,
3200 base, type);
Radek Krejcic5c27e52018-11-15 14:38:11 +01003201 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko69730152020-10-09 16:30:07 +02003202 } else if ((basetype != LY_TYPE_BOOL) && (basetype != LY_TYPE_EMPTY)) {
Radek Krejci19a96102018-11-15 13:38:09 +01003203 /* no specific restriction in leaf's type definition, copy from the base */
3204 free(*type);
3205 (*type) = base;
3206 ++(*type)->refcount;
Radek Krejci19a96102018-11-15 13:38:09 +01003207 }
3208
Radek Krejci0935f412019-08-20 16:15:18 +02003209 COMPILE_EXTS_GOTO(ctx, type_p->exts, (*type)->exts, (*type), LYEXT_PAR_TYPE, ret, cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01003210
3211cleanup:
3212 ly_set_erase(&tpdf_chain, free);
3213 return ret;
3214}
3215
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003216/**
3217 * @brief Compile status information of the given node.
3218 *
3219 * To simplify getting status of the node, the flags are set following inheritance rules, so all the nodes
3220 * has the status correctly set during the compilation.
3221 *
3222 * @param[in] ctx Compile context
3223 * @param[in,out] node_flags Flags of the compiled node which status is supposed to be resolved.
3224 * If the status was set explicitly on the node, it is already set in the flags value and we just check
3225 * the compatibility with the parent's status value.
3226 * @param[in] parent_flags Flags of the parent node to check/inherit the status value.
3227 * @return LY_ERR value.
3228 */
3229static LY_ERR
3230lys_compile_status(struct lysc_ctx *ctx, uint16_t *node_flags, uint16_t parent_flags)
3231{
3232 /* status - it is not inherited by specification, but it does not make sense to have
3233 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
3234 if (!((*node_flags) & LYS_STATUS_MASK)) {
3235 if (parent_flags & (LYS_STATUS_DEPRC | LYS_STATUS_OBSLT)) {
3236 if ((parent_flags & 0x3) != 0x3) {
3237 /* do not print the warning when inheriting status from uses - the uses_status value has a special
3238 * combination of bits (0x3) which marks the uses_status value */
3239 LOGWRN(ctx->ctx, "Missing explicit \"%s\" status that was already specified in parent, inheriting.",
Radek Krejci0f969882020-08-21 16:56:47 +02003240 (parent_flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003241 }
3242 (*node_flags) |= parent_flags & LYS_STATUS_MASK;
3243 } else {
3244 (*node_flags) |= LYS_STATUS_CURR;
3245 }
3246 } else if (parent_flags & LYS_STATUS_MASK) {
3247 /* check status compatibility with the parent */
3248 if ((parent_flags & LYS_STATUS_MASK) > ((*node_flags) & LYS_STATUS_MASK)) {
3249 if ((*node_flags) & LYS_STATUS_CURR) {
3250 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003251 "A \"current\" status is in conflict with the parent's \"%s\" status.",
Radek Krejci0f969882020-08-21 16:56:47 +02003252 (parent_flags & LYS_STATUS_DEPRC) ? "deprecated" : "obsolete");
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003253 } else { /* LYS_STATUS_DEPRC */
3254 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003255 "A \"deprecated\" status is in conflict with the parent's \"obsolete\" status.");
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003256 }
3257 return LY_EVALID;
3258 }
3259 }
3260 return LY_SUCCESS;
3261}
3262
Radek Krejci8cce8532019-03-05 11:27:45 +01003263/**
3264 * @brief Check uniqness of the node/action/notification name.
3265 *
3266 * Data nodes, actions/RPCs and Notifications are stored separately (in distinguish lists) in the schema
3267 * structures, but they share the namespace so we need to check their name collisions.
3268 *
3269 * @param[in] ctx Compile context.
Michal Vasko20424b42020-08-31 12:29:38 +02003270 * @param[in] parent Parent of the nodes to check, can be NULL.
Radek Krejci8cce8532019-03-05 11:27:45 +01003271 * @param[in] name Name of the item to find in the given lists.
Michal Vasko20424b42020-08-31 12:29:38 +02003272 * @param[in] exclude Node that was just added that should be excluded from the name checking.
Radek Krejci8cce8532019-03-05 11:27:45 +01003273 * @return LY_SUCCESS in case of unique name, LY_EEXIST otherwise.
3274 */
3275static LY_ERR
Michal Vasko20424b42020-08-31 12:29:38 +02003276lys_compile_node_uniqness(struct lysc_ctx *ctx, const struct lysc_node *parent, const char *name,
3277 const struct lysc_node *exclude)
Radek Krejci8cce8532019-03-05 11:27:45 +01003278{
Michal Vasko20424b42020-08-31 12:29:38 +02003279 const struct lysc_node *iter, *iter2;
3280 const struct lysc_action *actions;
3281 const struct lysc_notif *notifs;
3282 uint32_t getnext_flags;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003283 LY_ARRAY_COUNT_TYPE u;
Radek Krejci8cce8532019-03-05 11:27:45 +01003284
Michal Vasko20424b42020-08-31 12:29:38 +02003285#define CHECK_NODE(iter, exclude, name) (iter != (void *)exclude && (iter)->module == exclude->module && !strcmp(name, (iter)->name))
3286
3287 if (exclude->nodetype == LYS_CASE) {
3288 /* check restricted only to all the cases */
3289 assert(parent->nodetype == LYS_CHOICE);
3290 LY_LIST_FOR(lysc_node_children(parent, 0), iter) {
3291 if (CHECK_NODE(iter, exclude, name)) {
3292 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPIDENT, name, "case");
3293 return LY_EEXIST;
3294 }
3295 }
3296
3297 return LY_SUCCESS;
3298 }
3299
3300 /* no reason for our parent to be choice anymore */
3301 assert(!parent || (parent->nodetype != LYS_CHOICE));
3302
3303 if (parent && (parent->nodetype == LYS_CASE)) {
3304 /* move to the first data definition parent */
3305 parent = lysc_data_parent(parent);
3306 }
3307
3308 getnext_flags = LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCHOICE;
3309 if (parent && (parent->nodetype & (LYS_RPC | LYS_ACTION)) && (exclude->flags & LYS_CONFIG_R)) {
3310 getnext_flags |= LYS_GETNEXT_OUTPUT;
3311 }
3312
3313 iter = NULL;
3314 while ((iter = lys_getnext(iter, parent, ctx->mod->compiled, getnext_flags))) {
3315 if (CHECK_NODE(iter, exclude, name)) {
Radek Krejci8cce8532019-03-05 11:27:45 +01003316 goto error;
3317 }
Michal Vasko20424b42020-08-31 12:29:38 +02003318
3319 /* we must compare with both the choice and all its nested data-definiition nodes (but not recursively) */
3320 if (iter->nodetype == LYS_CHOICE) {
3321 iter2 = NULL;
3322 while ((iter2 = lys_getnext(iter2, iter, NULL, LYS_GETNEXT_NOSTATECHECK))) {
3323 if (CHECK_NODE(iter2, exclude, name)) {
3324 goto error;
3325 }
3326 }
3327 }
Radek Krejci8cce8532019-03-05 11:27:45 +01003328 }
Michal Vasko20424b42020-08-31 12:29:38 +02003329
3330 actions = parent ? lysc_node_actions(parent) : ctx->mod->compiled->rpcs;
Radek Krejci8cce8532019-03-05 11:27:45 +01003331 LY_ARRAY_FOR(actions, u) {
Michal Vasko20424b42020-08-31 12:29:38 +02003332 if (CHECK_NODE(&actions[u], exclude, name)) {
Radek Krejci8cce8532019-03-05 11:27:45 +01003333 goto error;
3334 }
3335 }
Michal Vasko20424b42020-08-31 12:29:38 +02003336
3337 notifs = parent ? lysc_node_notifs(parent) : ctx->mod->compiled->notifs;
Radek Krejci8cce8532019-03-05 11:27:45 +01003338 LY_ARRAY_FOR(notifs, u) {
Michal Vasko20424b42020-08-31 12:29:38 +02003339 if (CHECK_NODE(&notifs[u], exclude, name)) {
Radek Krejci8cce8532019-03-05 11:27:45 +01003340 goto error;
3341 }
3342 }
3343 return LY_SUCCESS;
Michal Vasko20424b42020-08-31 12:29:38 +02003344
Radek Krejci8cce8532019-03-05 11:27:45 +01003345error:
Michal Vaskoa3881362020-01-21 15:57:35 +01003346 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPIDENT, name, "data definition/RPC/action/notification");
Radek Krejci8cce8532019-03-05 11:27:45 +01003347 return LY_EEXIST;
Michal Vasko20424b42020-08-31 12:29:38 +02003348
3349#undef CHECK_NODE
Radek Krejci8cce8532019-03-05 11:27:45 +01003350}
3351
Michal Vasko7f45cf22020-10-01 12:49:44 +02003352static LY_ERR lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent,
3353 uint16_t uses_status, struct ly_set *child_set);
3354
3355static LY_ERR lys_compile_node_deviations_refines(struct lysc_ctx *ctx, const struct lysp_node *pnode,
3356 const struct lysc_node *parent, struct lysp_node **dev_pnode, ly_bool *not_supported);
3357
3358static LY_ERR lys_compile_node_augments(struct lysc_ctx *ctx, struct lysc_node *node);
3359
3360static void lysp_dev_node_free(const struct ly_ctx *ctx, struct lysp_node *dev_pnode);
Radek Krejci19a96102018-11-15 13:38:09 +01003361
Radek Krejcia3045382018-11-22 14:30:31 +01003362/**
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003363 * @brief Compile parsed RPC/action schema node information.
3364 * @param[in] ctx Compile context
Radek Krejci43981a32019-04-12 09:44:11 +02003365 * @param[in] action_p Parsed RPC/action schema node.
Radek Krejci43981a32019-04-12 09:44:11 +02003366 * @param[in] parent Parent node of the action, NULL in case of RPC (top-level action)
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003367 * @param[in,out] action Prepared (empty) compiled action structure to fill.
3368 * @param[in] uses_status If the RPC/action is being placed instead of uses, here we have the uses's status value (as node's flags).
3369 * Zero means no uses, non-zero value with no status bit set mean the default status.
Michal Vasko7f45cf22020-10-01 12:49:44 +02003370 * @return LY_SUCCESS on success,
3371 * @return LY_EVALID on validation error,
3372 * @return LY_EDENIED on not-supported deviation.
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003373 */
3374static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02003375lys_compile_action(struct lysc_ctx *ctx, struct lysp_action *action_p,
Radek Krejci0f969882020-08-21 16:56:47 +02003376 struct lysc_node *parent, struct lysc_action *action, uint16_t uses_status)
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003377{
3378 LY_ERR ret = LY_SUCCESS;
Michal Vasko7f45cf22020-10-01 12:49:44 +02003379 struct lysp_node *child_p, *dev_pnode = NULL, *dev_input_p = NULL, *dev_output_p = NULL;
3380 struct lysp_action *orig_action_p = action_p;
3381 struct lysp_action_inout *inout_p;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003382 LY_ARRAY_COUNT_TYPE u;
Michal Vasko7f45cf22020-10-01 12:49:44 +02003383 ly_bool not_supported;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003384 uint32_t opt_prev = ctx->options;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003385
Radek Krejci327de162019-06-14 12:52:07 +02003386 lysc_update_path(ctx, parent, action_p->name);
3387
Michal Vasko7f45cf22020-10-01 12:49:44 +02003388 /* apply deviation on the action/RPC */
3389 LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)action_p, parent, &dev_pnode, &not_supported));
3390 if (not_supported) {
3391 lysc_update_path(ctx, NULL, NULL);
3392 return LY_EDENIED;
3393 } else if (dev_pnode) {
3394 action_p = (struct lysp_action *)dev_pnode;
3395 }
3396
Michal Vasko20424b42020-08-31 12:29:38 +02003397 /* member needed for uniqueness check lys_getnext() */
3398 action->nodetype = parent ? LYS_ACTION : LYS_RPC;
3399 action->module = ctx->mod;
3400 action->parent = parent;
3401
3402 LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, action_p->name, (struct lysc_node *)action));
Radek Krejci8cce8532019-03-05 11:27:45 +01003403
Radek Krejciec4da802019-05-02 13:02:41 +02003404 if (ctx->options & (LYSC_OPT_RPC_MASK | LYSC_OPT_NOTIFICATION)) {
Radek Krejci05b774b2019-02-25 13:26:18 +01003405 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003406 "Action \"%s\" is placed inside %s.", action_p->name,
3407 ctx->options & LYSC_OPT_RPC_MASK ? "another RPC/action" : "notification");
Radek Krejci05b774b2019-02-25 13:26:18 +01003408 return LY_EVALID;
3409 }
3410
Radek Krejciec4da802019-05-02 13:02:41 +02003411 if (!(ctx->options & LYSC_OPT_FREE_SP)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003412 action->sp = orig_action_p;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003413 }
3414 action->flags = action_p->flags & LYS_FLAGS_COMPILED_MASK;
3415
3416 /* status - it is not inherited by specification, but it does not make sense to have
3417 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
Michal Vaskocc048b22020-03-27 15:52:38 +01003418 LY_CHECK_RET(lys_compile_status(ctx, &action->flags, uses_status ? uses_status : (parent ? parent->flags : 0)));
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003419
Radek Krejci011e4aa2020-09-04 15:22:31 +02003420 DUP_STRING_GOTO(ctx->ctx, action_p->name, action->name, ret, cleanup);
3421 DUP_STRING_GOTO(ctx->ctx, action_p->dsc, action->dsc, ret, cleanup);
3422 DUP_STRING_GOTO(ctx->ctx, action_p->ref, action->ref, ret, cleanup);
Radek Krejciec4da802019-05-02 13:02:41 +02003423 COMPILE_ARRAY_GOTO(ctx, action_p->iffeatures, action->iffeatures, u, lys_compile_iffeature, ret, cleanup);
Radek Krejci0935f412019-08-20 16:15:18 +02003424 COMPILE_EXTS_GOTO(ctx, action_p->exts, action->exts, action, LYEXT_PAR_NODE, ret, cleanup);
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003425
Michal Vasko7f45cf22020-10-01 12:49:44 +02003426 /* connect any action augments */
3427 LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)action));
3428
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003429 /* input */
Michal Vasko22df3f02020-08-24 13:29:22 +02003430 lysc_update_path(ctx, (struct lysc_node *)action, "input");
Michal Vasko7f45cf22020-10-01 12:49:44 +02003431
3432 /* apply deviations on input */
3433 LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->input, (struct lysc_node *)action,
3434 &dev_input_p, &not_supported));
3435 if (not_supported) {
3436 inout_p = NULL;
3437 } else if (dev_input_p) {
3438 inout_p = (struct lysp_action_inout *)dev_input_p;
3439 } else {
3440 inout_p = &action_p->input;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003441 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02003442
3443 if (inout_p) {
3444 action->input.nodetype = LYS_INPUT;
3445 COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->input.musts, u, lys_compile_must, ret, cleanup);
3446 COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->input_exts, &action->input, LYEXT_PAR_INPUT, ret, cleanup);
3447 ctx->options |= LYSC_OPT_RPC_INPUT;
3448
3449 /* connect any input augments */
3450 LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)&action->input));
3451
3452 LY_LIST_FOR(inout_p->data, child_p) {
3453 LY_CHECK_RET(lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL));
3454 }
3455 ctx->options = opt_prev;
3456 }
3457
Radek Krejci327de162019-06-14 12:52:07 +02003458 lysc_update_path(ctx, NULL, NULL);
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003459
3460 /* output */
Michal Vasko22df3f02020-08-24 13:29:22 +02003461 lysc_update_path(ctx, (struct lysc_node *)action, "output");
Michal Vasko7f45cf22020-10-01 12:49:44 +02003462
3463 /* apply deviations on output */
3464 LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)&action_p->output, (struct lysc_node *)action,
3465 &dev_output_p, &not_supported));
3466 if (not_supported) {
3467 inout_p = NULL;
3468 } else if (dev_output_p) {
3469 inout_p = (struct lysp_action_inout *)dev_output_p;
3470 } else {
3471 inout_p = &action_p->output;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003472 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02003473
3474 if (inout_p) {
3475 action->output.nodetype = LYS_OUTPUT;
3476 COMPILE_ARRAY_GOTO(ctx, inout_p->musts, action->output.musts, u, lys_compile_must, ret, cleanup);
3477 COMPILE_EXTS_GOTO(ctx, inout_p->exts, action->output_exts, &action->output, LYEXT_PAR_OUTPUT, ret, cleanup);
3478 ctx->options |= LYSC_OPT_RPC_OUTPUT;
3479
3480 /* connect any output augments */
3481 LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)&action->output));
3482
3483 LY_LIST_FOR(inout_p->data, child_p) {
3484 LY_CHECK_RET(lys_compile_node(ctx, child_p, (struct lysc_node *)action, uses_status, NULL));
3485 }
3486 ctx->options = opt_prev;
3487 }
3488
Radek Krejci327de162019-06-14 12:52:07 +02003489 lysc_update_path(ctx, NULL, NULL);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003490
Michal Vasko7f45cf22020-10-01 12:49:44 +02003491 if ((action->input.musts || action->output.musts) && !(ctx->options & LYSC_OPT_GROUPING)) {
Michal Vasko5d8756a2019-11-07 15:21:00 +01003492 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003493 ret = ly_set_add(&ctx->xpath, action, 0, NULL);
3494 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003495 }
3496
Michal Vasko7f45cf22020-10-01 12:49:44 +02003497 lysc_update_path(ctx, NULL, NULL);
3498
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003499cleanup:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003500 lysp_dev_node_free(ctx->ctx, dev_pnode);
3501 lysp_dev_node_free(ctx->ctx, dev_input_p);
3502 lysp_dev_node_free(ctx->ctx, dev_output_p);
Radek Krejciec4da802019-05-02 13:02:41 +02003503 ctx->options = opt_prev;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003504 return ret;
3505}
3506
3507/**
Radek Krejci43981a32019-04-12 09:44:11 +02003508 * @brief Compile parsed Notification schema node information.
Radek Krejcifc11bd72019-04-11 16:00:05 +02003509 * @param[in] ctx Compile context
Radek Krejci43981a32019-04-12 09:44:11 +02003510 * @param[in] notif_p Parsed Notification schema node.
Radek Krejci43981a32019-04-12 09:44:11 +02003511 * @param[in] parent Parent node of the Notification, NULL in case of top-level Notification
3512 * @param[in,out] notif Prepared (empty) compiled notification structure to fill.
3513 * @param[in] uses_status If the Notification is being placed instead of uses, here we have the uses's status value (as node's flags).
Radek Krejcifc11bd72019-04-11 16:00:05 +02003514 * Zero means no uses, non-zero value with no status bit set mean the default status.
Michal Vasko7f45cf22020-10-01 12:49:44 +02003515 * @return LY_SUCCESS on success,
3516 * @return LY_EVALID on validation error,
3517 * @return LY_EDENIED on not-supported deviation.
Radek Krejcifc11bd72019-04-11 16:00:05 +02003518 */
3519static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02003520lys_compile_notif(struct lysc_ctx *ctx, struct lysp_notif *notif_p,
Radek Krejci0f969882020-08-21 16:56:47 +02003521 struct lysc_node *parent, struct lysc_notif *notif, uint16_t uses_status)
Radek Krejcifc11bd72019-04-11 16:00:05 +02003522{
3523 LY_ERR ret = LY_SUCCESS;
Michal Vasko7f45cf22020-10-01 12:49:44 +02003524 struct lysp_node *child_p, *dev_pnode = NULL;
3525 struct lysp_notif *orig_notif_p = notif_p;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003526 LY_ARRAY_COUNT_TYPE u;
Michal Vasko7f45cf22020-10-01 12:49:44 +02003527 ly_bool not_supported;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003528 uint32_t opt_prev = ctx->options;
Radek Krejcifc11bd72019-04-11 16:00:05 +02003529
Radek Krejci327de162019-06-14 12:52:07 +02003530 lysc_update_path(ctx, parent, notif_p->name);
3531
Michal Vasko7f45cf22020-10-01 12:49:44 +02003532 LY_CHECK_RET(lys_compile_node_deviations_refines(ctx, (struct lysp_node *)notif_p, parent, &dev_pnode, &not_supported));
3533 if (not_supported) {
3534 lysc_update_path(ctx, NULL, NULL);
3535 return LY_EDENIED;
3536 } else if (dev_pnode) {
3537 notif_p = (struct lysp_notif *)dev_pnode;
3538 }
3539
Michal Vasko20424b42020-08-31 12:29:38 +02003540 /* member needed for uniqueness check lys_getnext() */
3541 notif->nodetype = LYS_NOTIF;
3542 notif->module = ctx->mod;
3543 notif->parent = parent;
3544
3545 LY_CHECK_RET(lys_compile_node_uniqness(ctx, parent, notif_p->name, (struct lysc_node *)notif));
Radek Krejcifc11bd72019-04-11 16:00:05 +02003546
Radek Krejciec4da802019-05-02 13:02:41 +02003547 if (ctx->options & (LYSC_OPT_RPC_MASK | LYSC_OPT_NOTIFICATION)) {
Radek Krejcifc11bd72019-04-11 16:00:05 +02003548 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003549 "Notification \"%s\" is placed inside %s.", notif_p->name,
3550 ctx->options & LYSC_OPT_RPC_MASK ? "RPC/action" : "another notification");
Radek Krejcifc11bd72019-04-11 16:00:05 +02003551 return LY_EVALID;
3552 }
3553
Radek Krejciec4da802019-05-02 13:02:41 +02003554 if (!(ctx->options & LYSC_OPT_FREE_SP)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003555 notif->sp = orig_notif_p;
Radek Krejcifc11bd72019-04-11 16:00:05 +02003556 }
3557 notif->flags = notif_p->flags & LYS_FLAGS_COMPILED_MASK;
3558
3559 /* status - it is not inherited by specification, but it does not make sense to have
3560 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003561 ret = lys_compile_status(ctx, &notif->flags, uses_status ? uses_status : (parent ? parent->flags : 0));
3562 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcifc11bd72019-04-11 16:00:05 +02003563
Radek Krejci011e4aa2020-09-04 15:22:31 +02003564 DUP_STRING_GOTO(ctx->ctx, notif_p->name, notif->name, ret, cleanup);
3565 DUP_STRING_GOTO(ctx->ctx, notif_p->dsc, notif->dsc, ret, cleanup);
3566 DUP_STRING_GOTO(ctx->ctx, notif_p->ref, notif->ref, ret, cleanup);
Radek Krejciec4da802019-05-02 13:02:41 +02003567 COMPILE_ARRAY_GOTO(ctx, notif_p->iffeatures, notif->iffeatures, u, lys_compile_iffeature, ret, cleanup);
Radek Krejcic71ac5b2019-09-10 15:34:22 +02003568 COMPILE_ARRAY_GOTO(ctx, notif_p->musts, notif->musts, u, lys_compile_must, ret, cleanup);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003569 if (notif_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
3570 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003571 ret = ly_set_add(&ctx->xpath, notif, 0, NULL);
3572 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003573 }
Radek Krejci0935f412019-08-20 16:15:18 +02003574 COMPILE_EXTS_GOTO(ctx, notif_p->exts, notif->exts, notif, LYEXT_PAR_NODE, ret, cleanup);
Radek Krejcifc11bd72019-04-11 16:00:05 +02003575
Radek Krejciec4da802019-05-02 13:02:41 +02003576 ctx->options |= LYSC_OPT_NOTIFICATION;
Michal Vasko7f45cf22020-10-01 12:49:44 +02003577
3578 /* connect any notification augments */
3579 LY_CHECK_RET(lys_compile_node_augments(ctx, (struct lysc_node *)notif));
3580
Radek Krejcifc11bd72019-04-11 16:00:05 +02003581 LY_LIST_FOR(notif_p->data, child_p) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003582 ret = lys_compile_node(ctx, child_p, (struct lysc_node *)notif, uses_status, NULL);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003583 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcifc11bd72019-04-11 16:00:05 +02003584 }
3585
Radek Krejci327de162019-06-14 12:52:07 +02003586 lysc_update_path(ctx, NULL, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003587
Radek Krejcifc11bd72019-04-11 16:00:05 +02003588cleanup:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003589 lysp_dev_node_free(ctx->ctx, dev_pnode);
Radek Krejciec4da802019-05-02 13:02:41 +02003590 ctx->options = opt_prev;
Radek Krejcifc11bd72019-04-11 16:00:05 +02003591 return ret;
3592}
3593
3594/**
Radek Krejcia3045382018-11-22 14:30:31 +01003595 * @brief Compile parsed container node information.
3596 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02003597 * @param[in] pnode Parsed container node.
Radek Krejcia3045382018-11-22 14:30:31 +01003598 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3599 * is enriched with the container-specific information.
3600 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3601 */
Radek Krejci19a96102018-11-15 13:38:09 +01003602static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02003603lys_compile_node_container(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci19a96102018-11-15 13:38:09 +01003604{
Michal Vasko7f45cf22020-10-01 12:49:44 +02003605 struct lysp_node_container *cont_p = (struct lysp_node_container *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02003606 struct lysc_node_container *cont = (struct lysc_node_container *)node;
Radek Krejci19a96102018-11-15 13:38:09 +01003607 struct lysp_node *child_p;
Michal Vaskoba417ac2020-08-06 14:48:20 +02003608 LY_ARRAY_COUNT_TYPE u;
Radek Krejci19a96102018-11-15 13:38:09 +01003609 LY_ERR ret = LY_SUCCESS;
3610
Radek Krejcife909632019-02-12 15:34:42 +01003611 if (cont_p->presence) {
Michal Vaskoba417ac2020-08-06 14:48:20 +02003612 /* explicit presence */
Radek Krejcife909632019-02-12 15:34:42 +01003613 cont->flags |= LYS_PRESENCE;
Michal Vaskoba417ac2020-08-06 14:48:20 +02003614 } else if (cont_p->musts) {
3615 /* container with a must condition */
Radek Krejci175f25b2020-08-13 12:02:36 +02003616 LOGWRN(ctx->ctx, "Container \"%s\" changed to presence because it has a meaning from its \"must\" condition.", cont_p->name);
3617 cont->flags |= LYS_PRESENCE;
3618 } else if (cont_p->when) {
3619 /* container with a when condition */
3620 LOGWRN(ctx->ctx, "Container \"%s\" changed to presence because it has a meaning from its \"when\" condition.", cont_p->name);
Michal Vaskoba417ac2020-08-06 14:48:20 +02003621 cont->flags |= LYS_PRESENCE;
3622 } else if (cont_p->parent) {
3623 if (cont_p->parent->nodetype == LYS_CHOICE) {
3624 /* container is an implicit case, so its existence decides the existence of the whole case */
Radek Krejci175f25b2020-08-13 12:02:36 +02003625 LOGWRN(ctx->ctx, "Container \"%s\" changed to presence because it has a meaning as a case of choice \"%s\".",
Michal Vasko69730152020-10-09 16:30:07 +02003626 cont_p->name, cont_p->parent->name);
Michal Vaskoba417ac2020-08-06 14:48:20 +02003627 cont->flags |= LYS_PRESENCE;
Michal Vasko69730152020-10-09 16:30:07 +02003628 } else if ((cont_p->parent->nodetype == LYS_CASE) &&
3629 (((struct lysp_node_case *)cont_p->parent)->child == pnode) && !cont_p->next) {
Michal Vaskoba417ac2020-08-06 14:48:20 +02003630 /* container is the only node in a case, so its existence decides the existence of the whole case */
Radek Krejci175f25b2020-08-13 12:02:36 +02003631 LOGWRN(ctx->ctx, "Container \"%s\" changed to presence because it has a meaning as a case of choice \"%s\".",
Michal Vasko69730152020-10-09 16:30:07 +02003632 cont_p->name, cont_p->parent->name);
Michal Vaskoba417ac2020-08-06 14:48:20 +02003633 cont->flags |= LYS_PRESENCE;
3634 }
Radek Krejcife909632019-02-12 15:34:42 +01003635 }
3636
Michal Vaskoba417ac2020-08-06 14:48:20 +02003637 /* more cases when the container has meaning but is kept NP for convenience:
3638 * - when condition
3639 * - direct child action/notification
3640 */
3641
Radek Krejci19a96102018-11-15 13:38:09 +01003642 LY_LIST_FOR(cont_p->child, child_p) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003643 ret = lys_compile_node(ctx, child_p, node, 0, NULL);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003644 LY_CHECK_GOTO(ret, done);
Radek Krejci19a96102018-11-15 13:38:09 +01003645 }
3646
Radek Krejcic71ac5b2019-09-10 15:34:22 +02003647 COMPILE_ARRAY_GOTO(ctx, cont_p->musts, cont->musts, u, lys_compile_must, ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003648 if (cont_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
3649 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003650 ret = ly_set_add(&ctx->xpath, cont, 0, NULL);
3651 LY_CHECK_GOTO(ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003652 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02003653 COMPILE_OP_ARRAY_GOTO(ctx, cont_p->actions, cont->actions, node, u, lys_compile_action, 0, ret, done);
3654 COMPILE_OP_ARRAY_GOTO(ctx, cont_p->notifs, cont->notifs, node, u, lys_compile_notif, 0, ret, done);
Radek Krejci19a96102018-11-15 13:38:09 +01003655
3656done:
3657 return ret;
3658}
3659
Radek Krejci33f72892019-02-21 10:36:58 +01003660/*
3661 * @brief Compile type in leaf/leaf-list node and do all the necessary checks.
3662 * @param[in] ctx Compile context.
3663 * @param[in] context_node Schema node where the type/typedef is placed to correctly find the base types.
3664 * @param[in] type_p Parsed type to compile.
Radek Krejci33f72892019-02-21 10:36:58 +01003665 * @param[in,out] leaf Compiled leaf structure (possibly cast leaf-list) to provide node information and to store the compiled type information.
3666 * @return LY_ERR value.
3667 */
3668static LY_ERR
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003669lys_compile_node_type(struct lysc_ctx *ctx, struct lysp_node *context_node, struct lysp_type *type_p,
Radek Krejci0f969882020-08-21 16:56:47 +02003670 struct lysc_node_leaf *leaf)
Radek Krejci33f72892019-02-21 10:36:58 +01003671{
Michal Vasko7f45cf22020-10-01 12:49:44 +02003672 struct lysp_qname *dflt;
Radek Krejci33f72892019-02-21 10:36:58 +01003673
Radek Krejciec4da802019-05-02 13:02:41 +02003674 LY_CHECK_RET(lys_compile_type(ctx, context_node, leaf->flags, ctx->mod_def->parsed, leaf->name, type_p, &leaf->type,
Michal Vasko69730152020-10-09 16:30:07 +02003675 leaf->units ? NULL : &leaf->units, &dflt));
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003676
3677 /* store default value, if any */
3678 if (dflt && !(leaf->flags & LYS_SET_DFLT)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003679 LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, dflt));
Radek Krejci33f72892019-02-21 10:36:58 +01003680 }
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003681
Radek Krejci33f72892019-02-21 10:36:58 +01003682 if (leaf->type->basetype == LY_TYPE_LEAFREF) {
3683 /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003684 LY_CHECK_RET(ly_set_add(&ctx->leafrefs, leaf, 0, NULL));
Radek Krejci33f72892019-02-21 10:36:58 +01003685 } else if (leaf->type->basetype == LY_TYPE_UNION) {
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003686 LY_ARRAY_COUNT_TYPE u;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003687 LY_ARRAY_FOR(((struct lysc_type_union *)leaf->type)->types, u) {
3688 if (((struct lysc_type_union *)leaf->type)->types[u]->basetype == LY_TYPE_LEAFREF) {
Radek Krejci33f72892019-02-21 10:36:58 +01003689 /* store to validate the path in the current context at the end of schema compiling when all the nodes are present */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003690 LY_CHECK_RET(ly_set_add(&ctx->leafrefs, leaf, 0, NULL));
Radek Krejci33f72892019-02-21 10:36:58 +01003691 }
3692 }
3693 } else if (leaf->type->basetype == LY_TYPE_EMPTY) {
Michal Vasko69730152020-10-09 16:30:07 +02003694 if ((leaf->nodetype == LYS_LEAFLIST) && (ctx->mod_def->version < LYS_VERSION_1_1)) {
Radek Krejci33f72892019-02-21 10:36:58 +01003695 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003696 "Leaf-list of type \"empty\" is allowed only in YANG 1.1 modules.");
Radek Krejci33f72892019-02-21 10:36:58 +01003697 return LY_EVALID;
3698 }
3699 }
3700
Radek Krejci33f72892019-02-21 10:36:58 +01003701 return LY_SUCCESS;
3702}
3703
Radek Krejcia3045382018-11-22 14:30:31 +01003704/**
3705 * @brief Compile parsed leaf node information.
3706 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02003707 * @param[in] pnode Parsed leaf node.
Radek Krejcia3045382018-11-22 14:30:31 +01003708 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3709 * is enriched with the leaf-specific information.
3710 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3711 */
Radek Krejci19a96102018-11-15 13:38:09 +01003712static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02003713lys_compile_node_leaf(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci19a96102018-11-15 13:38:09 +01003714{
Michal Vasko7f45cf22020-10-01 12:49:44 +02003715 struct lysp_node_leaf *leaf_p = (struct lysp_node_leaf *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02003716 struct lysc_node_leaf *leaf = (struct lysc_node_leaf *)node;
Michal Vasko7c8439f2020-08-05 13:25:19 +02003717 LY_ARRAY_COUNT_TYPE u;
Radek Krejci19a96102018-11-15 13:38:09 +01003718 LY_ERR ret = LY_SUCCESS;
3719
Radek Krejcic71ac5b2019-09-10 15:34:22 +02003720 COMPILE_ARRAY_GOTO(ctx, leaf_p->musts, leaf->musts, u, lys_compile_must, ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003721 if (leaf_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
3722 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003723 ret = ly_set_add(&ctx->xpath, leaf, 0, NULL);
3724 LY_CHECK_GOTO(ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003725 }
Radek Krejciccd20f12019-02-15 14:12:27 +01003726 if (leaf_p->units) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003727 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, leaf_p->units, 0, &leaf->units), done);
Radek Krejciccd20f12019-02-15 14:12:27 +01003728 leaf->flags |= LYS_SET_UNITS;
3729 }
Radek Krejcia1911222019-07-22 17:24:50 +02003730
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003731 /* compile type */
Michal Vasko7f45cf22020-10-01 12:49:44 +02003732 ret = lys_compile_node_type(ctx, pnode, &leaf_p->type, leaf);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003733 LY_CHECK_GOTO(ret, done);
Radek Krejcia1911222019-07-22 17:24:50 +02003734
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003735 /* store/update default value */
Michal Vasko7f45cf22020-10-01 12:49:44 +02003736 if (leaf_p->dflt.str) {
3737 LY_CHECK_RET(lysc_unres_leaf_dflt_add(ctx, leaf, &leaf_p->dflt));
Radek Krejci76b3e962018-12-14 17:01:25 +01003738 leaf->flags |= LYS_SET_DFLT;
3739 }
Radek Krejci43699232018-11-23 14:59:46 +01003740
Michal Vasko7f45cf22020-10-01 12:49:44 +02003741 /* checks */
3742 if ((leaf->flags & LYS_SET_DFLT) && (leaf->flags & LYS_MAND_TRUE)) {
3743 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
3744 "Invalid mandatory leaf with a default value.");
3745 return LY_EVALID;
3746 }
3747
Radek Krejci19a96102018-11-15 13:38:09 +01003748done:
3749 return ret;
3750}
3751
Radek Krejcia3045382018-11-22 14:30:31 +01003752/**
Radek Krejci0e5d8382018-11-28 16:37:53 +01003753 * @brief Compile parsed leaf-list node information.
3754 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02003755 * @param[in] pnode Parsed leaf-list node.
Radek Krejci0e5d8382018-11-28 16:37:53 +01003756 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3757 * is enriched with the leaf-list-specific information.
3758 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3759 */
3760static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02003761lys_compile_node_leaflist(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci0e5d8382018-11-28 16:37:53 +01003762{
Michal Vasko7f45cf22020-10-01 12:49:44 +02003763 struct lysp_node_leaflist *llist_p = (struct lysp_node_leaflist *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02003764 struct lysc_node_leaflist *llist = (struct lysc_node_leaflist *)node;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003765 LY_ARRAY_COUNT_TYPE u;
Radek Krejci0e5d8382018-11-28 16:37:53 +01003766 LY_ERR ret = LY_SUCCESS;
3767
Radek Krejcic71ac5b2019-09-10 15:34:22 +02003768 COMPILE_ARRAY_GOTO(ctx, llist_p->musts, llist->musts, u, lys_compile_must, ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003769 if (llist_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
3770 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003771 ret = ly_set_add(&ctx->xpath, llist, 0, NULL);
3772 LY_CHECK_GOTO(ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003773 }
Radek Krejciccd20f12019-02-15 14:12:27 +01003774 if (llist_p->units) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003775 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, llist_p->units, 0, &llist->units), done);
Radek Krejciccd20f12019-02-15 14:12:27 +01003776 llist->flags |= LYS_SET_UNITS;
3777 }
Radek Krejci0e5d8382018-11-28 16:37:53 +01003778
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003779 /* compile type */
Michal Vasko7f45cf22020-10-01 12:49:44 +02003780 ret = lys_compile_node_type(ctx, pnode, &llist_p->type, (struct lysc_node_leaf *)llist);
Radek Krejciba03a5a2020-08-27 14:40:41 +02003781 LY_CHECK_GOTO(ret, done);
Michal Vasko6a044b22020-01-15 12:25:39 +01003782
Michal Vaskoba99a3e2020-08-18 15:50:05 +02003783 /* store/update default values */
Radek Krejci0e5d8382018-11-28 16:37:53 +01003784 if (llist_p->dflts) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003785 if (ctx->mod_def->version < LYS_VERSION_1_1) {
3786 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003787 "Leaf-list default values are allowed only in YANG 1.1 modules.");
Michal Vasko7f45cf22020-10-01 12:49:44 +02003788 return LY_EVALID;
3789 }
3790
3791 LY_CHECK_GOTO(lysc_unres_llist_dflts_add(ctx, llist, llist_p->dflts), done);
Radek Krejciccd20f12019-02-15 14:12:27 +01003792 llist->flags |= LYS_SET_DFLT;
Radek Krejci0e5d8382018-11-28 16:37:53 +01003793 }
3794
3795 llist->min = llist_p->min;
Radek Krejcife909632019-02-12 15:34:42 +01003796 if (llist->min) {
3797 llist->flags |= LYS_MAND_TRUE;
3798 }
Radek Krejcib7408632018-11-28 17:12:11 +01003799 llist->max = llist_p->max ? llist_p->max : (uint32_t)-1;
Radek Krejci0e5d8382018-11-28 16:37:53 +01003800
Michal Vasko7f45cf22020-10-01 12:49:44 +02003801 /* checks */
3802 if ((llist->flags & LYS_SET_DFLT) && (llist->flags & LYS_MAND_TRUE)) {
3803 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
3804 "Invalid mandatory leaf-list with default value(s).");
3805 return LY_EVALID;
3806 }
3807
3808 if (llist->min > llist->max) {
3809 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Leaf-list min-elements %u is bigger than max-elements %u.",
Michal Vasko69730152020-10-09 16:30:07 +02003810 llist->min, llist->max);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003811 return LY_EVALID;
3812 }
3813
Radek Krejci0e5d8382018-11-28 16:37:53 +01003814done:
3815 return ret;
3816}
3817
3818/**
Radek Krejci7af64242019-02-18 13:07:53 +01003819 * @brief Compile information about list's uniques.
3820 * @param[in] ctx Compile context.
Radek Krejci7af64242019-02-18 13:07:53 +01003821 * @param[in] uniques Sized array list of unique statements.
3822 * @param[in] list Compiled list where the uniques are supposed to be resolved and stored.
3823 * @return LY_ERR value.
3824 */
3825static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02003826lys_compile_node_list_unique(struct lysc_ctx *ctx, struct lysp_qname *uniques, struct lysc_node_list *list)
Radek Krejci7af64242019-02-18 13:07:53 +01003827{
3828 LY_ERR ret = LY_SUCCESS;
3829 struct lysc_node_leaf **key, ***unique;
Michal Vasko14654712020-02-06 08:35:21 +01003830 struct lysc_node *parent;
Radek Krejci7af64242019-02-18 13:07:53 +01003831 const char *keystr, *delim;
3832 size_t len;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003833 LY_ARRAY_COUNT_TYPE v;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003834 int8_t config; /* -1 - not yet seen; 0 - LYS_CONFIG_R; 1 - LYS_CONFIG_W */
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003835 uint16_t flags;
Radek Krejci7af64242019-02-18 13:07:53 +01003836
Michal Vasko7f45cf22020-10-01 12:49:44 +02003837 LY_ARRAY_FOR(uniques, v) {
Radek Krejci7af64242019-02-18 13:07:53 +01003838 config = -1;
3839 LY_ARRAY_NEW_RET(ctx->ctx, list->uniques, unique, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003840 keystr = uniques[v].str;
Radek Krejci7af64242019-02-18 13:07:53 +01003841 while (keystr) {
3842 delim = strpbrk(keystr, " \t\n");
3843 if (delim) {
3844 len = delim - keystr;
3845 while (isspace(*delim)) {
3846 ++delim;
3847 }
3848 } else {
3849 len = strlen(keystr);
3850 }
3851
3852 /* unique node must be present */
3853 LY_ARRAY_NEW_RET(ctx->ctx, *unique, key, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003854 ret = lysc_resolve_schema_nodeid(ctx, keystr, len, (struct lysc_node *)list, uniques[v].mod, LYS_LEAF,
Michal Vasko69730152020-10-09 16:30:07 +02003855 (const struct lysc_node **)key, &flags);
Radek Krejci7af64242019-02-18 13:07:53 +01003856 if (ret != LY_SUCCESS) {
3857 if (ret == LY_EDENIED) {
3858 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003859 "Unique's descendant-schema-nodeid \"%.*s\" refers to %s node instead of a leaf.",
3860 len, keystr, lys_nodetype2str((*key)->nodetype));
Radek Krejci7af64242019-02-18 13:07:53 +01003861 }
3862 return LY_EVALID;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003863 } else if (flags) {
3864 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003865 "Unique's descendant-schema-nodeid \"%.*s\" refers into %s node.",
3866 len, keystr, flags & LYSC_OPT_NOTIFICATION ? "notification" : "RPC/action");
Radek Krejci6eeb58f2019-02-22 16:29:37 +01003867 return LY_EVALID;
Radek Krejci7af64242019-02-18 13:07:53 +01003868 }
3869
3870 /* all referenced leafs must be of the same config type */
Michal Vasko69730152020-10-09 16:30:07 +02003871 if ((config != -1) && ((((*key)->flags & LYS_CONFIG_W) && (config == 0)) || (((*key)->flags & LYS_CONFIG_R) && (config == 1)))) {
Radek Krejci7af64242019-02-18 13:07:53 +01003872 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003873 "Unique statement \"%s\" refers to leaves with different config type.", uniques[v].str);
Radek Krejci7af64242019-02-18 13:07:53 +01003874 return LY_EVALID;
3875 } else if ((*key)->flags & LYS_CONFIG_W) {
3876 config = 1;
3877 } else { /* LYS_CONFIG_R */
3878 config = 0;
3879 }
3880
Michal Vasko14654712020-02-06 08:35:21 +01003881 /* we forbid referencing nested lists because it is unspecified what instance of such a list to use */
3882 for (parent = (*key)->parent; parent != (struct lysc_node *)list; parent = parent->parent) {
3883 if (parent->nodetype == LYS_LIST) {
3884 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003885 "Unique statement \"%s\" refers to a leaf in nested list \"%s\".", uniques[v].str, parent->name);
Michal Vasko14654712020-02-06 08:35:21 +01003886 return LY_EVALID;
3887 }
3888 }
3889
Radek Krejci7af64242019-02-18 13:07:53 +01003890 /* check status */
3891 LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
Radek Krejci0f969882020-08-21 16:56:47 +02003892 (*key)->flags, (*key)->module, (*key)->name));
Radek Krejci7af64242019-02-18 13:07:53 +01003893
3894 /* mark leaf as unique */
3895 (*key)->flags |= LYS_UNIQUE;
3896
3897 /* next unique value in line */
3898 keystr = delim;
3899 }
3900 /* next unique definition */
3901 }
3902
3903 return LY_SUCCESS;
3904}
3905
3906/**
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003907 * @brief Compile parsed list node information.
3908 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02003909 * @param[in] pnode Parsed list node.
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003910 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
3911 * is enriched with the list-specific information.
3912 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
3913 */
3914static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02003915lys_compile_node_list(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003916{
Michal Vasko7f45cf22020-10-01 12:49:44 +02003917 struct lysp_node_list *list_p = (struct lysp_node_list *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02003918 struct lysc_node_list *list = (struct lysc_node_list *)node;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003919 struct lysp_node *child_p;
Radek Krejci0fe9b512019-07-26 17:51:05 +02003920 struct lysc_node_leaf *key, *prev_key = NULL;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003921 size_t len;
Radek Krejci1deb5be2020-08-26 16:43:36 +02003922 LY_ARRAY_COUNT_TYPE u;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003923 const char *keystr, *delim;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003924 LY_ERR ret = LY_SUCCESS;
3925
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003926 list->min = list_p->min;
Radek Krejcife909632019-02-12 15:34:42 +01003927 if (list->min) {
3928 list->flags |= LYS_MAND_TRUE;
3929 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003930 list->max = list_p->max ? list_p->max : (uint32_t)-1;
3931
3932 LY_LIST_FOR(list_p->child, child_p) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02003933 LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0, NULL));
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003934 }
3935
Radek Krejcic71ac5b2019-09-10 15:34:22 +02003936 COMPILE_ARRAY_GOTO(ctx, list_p->musts, list->musts, u, lys_compile_must, ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01003937 if (list_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
3938 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02003939 LY_CHECK_RET(ly_set_add(&ctx->xpath, list, 0, NULL));
Michal Vasko5d8756a2019-11-07 15:21:00 +01003940 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003941
3942 /* keys */
3943 if ((list->flags & LYS_CONFIG_W) && (!list_p->key || !list_p->key[0])) {
3944 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Missing key in list representing configuration data.");
3945 return LY_EVALID;
3946 }
3947
3948 /* find all the keys (must be direct children) */
3949 keystr = list_p->key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02003950 if (!keystr) {
3951 /* keyless list */
3952 list->flags |= LYS_KEYLESS;
3953 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003954 while (keystr) {
3955 delim = strpbrk(keystr, " \t\n");
3956 if (delim) {
3957 len = delim - keystr;
3958 while (isspace(*delim)) {
3959 ++delim;
3960 }
3961 } else {
3962 len = strlen(keystr);
3963 }
3964
3965 /* key node must be present */
Michal Vasko22df3f02020-08-24 13:29:22 +02003966 key = (struct lysc_node_leaf *)lys_find_child(node, node->module, keystr, len, LYS_LEAF, LYS_GETNEXT_NOCHOICE | LYS_GETNEXT_NOSTATECHECK);
Radek Krejci0fe9b512019-07-26 17:51:05 +02003967 if (!(key)) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003968 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02003969 "The list's key \"%.*s\" not found.", len, keystr);
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003970 return LY_EVALID;
3971 }
3972 /* keys must be unique */
Radek Krejci0fe9b512019-07-26 17:51:05 +02003973 if (key->flags & LYS_KEY) {
3974 /* the node was already marked as a key */
3975 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003976 "Duplicated key identifier \"%.*s\".", len, keystr);
Radek Krejci0fe9b512019-07-26 17:51:05 +02003977 return LY_EVALID;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003978 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02003979
Michal Vasko22df3f02020-08-24 13:29:22 +02003980 lysc_update_path(ctx, (struct lysc_node *)list, key->name);
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003981 /* key must have the same config flag as the list itself */
Radek Krejci0fe9b512019-07-26 17:51:05 +02003982 if ((list->flags & LYS_CONFIG_MASK) != (key->flags & LYS_CONFIG_MASK)) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003983 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Key of the configuration list must not be status leaf.");
3984 return LY_EVALID;
3985 }
Radek Krejci0bcdaed2019-01-10 10:21:34 +01003986 if (ctx->mod_def->version < LYS_VERSION_1_1) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003987 /* YANG 1.0 denies key to be of empty type */
Radek Krejci0fe9b512019-07-26 17:51:05 +02003988 if (key->type->basetype == LY_TYPE_EMPTY) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003989 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003990 "List's key cannot be of \"empty\" type until it is in YANG 1.1 module.");
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003991 return LY_EVALID;
3992 }
3993 } else {
3994 /* when and if-feature are illegal on list keys */
Radek Krejci0fe9b512019-07-26 17:51:05 +02003995 if (key->when) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003996 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02003997 "List's key must not have any \"when\" statement.");
Radek Krejci9bb94eb2018-12-04 16:48:35 +01003998 return LY_EVALID;
3999 }
Radek Krejci0fe9b512019-07-26 17:51:05 +02004000 if (key->iffeatures) {
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004001 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02004002 "List's key must not have any \"if-feature\" statement.");
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004003 return LY_EVALID;
4004 }
4005 }
Radek Krejci76b3e962018-12-14 17:01:25 +01004006
4007 /* check status */
4008 LY_CHECK_RET(lysc_check_status(ctx, list->flags, list->module, list->name,
Michal Vasko69730152020-10-09 16:30:07 +02004009 key->flags, key->module, key->name));
Radek Krejci76b3e962018-12-14 17:01:25 +01004010
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004011 /* ignore default values of the key */
Radek Krejci0fe9b512019-07-26 17:51:05 +02004012 if (key->dflt) {
4013 key->dflt->realtype->plugin->free(ctx->ctx, key->dflt);
Michal Vaskofeca4fb2020-10-05 08:58:40 +02004014 lysc_type_free(ctx->ctx, (struct lysc_type *)key->dflt->realtype);
Radek Krejci0fe9b512019-07-26 17:51:05 +02004015 free(key->dflt);
4016 key->dflt = NULL;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004017 }
4018 /* mark leaf as key */
Radek Krejci0fe9b512019-07-26 17:51:05 +02004019 key->flags |= LYS_KEY;
4020
4021 /* move it to the correct position */
Michal Vasko69730152020-10-09 16:30:07 +02004022 if ((prev_key && ((struct lysc_node *)prev_key != key->prev)) || (!prev_key && key->prev->next)) {
Radek Krejci0fe9b512019-07-26 17:51:05 +02004023 /* fix links in closest previous siblings of the key */
4024 if (key->next) {
4025 key->next->prev = key->prev;
4026 } else {
4027 /* last child */
4028 list->child->prev = key->prev;
4029 }
4030 if (key->prev->next) {
4031 key->prev->next = key->next;
4032 }
4033 /* fix links in the key */
4034 if (prev_key) {
Michal Vasko22df3f02020-08-24 13:29:22 +02004035 key->prev = (struct lysc_node *)prev_key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004036 key->next = prev_key->next;
4037 } else {
4038 key->prev = list->child->prev;
4039 key->next = list->child;
4040 }
4041 /* fix links in closes future siblings of the key */
4042 if (prev_key) {
4043 if (prev_key->next) {
Michal Vasko22df3f02020-08-24 13:29:22 +02004044 prev_key->next->prev = (struct lysc_node *)key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004045 } else {
Michal Vasko22df3f02020-08-24 13:29:22 +02004046 list->child->prev = (struct lysc_node *)key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004047 }
Michal Vasko22df3f02020-08-24 13:29:22 +02004048 prev_key->next = (struct lysc_node *)key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004049 } else {
Michal Vasko22df3f02020-08-24 13:29:22 +02004050 list->child->prev = (struct lysc_node *)key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004051 }
4052 /* fix links in parent */
4053 if (!key->prev->next) {
Michal Vasko22df3f02020-08-24 13:29:22 +02004054 list->child = (struct lysc_node *)key;
Radek Krejci0fe9b512019-07-26 17:51:05 +02004055 }
4056 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004057
4058 /* next key value */
Radek Krejci0fe9b512019-07-26 17:51:05 +02004059 prev_key = key;
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004060 keystr = delim;
Radek Krejci327de162019-06-14 12:52:07 +02004061 lysc_update_path(ctx, NULL, NULL);
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004062 }
4063
4064 /* uniques */
4065 if (list_p->uniques) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004066 LY_CHECK_RET(lys_compile_node_list_unique(ctx, list_p->uniques, list));
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004067 }
4068
Michal Vasko7f45cf22020-10-01 12:49:44 +02004069 COMPILE_OP_ARRAY_GOTO(ctx, list_p->actions, list->actions, node, u, lys_compile_action, 0, ret, done);
4070 COMPILE_OP_ARRAY_GOTO(ctx, list_p->notifs, list->notifs, node, u, lys_compile_notif, 0, ret, done);
4071
4072 /* checks */
4073 if (list->min > list->max) {
4074 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "List min-elements %u is bigger than max-elements %u.",
Michal Vasko69730152020-10-09 16:30:07 +02004075 list->min, list->max);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004076 return LY_EVALID;
4077 }
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004078
4079done:
4080 return ret;
4081}
4082
Radek Krejcib56c7502019-02-13 14:19:54 +01004083/**
4084 * @brief Do some checks and set the default choice's case.
4085 *
4086 * Selects (and stores into ::lysc_node_choice#dflt) the default case and set LYS_SET_DFLT flag on it.
4087 *
4088 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02004089 * @param[in] dflt Name of the default branch. Can even contain a prefix.
Radek Krejcib56c7502019-02-13 14:19:54 +01004090 * @param[in,out] ch The compiled choice node, its dflt member is filled to point to the default case node of the choice.
4091 * @return LY_ERR value.
4092 */
Radek Krejci76b3e962018-12-14 17:01:25 +01004093static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004094lys_compile_node_choice_dflt(struct lysc_ctx *ctx, struct lysp_qname *dflt, struct lysc_node_choice *ch)
Radek Krejci76b3e962018-12-14 17:01:25 +01004095{
Michal Vasko22df3f02020-08-24 13:29:22 +02004096 struct lysc_node *iter, *node = (struct lysc_node *)ch;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004097 const struct lys_module *mod;
Radek Krejci76b3e962018-12-14 17:01:25 +01004098 const char *prefix = NULL, *name;
4099 size_t prefix_len = 0;
4100
4101 /* could use lys_parse_nodeid(), but it checks syntax which is already done in this case by the parsers */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004102 name = strchr(dflt->str, ':');
Radek Krejci76b3e962018-12-14 17:01:25 +01004103 if (name) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004104 prefix = dflt->str;
Radek Krejci76b3e962018-12-14 17:01:25 +01004105 prefix_len = name - prefix;
4106 ++name;
4107 } else {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004108 name = dflt->str;
Radek Krejci76b3e962018-12-14 17:01:25 +01004109 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004110 if (prefix) {
4111 mod = ly_resolve_prefix(ctx->ctx, prefix, prefix_len, LY_PREF_SCHEMA, (void *)dflt->mod);
4112 if (!mod) {
4113 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
4114 "Default case prefix \"%.*s\" not found in imports of \"%s\".", prefix_len, prefix, dflt->mod->name);
4115 return LY_EVALID;
4116 }
4117 } else {
4118 mod = node->module;
Radek Krejci76b3e962018-12-14 17:01:25 +01004119 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004120
4121 ch->dflt = (struct lysc_node_case *)lys_find_child(node, mod, name, 0, LYS_CASE, LYS_GETNEXT_NOSTATECHECK | LYS_GETNEXT_WITHCASE);
Radek Krejci76b3e962018-12-14 17:01:25 +01004122 if (!ch->dflt) {
4123 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02004124 "Default case \"%s\" not found.", dflt->str);
Radek Krejci76b3e962018-12-14 17:01:25 +01004125 return LY_EVALID;
4126 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004127
Radek Krejci76b3e962018-12-14 17:01:25 +01004128 /* no mandatory nodes directly under the default case */
4129 LY_LIST_FOR(ch->dflt->child, iter) {
Michal Vasko22df3f02020-08-24 13:29:22 +02004130 if (iter->parent != (struct lysc_node *)ch->dflt) {
Radek Krejcife13da42019-02-15 14:51:01 +01004131 break;
4132 }
Radek Krejci76b3e962018-12-14 17:01:25 +01004133 if (iter->flags & LYS_MAND_TRUE) {
4134 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02004135 "Mandatory node \"%s\" under the default case \"%s\".", iter->name, dflt->str);
Radek Krejci76b3e962018-12-14 17:01:25 +01004136 return LY_EVALID;
4137 }
4138 }
Radek Krejci76b3e962018-12-14 17:01:25 +01004139
Michal Vasko7f45cf22020-10-01 12:49:44 +02004140 if (ch->flags & LYS_MAND_TRUE) {
4141 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Invalid mandatory choice with a default case.");
Radek Krejciccd20f12019-02-15 14:12:27 +01004142 return LY_EVALID;
4143 }
4144
Michal Vasko7f45cf22020-10-01 12:49:44 +02004145 ch->dflt->flags |= LYS_SET_DFLT;
Radek Krejciccd20f12019-02-15 14:12:27 +01004146 return LY_SUCCESS;
4147}
4148
Radek Krejci9bb94eb2018-12-04 16:48:35 +01004149/**
Michal Vasko20424b42020-08-31 12:29:38 +02004150 * @brief Compile choice children.
4151 *
4152 * @param[in] ctx Compile context
4153 * @param[in] child_p Parsed choice children nodes.
4154 * @param[in] node Compiled choice node to compile and add children to.
4155 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
4156 */
4157static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004158lys_compile_node_choice_child(struct lysc_ctx *ctx, struct lysp_node *child_p, struct lysc_node *node,
4159 struct ly_set *child_set)
Michal Vasko20424b42020-08-31 12:29:38 +02004160{
4161 LY_ERR ret = LY_SUCCESS;
Radek Krejci8f5fad22020-09-15 16:50:54 +02004162 struct lysp_node *child_p_next = child_p->next;
Michal Vasko20424b42020-08-31 12:29:38 +02004163 struct lysp_node_case *cs_p;
4164
4165 if (child_p->nodetype == LYS_CASE) {
4166 /* standard case under choice */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004167 ret = lys_compile_node(ctx, child_p, node, 0, child_set);
Michal Vasko20424b42020-08-31 12:29:38 +02004168 } else {
4169 /* we need the implicit case first, so create a fake parsed case */
4170 cs_p = calloc(1, sizeof *cs_p);
4171 cs_p->nodetype = LYS_CASE;
Radek Krejci87e25252020-09-15 13:28:31 +02004172 DUP_STRING_GOTO(ctx->ctx, child_p->name, cs_p->name, ret, free_fake_node);
Michal Vasko20424b42020-08-31 12:29:38 +02004173 cs_p->child = child_p;
4174
4175 /* make the child the only case child */
Michal Vasko20424b42020-08-31 12:29:38 +02004176 child_p->next = NULL;
4177
4178 /* compile it normally */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004179 ret = lys_compile_node(ctx, (struct lysp_node *)cs_p, node, 0, child_set);
Michal Vasko20424b42020-08-31 12:29:38 +02004180
Radek Krejci87e25252020-09-15 13:28:31 +02004181free_fake_node:
Michal Vasko20424b42020-08-31 12:29:38 +02004182 /* free the fake parsed node and correct pointers back */
4183 cs_p->child = NULL;
4184 lysp_node_free(ctx->ctx, (struct lysp_node *)cs_p);
Radek Krejci8f5fad22020-09-15 16:50:54 +02004185 child_p->next = child_p_next;
Michal Vasko20424b42020-08-31 12:29:38 +02004186 }
4187
4188 return ret;
4189}
4190
4191/**
Radek Krejci056d0a82018-12-06 16:57:25 +01004192 * @brief Compile parsed choice node information.
Michal Vasko20424b42020-08-31 12:29:38 +02004193 *
Radek Krejci056d0a82018-12-06 16:57:25 +01004194 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02004195 * @param[in] pnode Parsed choice node.
Radek Krejci056d0a82018-12-06 16:57:25 +01004196 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
Radek Krejci76b3e962018-12-14 17:01:25 +01004197 * is enriched with the choice-specific information.
Radek Krejci056d0a82018-12-06 16:57:25 +01004198 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
4199 */
4200static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004201lys_compile_node_choice(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci056d0a82018-12-06 16:57:25 +01004202{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004203 struct lysp_node_choice *ch_p = (struct lysp_node_choice *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02004204 struct lysc_node_choice *ch = (struct lysc_node_choice *)node;
Michal Vasko20424b42020-08-31 12:29:38 +02004205 struct lysp_node *child_p;
Radek Krejci056d0a82018-12-06 16:57:25 +01004206 LY_ERR ret = LY_SUCCESS;
4207
Michal Vasko20424b42020-08-31 12:29:38 +02004208 assert(node->nodetype == LYS_CHOICE);
4209
Radek Krejci056d0a82018-12-06 16:57:25 +01004210 LY_LIST_FOR(ch_p->child, child_p) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004211 LY_CHECK_RET(lys_compile_node_choice_child(ctx, child_p, node, NULL));
Radek Krejci056d0a82018-12-06 16:57:25 +01004212 }
4213
4214 /* default branch */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004215 if (ch_p->dflt.str) {
4216 LY_CHECK_RET(lys_compile_node_choice_dflt(ctx, &ch_p->dflt, ch));
Radek Krejcia9026eb2018-12-12 16:04:47 +01004217 }
Radek Krejci056d0a82018-12-06 16:57:25 +01004218
Radek Krejci9800fb82018-12-13 14:26:23 +01004219 return ret;
4220}
4221
4222/**
4223 * @brief Compile parsed anydata or anyxml node information.
4224 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02004225 * @param[in] pnode Parsed anydata or anyxml node.
Radek Krejci9800fb82018-12-13 14:26:23 +01004226 * @param[in,out] node Pre-prepared structure from lys_compile_node() with filled generic node information
4227 * is enriched with the any-specific information.
4228 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
4229 */
4230static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004231lys_compile_node_any(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci9800fb82018-12-13 14:26:23 +01004232{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004233 struct lysp_node_anydata *any_p = (struct lysp_node_anydata *)pnode;
Michal Vasko22df3f02020-08-24 13:29:22 +02004234 struct lysc_node_anydata *any = (struct lysc_node_anydata *)node;
Radek Krejci1deb5be2020-08-26 16:43:36 +02004235 LY_ARRAY_COUNT_TYPE u;
Radek Krejci9800fb82018-12-13 14:26:23 +01004236 LY_ERR ret = LY_SUCCESS;
4237
Radek Krejcic71ac5b2019-09-10 15:34:22 +02004238 COMPILE_ARRAY_GOTO(ctx, any_p->musts, any->musts, u, lys_compile_must, ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01004239 if (any_p->musts && !(ctx->options & LYSC_OPT_GROUPING)) {
4240 /* do not check "must" semantics in a grouping */
Radek Krejciba03a5a2020-08-27 14:40:41 +02004241 ret = ly_set_add(&ctx->xpath, any, 0, NULL);
4242 LY_CHECK_GOTO(ret, done);
Michal Vasko5d8756a2019-11-07 15:21:00 +01004243 }
Radek Krejci9800fb82018-12-13 14:26:23 +01004244
4245 if (any->flags & LYS_CONFIG_W) {
Radek Krejci5c4ed7b2020-08-12 11:29:44 +02004246 LOGWRN(ctx->ctx, "Use of %s to define configuration data is not recommended. %s",
Michal Vasko69730152020-10-09 16:30:07 +02004247 ly_stmt2str(any->nodetype == LYS_ANYDATA ? LY_STMT_ANYDATA : LY_STMT_ANYXML), ctx->path);
Radek Krejci9800fb82018-12-13 14:26:23 +01004248 }
Radek Krejci056d0a82018-12-06 16:57:25 +01004249done:
4250 return ret;
4251}
4252
Radek Krejcib56c7502019-02-13 14:19:54 +01004253/**
Michal Vasko795b3752020-07-13 15:24:27 +02004254 * @brief Connect the node into the siblings list and check its name uniqueness. Also,
4255 * keep specific order of augments targetting the same node.
Radek Krejci056d0a82018-12-06 16:57:25 +01004256 *
4257 * @param[in] ctx Compile context
4258 * @param[in] parent Parent node holding the children list, in case of node from a choice's case,
4259 * the choice itself is expected instead of a specific case node.
4260 * @param[in] node Schema node to connect into the list.
4261 * @return LY_ERR value - LY_SUCCESS or LY_EEXIST.
Radek Krejci1c54f462020-05-12 17:25:34 +02004262 * In case of LY_EEXIST, the node is actually kept in the tree, so do not free it directly.
Radek Krejci056d0a82018-12-06 16:57:25 +01004263 */
4264static LY_ERR
Radek Krejciec4da802019-05-02 13:02:41 +02004265lys_compile_node_connect(struct lysc_ctx *ctx, struct lysc_node *parent, struct lysc_node *node)
Radek Krejci056d0a82018-12-06 16:57:25 +01004266{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004267 struct lysc_node **children, *anchor = NULL;
4268 int insert_after = 0;
Radek Krejci056d0a82018-12-06 16:57:25 +01004269
Michal Vasko20424b42020-08-31 12:29:38 +02004270 node->parent = parent;
4271
4272 if (parent) {
4273 if (parent->nodetype == LYS_CHOICE) {
4274 assert(node->nodetype == LYS_CASE);
4275 children = (struct lysc_node **)&((struct lysc_node_choice *)parent)->cases;
4276 } else {
4277 children = lysc_node_children_p(parent, ctx->options);
4278 }
4279 assert(children);
4280
Radek Krejci056d0a82018-12-06 16:57:25 +01004281 if (!(*children)) {
4282 /* first child */
4283 *children = node;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004284 } else if (node->flags & LYS_KEY) {
4285 /* special handling of adding keys */
4286 assert(node->module == parent->module);
4287 anchor = *children;
4288 if (anchor->flags & LYS_KEY) {
4289 while ((anchor->flags & LYS_KEY) && anchor->next) {
4290 anchor = anchor->next;
4291 }
4292 /* insert after the last key */
4293 insert_after = 1;
4294 } /* else insert before anchor (at the beginning) */
4295 } else if ((*children)->prev->module == node->module) {
4296 /* last child is from the same module, keep the order and insert at the end */
4297 anchor = (*children)->prev;
4298 insert_after = 1;
4299 } else if (parent->module == node->module) {
4300 /* adding module child after some augments were connected */
4301 for (anchor = *children; anchor->module == node->module; anchor = anchor->next) {}
4302 } else {
4303 /* some augments are already connected and we are connecting new ones,
4304 * keep module name order and insert the node into the children list */
4305 anchor = *children;
4306 do {
4307 anchor = anchor->prev;
Michal Vasko795b3752020-07-13 15:24:27 +02004308
Michal Vasko7f45cf22020-10-01 12:49:44 +02004309 /* check that we have not found the last augment node from our module or
4310 * the first augment node from a "smaller" module or
4311 * the first node from a local module */
Michal Vasko69730152020-10-09 16:30:07 +02004312 if ((anchor->module == node->module) || (strcmp(anchor->module->name, node->module->name) < 0) ||
4313 (anchor->module == parent->module)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004314 /* insert after */
4315 insert_after = 1;
4316 break;
4317 }
4318
4319 /* we have traversed all the nodes, insert before anchor (as the first node) */
4320 } while (anchor->prev->next);
4321 }
4322
4323 /* insert */
4324 if (anchor) {
4325 if (insert_after) {
4326 node->next = anchor->next;
4327 node->prev = anchor;
4328 anchor->next = node;
4329 if (node->next) {
4330 /* middle node */
4331 node->next->prev = node;
4332 } else {
4333 /* last node */
4334 (*children)->prev = node;
4335 }
Michal Vasko795b3752020-07-13 15:24:27 +02004336 } else {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004337 node->next = anchor;
4338 node->prev = anchor->prev;
4339 anchor->prev = node;
4340 if (anchor == *children) {
4341 /* first node */
4342 *children = node;
4343 } else {
4344 /* middle node */
4345 node->prev->next = node;
4346 }
Michal Vasko795b3752020-07-13 15:24:27 +02004347 }
Michal Vasko20424b42020-08-31 12:29:38 +02004348 }
Radek Krejci056d0a82018-12-06 16:57:25 +01004349
Michal Vasko20424b42020-08-31 12:29:38 +02004350 /* check the name uniqueness (even for an only child, it may be in case) */
4351 if (lys_compile_node_uniqness(ctx, parent, node->name, node)) {
4352 return LY_EEXIST;
4353 }
4354 } else {
4355 /* top-level element */
4356 if (!ctx->mod->compiled->data) {
4357 ctx->mod->compiled->data = node;
4358 } else {
4359 /* insert at the end of the module's top-level nodes list */
4360 ctx->mod->compiled->data->prev->next = node;
4361 node->prev = ctx->mod->compiled->data->prev;
4362 ctx->mod->compiled->data->prev = node;
4363 }
4364
4365 /* check the name uniqueness on top-level */
4366 if (lys_compile_node_uniqness(ctx, NULL, node->name, node)) {
4367 return LY_EEXIST;
Radek Krejci056d0a82018-12-06 16:57:25 +01004368 }
4369 }
Michal Vasko20424b42020-08-31 12:29:38 +02004370
Radek Krejci056d0a82018-12-06 16:57:25 +01004371 return LY_SUCCESS;
4372}
4373
Radek Krejci95710c92019-02-11 15:49:55 +01004374/**
Radek Krejcib56c7502019-02-13 14:19:54 +01004375 * @brief Prepare the case structure in choice node for the new data node.
4376 *
4377 * 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
4378 * created in the choice when the first child was processed.
4379 *
4380 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02004381 * @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,
Radek Krejci39424802020-08-12 09:31:00 +02004382 * it is the LYS_CHOICE, LYS_AUGMENT or LYS_GROUPING node.
Radek Krejcib56c7502019-02-13 14:19:54 +01004383 * @param[in] ch The compiled choice structure where the new case structures are created (if needed).
4384 * @param[in] child The new data node being part of a case (no matter if explicit or implicit).
4385 * @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,
4386 * it is linked from the case structure only in case it is its first child.
Radek Krejci95710c92019-02-11 15:49:55 +01004387 */
Michal Vasko20424b42020-08-31 12:29:38 +02004388static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004389lys_compile_node_case(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *node)
Radek Krejci056d0a82018-12-06 16:57:25 +01004390{
Michal Vasko20424b42020-08-31 12:29:38 +02004391 struct lysp_node *child_p;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004392 struct lysp_node_case *cs_p = (struct lysp_node_case *)pnode;
Radek Krejci056d0a82018-12-06 16:57:25 +01004393
Michal Vasko7f45cf22020-10-01 12:49:44 +02004394 if (pnode->nodetype & (LYS_CHOICE | LYS_AUGMENT | LYS_GROUPING)) {
Radek Krejci056d0a82018-12-06 16:57:25 +01004395 /* we have to add an implicit case node into the parent choice */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004396 } else if (pnode->nodetype == LYS_CASE) {
Michal Vasko20424b42020-08-31 12:29:38 +02004397 /* explicit parent case */
4398 LY_LIST_FOR(cs_p->child, child_p) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004399 LY_CHECK_RET(lys_compile_node(ctx, child_p, node, 0, NULL));
Radek Krejci056d0a82018-12-06 16:57:25 +01004400 }
Radek Krejci95710c92019-02-11 15:49:55 +01004401 } else {
Michal Vasko20424b42020-08-31 12:29:38 +02004402 LOGINT_RET(ctx->ctx);
Radek Krejci056d0a82018-12-06 16:57:25 +01004403 }
Radek Krejci056d0a82018-12-06 16:57:25 +01004404
Michal Vasko20424b42020-08-31 12:29:38 +02004405 return LY_SUCCESS;
Radek Krejci056d0a82018-12-06 16:57:25 +01004406}
4407
Radek Krejcib56c7502019-02-13 14:19:54 +01004408/**
Radek Krejcib56c7502019-02-13 14:19:54 +01004409 * @brief Set LYS_MAND_TRUE flag for the non-presence container parents.
4410 *
4411 * A non-presence container is mandatory in case it has at least one mandatory children. This function propagate
4412 * the flag to such parents from a mandatory children.
4413 *
4414 * @param[in] parent A schema node to be examined if the mandatory child make it also mandatory.
4415 * @param[in] add Flag to distinguish adding the mandatory flag (new mandatory children appeared) or removing the flag
4416 * (mandatory children was removed).
4417 */
Radek Krejci1deb5be2020-08-26 16:43:36 +02004418static void
Radek Krejci857189e2020-09-01 13:26:36 +02004419lys_compile_mandatory_parents(struct lysc_node *parent, ly_bool add)
Radek Krejcife909632019-02-12 15:34:42 +01004420{
4421 struct lysc_node *iter;
4422
4423 if (add) { /* set flag */
Michal Vaskod989ba02020-08-24 10:59:24 +02004424 for ( ; parent && parent->nodetype == LYS_CONTAINER && !(parent->flags & LYS_MAND_TRUE) && !(parent->flags & LYS_PRESENCE);
Radek Krejcife909632019-02-12 15:34:42 +01004425 parent = parent->parent) {
4426 parent->flags |= LYS_MAND_TRUE;
4427 }
4428 } else { /* unset flag */
Michal Vaskod989ba02020-08-24 10:59:24 +02004429 for ( ; parent && parent->nodetype == LYS_CONTAINER && (parent->flags & LYS_MAND_TRUE); parent = parent->parent) {
Michal Vasko22df3f02020-08-24 13:29:22 +02004430 for (iter = (struct lysc_node *)lysc_node_children(parent, 0); iter; iter = iter->next) {
Radek Krejcif1421c22019-02-19 13:05:20 +01004431 if (iter->flags & LYS_MAND_TRUE) {
Radek Krejcife909632019-02-12 15:34:42 +01004432 /* there is another mandatory node */
4433 return;
4434 }
4435 }
4436 /* unset mandatory flag - there is no mandatory children in the non-presence container */
4437 parent->flags &= ~LYS_MAND_TRUE;
4438 }
4439 }
4440}
4441
Radek Krejci056d0a82018-12-06 16:57:25 +01004442/**
Radek Krejci3641f562019-02-13 15:38:40 +01004443 * @brief Compile the parsed augment connecting it into its target.
4444 *
4445 * It is expected that all the data referenced in path are present - augments are ordered so that augment B
4446 * targeting data from augment A is being compiled after augment A. Also the modules referenced in the path
4447 * are already implemented and compiled.
4448 *
4449 * @param[in] ctx Compile context.
4450 * @param[in] aug_p Parsed augment to compile.
Michal Vasko7f45cf22020-10-01 12:49:44 +02004451 * @param[in] target Target node of the augment.
Radek Krejci3641f562019-02-13 15:38:40 +01004452 * @return LY_SUCCESS on success.
4453 * @return LY_EVALID on failure.
4454 */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004455static LY_ERR
4456lys_compile_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, struct lysc_node *target)
Radek Krejci3641f562019-02-13 15:38:40 +01004457{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004458 LY_ERR ret = LY_SUCCESS;
4459 struct lysp_node *pnode;
Radek Krejci3641f562019-02-13 15:38:40 +01004460 struct lysc_node *node;
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004461 struct lysc_when *when_shared = NULL;
4462 struct lysc_action **actions;
4463 struct lysc_notif **notifs;
Radek Krejci857189e2020-09-01 13:26:36 +02004464 ly_bool allow_mandatory = 0;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004465 LY_ARRAY_COUNT_TYPE u;
4466 struct ly_set child_set = {0};
4467 uint32_t i;
Radek Krejci3641f562019-02-13 15:38:40 +01004468
Michal Vasko7f45cf22020-10-01 12:49:44 +02004469 if (!(target->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF))) {
4470 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
4471 "Augment's %s-schema-nodeid \"%s\" refers to a %s node which is not an allowed augment's target.",
4472 aug_p->nodeid[0] == '/' ? "absolute" : "descendant", aug_p->nodeid, lys_nodetype2str(target->nodetype));
4473 ret = LY_EVALID;
4474 goto cleanup;
Radek Krejci3641f562019-02-13 15:38:40 +01004475 }
4476
4477 /* check for mandatory nodes
4478 * - new cases augmenting some choice can have mandatory nodes
4479 * - mandatory nodes are allowed only in case the augmentation is made conditional with a when statement
4480 */
Michal Vasko69730152020-10-09 16:30:07 +02004481 if (aug_p->when || (target->nodetype == LYS_CHOICE) || (ctx->mod == target->module)) {
Radek Krejci3641f562019-02-13 15:38:40 +01004482 allow_mandatory = 1;
4483 }
4484
Michal Vasko7f45cf22020-10-01 12:49:44 +02004485 LY_LIST_FOR(aug_p->child, pnode) {
Radek Krejci3641f562019-02-13 15:38:40 +01004486 /* check if the subnode can be connected to the found target (e.g. case cannot be inserted into container) */
Michal Vasko69730152020-10-09 16:30:07 +02004487 if (((pnode->nodetype == LYS_CASE) && (target->nodetype != LYS_CHOICE)) ||
4488 ((pnode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && !(target->nodetype & (LYS_CONTAINER | LYS_LIST))) ||
4489 ((pnode->nodetype == LYS_USES) && (target->nodetype == LYS_CHOICE))) {
Radek Krejci3641f562019-02-13 15:38:40 +01004490 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02004491 "Invalid augment of %s node which is not allowed to contain %s node \"%s\".",
4492 lys_nodetype2str(target->nodetype), lys_nodetype2str(pnode->nodetype), pnode->name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004493 ret = LY_EVALID;
4494 goto cleanup;
Radek Krejci3641f562019-02-13 15:38:40 +01004495 }
4496
4497 /* compile the children */
Michal Vasko20424b42020-08-31 12:29:38 +02004498 if (target->nodetype == LYS_CHOICE) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004499 LY_CHECK_GOTO(ret = lys_compile_node_choice_child(ctx, pnode, target, &child_set), cleanup);
Radek Krejci3641f562019-02-13 15:38:40 +01004500 } else {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004501 LY_CHECK_GOTO(ret = lys_compile_node(ctx, pnode, target, 0, &child_set), cleanup);
Radek Krejci3641f562019-02-13 15:38:40 +01004502 }
4503
Michal Vasko7f45cf22020-10-01 12:49:44 +02004504 /* since the augment node is not present in the compiled tree, we need to pass some of its
4505 * statements to all its children */
4506 for (i = 0; i < child_set.count; ++i) {
4507 node = child_set.snodes[i];
4508 if (!allow_mandatory && (node->flags & LYS_CONFIG_W) && (node->flags & LYS_MAND_TRUE)) {
4509 node->flags &= ~LYS_MAND_TRUE;
4510 lys_compile_mandatory_parents(target, 0);
4511 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02004512 "Invalid augment adding mandatory node \"%s\" without making it conditional via when statement.", node->name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004513 ret = LY_EVALID;
4514 goto cleanup;
Radek Krejci7c7783d2020-04-08 15:34:39 +02004515 }
Radek Krejci3641f562019-02-13 15:38:40 +01004516
Michal Vasko7f45cf22020-10-01 12:49:44 +02004517 if (aug_p->when) {
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004518 /* pass augment's when to all the children */
4519 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target), node, &when_shared);
4520 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci3641f562019-02-13 15:38:40 +01004521 }
4522 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004523 ly_set_erase(&child_set, NULL);
Radek Krejci3641f562019-02-13 15:38:40 +01004524 }
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004525
4526 switch (target->nodetype) {
4527 case LYS_CONTAINER:
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004528 actions = &((struct lysc_node_container *)target)->actions;
4529 notifs = &((struct lysc_node_container *)target)->notifs;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004530 break;
4531 case LYS_LIST:
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004532 actions = &((struct lysc_node_list *)target)->actions;
4533 notifs = &((struct lysc_node_list *)target)->notifs;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004534 break;
4535 default:
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004536 actions = NULL;
4537 notifs = NULL;
4538 break;
4539 }
4540
4541 if (aug_p->actions) {
4542 if (!actions) {
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004543 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02004544 "Invalid augment of %s node which is not allowed to contain RPC/action node \"%s\".",
4545 lys_nodetype2str(target->nodetype), aug_p->actions[0].name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004546 ret = LY_EVALID;
4547 goto cleanup;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004548 }
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004549
4550 /* compile actions into the target */
4551 COMPILE_OP_ARRAY_GOTO(ctx, aug_p->actions, *actions, target, u, lys_compile_action, 0, ret, cleanup);
4552
4553 if (aug_p->when) {
4554 /* inherit when */
4555 LY_ARRAY_FOR(*actions, u) {
4556 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target),
4557 (struct lysc_node *)&(*actions)[u], &when_shared);
4558 LY_CHECK_GOTO(ret, cleanup);
4559 }
4560 }
4561 }
4562 if (aug_p->notifs) {
4563 if (!notifs) {
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004564 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02004565 "Invalid augment of %s node which is not allowed to contain notification node \"%s\".",
4566 lys_nodetype2str(target->nodetype), aug_p->notifs[0].name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004567 ret = LY_EVALID;
4568 goto cleanup;
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004569 }
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004570
4571 /* compile notifications into the target */
4572 COMPILE_OP_ARRAY_GOTO(ctx, aug_p->notifs, *notifs, target, u, lys_compile_notif, 0, ret, cleanup);
4573
4574 if (aug_p->when) {
4575 /* inherit when */
4576 LY_ARRAY_FOR(*notifs, u) {
4577 ret = lys_compile_when(ctx, aug_p->when, aug_p->flags, lysc_xpath_context(target),
4578 (struct lysc_node *)&(*notifs)[u], &when_shared);
4579 LY_CHECK_GOTO(ret, cleanup);
4580 }
4581 }
Radek Krejci6eeb58f2019-02-22 16:29:37 +01004582 }
Radek Krejci3641f562019-02-13 15:38:40 +01004583
Michal Vasko7f45cf22020-10-01 12:49:44 +02004584cleanup:
4585 ly_set_erase(&child_set, NULL);
Radek Krejci3641f562019-02-13 15:38:40 +01004586 return ret;
4587}
4588
4589/**
Michal Vasko601ddb32020-08-31 16:25:35 +02004590 * @brief Find grouping for a uses.
Radek Krejcie86bf772018-12-14 11:39:53 +01004591 *
Michal Vasko601ddb32020-08-31 16:25:35 +02004592 * @param[in] ctx Compile context.
4593 * @param[in] uses_p Parsed uses node.
4594 * @param[out] gpr_p Found grouping on success.
4595 * @param[out] grp_mod Module of @p grp_p on success.
4596 * @return LY_ERR value.
Radek Krejcie86bf772018-12-14 11:39:53 +01004597 */
4598static LY_ERR
Michal Vasko601ddb32020-08-31 16:25:35 +02004599lys_compile_uses_find_grouping(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysp_grp **grp_p,
4600 struct lys_module **grp_mod)
Radek Krejcie86bf772018-12-14 11:39:53 +01004601{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004602 struct lysp_node *pnode;
Michal Vasko601ddb32020-08-31 16:25:35 +02004603 struct lysp_grp *grp;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02004604 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci857189e2020-09-01 13:26:36 +02004605 ly_bool found = 0;
Radek Krejcie86bf772018-12-14 11:39:53 +01004606 const char *id, *name, *prefix;
4607 size_t prefix_len, name_len;
Michal Vasko601ddb32020-08-31 16:25:35 +02004608 struct lys_module *mod;
4609
4610 *grp_p = NULL;
4611 *grp_mod = NULL;
Radek Krejcie86bf772018-12-14 11:39:53 +01004612
4613 /* search for the grouping definition */
Radek Krejcie86bf772018-12-14 11:39:53 +01004614 id = uses_p->name;
Radek Krejcib4a4a272019-06-10 12:44:52 +02004615 LY_CHECK_RET(ly_parse_nodeid(&id, &prefix, &prefix_len, &name, &name_len), LY_EVALID);
Radek Krejcie86bf772018-12-14 11:39:53 +01004616 if (prefix) {
4617 mod = lys_module_find_prefix(ctx->mod_def, prefix, prefix_len);
4618 if (!mod) {
4619 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02004620 "Invalid prefix used for grouping reference.", uses_p->name);
Radek Krejcie86bf772018-12-14 11:39:53 +01004621 return LY_EVALID;
4622 }
4623 } else {
4624 mod = ctx->mod_def;
4625 }
4626 if (mod == ctx->mod_def) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02004627 for (pnode = uses_p->parent; !found && pnode; pnode = pnode->parent) {
4628 grp = (struct lysp_grp *)lysp_node_groupings(pnode);
Radek Krejcie86bf772018-12-14 11:39:53 +01004629 LY_ARRAY_FOR(grp, u) {
4630 if (!strcmp(grp[u].name, name)) {
4631 grp = &grp[u];
4632 found = 1;
4633 break;
4634 }
4635 }
4636 }
4637 }
4638 if (!found) {
Radek Krejci76b3e962018-12-14 17:01:25 +01004639 /* search in top-level groupings of the main module ... */
Radek Krejcie86bf772018-12-14 11:39:53 +01004640 grp = mod->parsed->groupings;
Michal Vasko601ddb32020-08-31 16:25:35 +02004641 LY_ARRAY_FOR(grp, u) {
4642 if (!strcmp(grp[u].name, name)) {
4643 grp = &grp[u];
4644 found = 1;
4645 break;
Radek Krejci76b3e962018-12-14 17:01:25 +01004646 }
4647 }
Michal Vasko601ddb32020-08-31 16:25:35 +02004648 if (!found) {
Radek Krejci76b3e962018-12-14 17:01:25 +01004649 /* ... and all the submodules */
Michal Vasko601ddb32020-08-31 16:25:35 +02004650 LY_ARRAY_FOR(mod->parsed->includes, u) {
Radek Krejci76b3e962018-12-14 17:01:25 +01004651 grp = mod->parsed->includes[u].submodule->groupings;
Michal Vasko601ddb32020-08-31 16:25:35 +02004652 LY_ARRAY_FOR(grp, v) {
4653 if (!strcmp(grp[v].name, name)) {
4654 grp = &grp[v];
4655 found = 1;
4656 break;
Radek Krejci76b3e962018-12-14 17:01:25 +01004657 }
4658 }
Michal Vasko601ddb32020-08-31 16:25:35 +02004659 if (found) {
4660 break;
4661 }
Radek Krejcie86bf772018-12-14 11:39:53 +01004662 }
4663 }
4664 }
4665 if (!found) {
4666 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02004667 "Grouping \"%s\" referenced by a uses statement not found.", uses_p->name);
Radek Krejcie86bf772018-12-14 11:39:53 +01004668 return LY_EVALID;
4669 }
4670
Radek Krejcif2de0ed2019-05-02 14:13:18 +02004671 if (!(ctx->options & LYSC_OPT_GROUPING)) {
4672 /* remember that the grouping is instantiated to avoid its standalone validation */
4673 grp->flags |= LYS_USED_GRP;
4674 }
Radek Krejcie86bf772018-12-14 11:39:53 +01004675
Michal Vasko601ddb32020-08-31 16:25:35 +02004676 *grp_p = grp;
4677 *grp_mod = mod;
4678 return LY_SUCCESS;
4679}
Radek Krejcie86bf772018-12-14 11:39:53 +01004680
Michal Vasko7f45cf22020-10-01 12:49:44 +02004681static const struct lys_module *lys_schema_node_get_module(const struct ly_ctx *ctx, const char *nametest,
4682 size_t nametest_len, const struct lys_module *local_mod, const char **name, size_t *name_len);
4683
Michal Vasko601ddb32020-08-31 16:25:35 +02004684static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004685lys_nodeid_check(struct lysc_ctx *ctx, const char *nodeid, ly_bool abs, struct lys_module **target_mod,
4686 struct lyxp_expr **expr)
Michal Vasko601ddb32020-08-31 16:25:35 +02004687{
Michal Vasko601ddb32020-08-31 16:25:35 +02004688 LY_ERR ret = LY_SUCCESS;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004689 struct lyxp_expr *e = NULL;
4690 struct lys_module *tmod = NULL, *mod;
4691 const char *nodeid_type = abs ? "absolute-schema-nodeid" : "descendant-schema-nodeid";
4692 uint32_t i;
Radek Krejcie86bf772018-12-14 11:39:53 +01004693
Michal Vasko7f45cf22020-10-01 12:49:44 +02004694 /* parse */
4695 ret = lyxp_expr_parse(ctx->ctx, nodeid, strlen(nodeid), 0, &e);
4696 if (ret) {
4697 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid %s value \"%s\" - invalid syntax.",
4698 nodeid_type, nodeid);
4699 ret = LY_EVALID;
4700 goto cleanup;
Radek Krejci01342af2019-01-03 15:18:08 +01004701 }
Radek Krejcie86bf772018-12-14 11:39:53 +01004702
Michal Vasko7f45cf22020-10-01 12:49:44 +02004703 if (abs) {
4704 /* absolute schema nodeid */
4705 i = 0;
4706 } else {
4707 /* descendant schema nodeid */
4708 if (e->tokens[0] != LYXP_TOKEN_NAMETEST) {
4709 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
4710 nodeid_type, nodeid, e->tok_len[0], e->expr + e->tok_pos[0]);
Michal Vasko20424b42020-08-31 12:29:38 +02004711 ret = LY_EVALID;
Radek Krejcifc11bd72019-04-11 16:00:05 +02004712 goto cleanup;
Radek Krejcif2271f12019-01-07 16:42:23 +01004713 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004714 i = 1;
4715 }
Radek Krejcif2271f12019-01-07 16:42:23 +01004716
Michal Vasko7f45cf22020-10-01 12:49:44 +02004717 /* check all the tokens */
4718 for ( ; i < e->used; i += 2) {
4719 if (e->tokens[i] != LYXP_TOKEN_OPER_PATH) {
4720 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - \"/\" expected instead of \"%.*s\".",
4721 nodeid_type, nodeid, e->tok_len[i], e->expr + e->tok_pos[i]);
4722 ret = LY_EVALID;
4723 goto cleanup;
4724 } else if (e->used == i + 1) {
4725 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
4726 "Invalid %s value \"%s\" - unexpected end of expression.", nodeid_type, e->expr);
4727 ret = LY_EVALID;
4728 goto cleanup;
4729 } else if (e->tokens[i + 1] != LYXP_TOKEN_NAMETEST) {
4730 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s value \"%s\" - name test expected instead of \"%.*s\".",
4731 nodeid_type, nodeid, e->tok_len[i + 1], e->expr + e->tok_pos[i + 1]);
4732 ret = LY_EVALID;
4733 goto cleanup;
4734 } else if (abs) {
4735 mod = (struct lys_module *)lys_schema_node_get_module(ctx->ctx, e->expr + e->tok_pos[i + 1],
4736 e->tok_len[i + 1], ctx->mod_def, NULL, NULL);
4737 LY_CHECK_ERR_GOTO(!mod, ret = LY_EVALID, cleanup);
4738
4739 /* only keep the first module */
4740 if (!tmod) {
4741 tmod = mod;
Radek Krejcif2271f12019-01-07 16:42:23 +01004742 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004743
4744 /* all the modules must be implemented */
4745 if (!mod->implemented) {
Michal Vasko89b5c072020-10-06 13:52:44 +02004746 ret = lys_set_implemented(mod);
Michal Vasko7f45cf22020-10-01 12:49:44 +02004747 LY_CHECK_GOTO(ret, cleanup);
4748 }
4749 }
4750 }
4751
4752cleanup:
4753 if (ret || !expr) {
4754 lyxp_expr_free(ctx->ctx, e);
4755 e = NULL;
4756 }
4757 if (expr) {
4758 *expr = ret ? NULL : e;
4759 }
4760 if (target_mod) {
4761 *target_mod = ret ? NULL : tmod;
4762 }
4763 return ret;
4764}
4765
4766/**
4767 * @brief Check whether 2 schema nodeids match.
4768 *
4769 * @param[in] ctx libyang context.
4770 * @param[in] exp1 First schema nodeid.
4771 * @param[in] exp1_mod Module of @p exp1 nodes without any prefix.
4772 * @param[in] exp2 Second schema nodeid.
4773 * @param[in] exp2_mod Module of @p exp2 nodes without any prefix.
4774 * @return Whether the schema nodeids match or not.
4775 */
4776static ly_bool
4777lys_abs_schema_nodeid_match(const struct ly_ctx *ctx, const struct lyxp_expr *exp1, const struct lys_module *exp1_mod,
4778 const struct lyxp_expr *exp2, const struct lys_module *exp2_mod)
4779{
4780 uint32_t i;
4781 const struct lys_module *mod1, *mod2;
4782 const char *name1, *name2;
4783 size_t name1_len, name2_len;
4784
4785 if (exp1->used != exp2->used) {
4786 return 0;
4787 }
4788
4789 for (i = 0; i < exp1->used; ++i) {
4790 assert(exp1->tokens[i] == exp2->tokens[i]);
4791
4792 if (exp1->tokens[i] == LYXP_TOKEN_NAMETEST) {
4793 /* check modules of all the nodes in the node ID */
4794 mod1 = lys_schema_node_get_module(ctx, exp1->expr + exp1->tok_pos[i], exp1->tok_len[i], exp1_mod,
4795 &name1, &name1_len);
4796 assert(mod1);
4797 mod2 = lys_schema_node_get_module(ctx, exp2->expr + exp2->tok_pos[i], exp2->tok_len[i], exp2_mod,
4798 &name2, &name2_len);
4799 assert(mod2);
4800
4801 /* compare modules */
4802 if (mod1 != mod2) {
4803 return 0;
4804 }
4805
4806 /* compare names */
4807 if ((name1_len != name2_len) || strncmp(name1, name2, name1_len)) {
4808 return 0;
4809 }
4810 }
4811 }
4812
4813 return 1;
4814}
4815
4816/**
4817 * @brief Prepare any uses augments and refines in the context to be applied during uses descendant node compilation.
4818 *
4819 * @param[in] ctx Compile context.
4820 * @param[in] uses_p Parsed uses structure with augments and refines.
4821 * @param[in] ctx_node Context node of @p uses_p meaning its first data definiition parent.
4822 * @return LY_ERR value.
4823 */
4824static LY_ERR
4825lys_precompile_uses_augments_refines(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, const struct lysc_node *ctx_node)
4826{
4827 LY_ERR ret = LY_SUCCESS;
4828 LY_ARRAY_COUNT_TYPE u;
4829 struct lyxp_expr *exp = NULL;
4830 struct lysc_augment *aug;
4831 struct lysc_refine *rfn;
4832 struct lysp_refine **new_rfn;
4833 uint32_t i;
4834
4835 LY_ARRAY_FOR(uses_p->augments, u) {
4836 lysc_update_path(ctx, NULL, "{augment}");
4837 lysc_update_path(ctx, NULL, uses_p->augments[u].nodeid);
4838
4839 /* parse the nodeid */
4840 LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, uses_p->augments[u].nodeid, 0, NULL, &exp), cleanup);
4841
4842 /* allocate new compiled augment and store it in the set */
4843 aug = calloc(1, sizeof *aug);
4844 LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
4845 LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_augs, aug, LY_SET_OPT_USEASLIST, NULL), cleanup);
4846
4847 aug->nodeid = exp;
4848 exp = NULL;
4849 aug->nodeid_ctx_node = ctx_node;
4850 aug->aug_p = &uses_p->augments[u];
4851
4852 lysc_update_path(ctx, NULL, NULL);
4853 lysc_update_path(ctx, NULL, NULL);
4854 }
4855
4856 LY_ARRAY_FOR(uses_p->refines, u) {
4857 lysc_update_path(ctx, NULL, "{refine}");
4858 lysc_update_path(ctx, NULL, uses_p->refines[u].nodeid);
4859
4860 /* parse the nodeid */
4861 LY_CHECK_GOTO(ret = lys_nodeid_check(ctx, uses_p->refines[u].nodeid, 0, NULL, &exp), cleanup);
4862
4863 /* try to find the node in already compiled refines */
4864 rfn = NULL;
4865 for (i = 0; i < ctx->uses_rfns.count; ++i) {
4866 if (lys_abs_schema_nodeid_match(ctx->ctx, exp, ctx->mod_def, ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid,
4867 ctx->mod_def)) {
4868 rfn = ctx->uses_rfns.objs[i];
4869 break;
Radek Krejcif2271f12019-01-07 16:42:23 +01004870 }
4871 }
Michal Vasko601ddb32020-08-31 16:25:35 +02004872
Michal Vasko7f45cf22020-10-01 12:49:44 +02004873 if (!rfn) {
4874 /* allocate new compiled refine */
4875 rfn = calloc(1, sizeof *rfn);
4876 LY_CHECK_ERR_GOTO(!rfn, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
4877 LY_CHECK_GOTO(ret = ly_set_add(&ctx->uses_rfns, rfn, LY_SET_OPT_USEASLIST, NULL), cleanup);
4878
4879 rfn->nodeid = exp;
4880 exp = NULL;
4881 rfn->nodeid_ctx_node = ctx_node;
4882 } else {
4883 /* just free exp */
4884 lyxp_expr_free(ctx->ctx, exp);
4885 exp = NULL;
4886 }
4887
4888 /* add new parsed refine structure */
4889 LY_ARRAY_NEW_GOTO(ctx->ctx, rfn->rfns, new_rfn, ret, cleanup);
4890 *new_rfn = &uses_p->refines[u];
4891
4892 lysc_update_path(ctx, NULL, NULL);
Michal Vasko601ddb32020-08-31 16:25:35 +02004893 lysc_update_path(ctx, NULL, NULL);
Radek Krejcif2271f12019-01-07 16:42:23 +01004894 }
4895
Michal Vasko601ddb32020-08-31 16:25:35 +02004896cleanup:
Michal Vasko7f45cf22020-10-01 12:49:44 +02004897 lyxp_expr_free(ctx->ctx, exp);
Michal Vasko601ddb32020-08-31 16:25:35 +02004898 return ret;
4899}
4900
4901/**
4902 * @brief Compile parsed uses statement - resolve target grouping and connect its content into parent.
4903 * If present, also apply uses's modificators.
4904 *
4905 * @param[in] ctx Compile context
4906 * @param[in] uses_p Parsed uses schema node.
4907 * @param[in] parent Compiled parent node where the content of the referenced grouping is supposed to be connected. It is
4908 * NULL for top-level nodes, in such a case the module where the node will be connected is taken from
4909 * the compile context.
4910 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
4911 */
4912static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02004913lys_compile_uses(struct lysc_ctx *ctx, struct lysp_node_uses *uses_p, struct lysc_node *parent, struct ly_set *child_set)
Michal Vasko601ddb32020-08-31 16:25:35 +02004914{
Michal Vasko7f45cf22020-10-01 12:49:44 +02004915 struct lysp_node *pnode;
4916 struct lysc_node *child;
Michal Vasko601ddb32020-08-31 16:25:35 +02004917 struct lysp_grp *grp = NULL;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004918 uint32_t i, grp_stack_count;
Michal Vaskoaf702452020-10-02 09:02:55 +02004919 struct lys_module *grp_mod, *mod_old = ctx->mod_def;
Michal Vasko601ddb32020-08-31 16:25:35 +02004920 LY_ERR ret = LY_SUCCESS;
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004921 struct lysc_when *when_shared = NULL;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004922 LY_ARRAY_COUNT_TYPE u;
Michal Vasko601ddb32020-08-31 16:25:35 +02004923 struct lysc_notif **notifs = NULL;
4924 struct lysc_action **actions = NULL;
Michal Vasko7f45cf22020-10-01 12:49:44 +02004925 struct ly_set uses_child_set = {0};
Michal Vasko601ddb32020-08-31 16:25:35 +02004926
4927 /* find the referenced grouping */
4928 LY_CHECK_RET(lys_compile_uses_find_grouping(ctx, uses_p, &grp, &grp_mod));
4929
4930 /* grouping must not reference themselves - stack in ctx maintains list of groupings currently being applied */
4931 grp_stack_count = ctx->groupings.count;
4932 LY_CHECK_RET(ly_set_add(&ctx->groupings, (void *)grp, 0, NULL));
4933 if (grp_stack_count == ctx->groupings.count) {
4934 /* the target grouping is already in the stack, so we are already inside it -> circular dependency */
4935 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02004936 "Grouping \"%s\" references itself through a uses statement.", grp->name);
Michal Vasko601ddb32020-08-31 16:25:35 +02004937 return LY_EVALID;
4938 }
4939
Michal Vasko7f45cf22020-10-01 12:49:44 +02004940 /* check status */
4941 ret = lysc_check_status(ctx, uses_p->flags, ctx->mod_def, uses_p->name, grp->flags, grp_mod, grp->name);
4942 LY_CHECK_GOTO(ret, cleanup);
4943
4944 /* compile any augments and refines so they can be applied during the grouping nodes compilation */
4945 ret = lys_precompile_uses_augments_refines(ctx, uses_p, parent);
4946 LY_CHECK_GOTO(ret, cleanup);
4947
Michal Vasko601ddb32020-08-31 16:25:35 +02004948 /* switch context's mod_def */
Michal Vasko601ddb32020-08-31 16:25:35 +02004949 ctx->mod_def = grp_mod;
4950
Michal Vasko601ddb32020-08-31 16:25:35 +02004951 /* compile data nodes */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004952 LY_LIST_FOR(grp->data, pnode) {
Michal Vasko601ddb32020-08-31 16:25:35 +02004953 /* 0x3 in uses_status is a special bits combination to be able to detect status flags from uses */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004954 ret = lys_compile_node(ctx, pnode, parent, (uses_p->flags & LYS_STATUS_MASK) | 0x3, &uses_child_set);
Michal Vasko601ddb32020-08-31 16:25:35 +02004955 LY_CHECK_GOTO(ret, cleanup);
4956 }
4957
Michal Vasko7f45cf22020-10-01 12:49:44 +02004958 if (child_set) {
4959 /* add these children to our compiled child_set as well since uses is a schema-only node */
4960 LY_CHECK_GOTO(ret = ly_set_merge(child_set, &uses_child_set, LY_SET_OPT_USEASLIST, NULL), cleanup);
Michal Vasko601ddb32020-08-31 16:25:35 +02004961 }
4962
Michal Vasko7f45cf22020-10-01 12:49:44 +02004963 if (uses_p->when) {
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004964 /* pass uses's when to all the data children */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004965 for (i = 0; i < uses_child_set.count; ++i) {
4966 child = uses_child_set.snodes[i];
4967
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004968 ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_xpath_context(parent), child, &when_shared);
4969 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko601ddb32020-08-31 16:25:35 +02004970 }
4971 }
4972
4973 /* compile actions */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004974 if (grp->actions) {
4975 actions = parent ? lysc_node_actions_p(parent) : &ctx->mod->compiled->rpcs;
4976 if (!actions) {
4977 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
Michal Vasko69730152020-10-09 16:30:07 +02004978 grp->actions[0].name, lys_nodetype2str(grp->actions[0].nodetype), parent->name,
4979 lys_nodetype2str(parent->nodetype));
Michal Vasko7f45cf22020-10-01 12:49:44 +02004980 ret = LY_EVALID;
4981 goto cleanup;
Michal Vasko601ddb32020-08-31 16:25:35 +02004982 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02004983 COMPILE_OP_ARRAY_GOTO(ctx, grp->actions, *actions, parent, u, lys_compile_action, 0, ret, cleanup);
Michal Vaskoceab6dd2020-10-09 16:53:36 +02004984
4985 if (uses_p->when) {
4986 /* inherit when */
4987 LY_ARRAY_FOR(*actions, u) {
4988 ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_xpath_context(parent),
4989 (struct lysc_node *)&(*actions)[u], &when_shared);
4990 LY_CHECK_GOTO(ret, cleanup);
4991 }
4992 }
Michal Vasko601ddb32020-08-31 16:25:35 +02004993 }
4994
4995 /* compile notifications */
Michal Vasko7f45cf22020-10-01 12:49:44 +02004996 if (grp->notifs) {
4997 notifs = parent ? lysc_node_notifs_p(parent) : &ctx->mod->compiled->notifs;
4998 if (!notifs) {
4999 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid child %s \"%s\" of uses parent %s \"%s\" node.",
Michal Vasko69730152020-10-09 16:30:07 +02005000 grp->notifs[0].name, lys_nodetype2str(grp->notifs[0].nodetype), parent->name,
5001 lys_nodetype2str(parent->nodetype));
Michal Vasko7f45cf22020-10-01 12:49:44 +02005002 ret = LY_EVALID;
5003 goto cleanup;
Michal Vasko601ddb32020-08-31 16:25:35 +02005004 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02005005 COMPILE_OP_ARRAY_GOTO(ctx, grp->notifs, *notifs, parent, u, lys_compile_notif, 0, ret, cleanup);
Michal Vaskoceab6dd2020-10-09 16:53:36 +02005006
5007 if (uses_p->when) {
5008 /* inherit when */
5009 LY_ARRAY_FOR(*notifs, u) {
5010 ret = lys_compile_when(ctx, uses_p->when, uses_p->flags, lysc_xpath_context(parent),
5011 (struct lysc_node *)&(*notifs)[u], &when_shared);
5012 LY_CHECK_GOTO(ret, cleanup);
5013 }
5014 }
Michal Vasko601ddb32020-08-31 16:25:35 +02005015 }
5016
Michal Vasko7f45cf22020-10-01 12:49:44 +02005017 /* check that all augments were applied */
5018 for (i = 0; i < ctx->uses_augs.count; ++i) {
5019 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02005020 "Augment target node \"%s\" in grouping \"%s\" was not found.",
Michal Vasko891d7532020-10-07 09:41:38 +02005021 ((struct lysc_augment *)ctx->uses_augs.objs[i])->nodeid->expr, grp->name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005022 ret = LY_ENOTFOUND;
Michal Vasko601ddb32020-08-31 16:25:35 +02005023 }
Michal Vasko601ddb32020-08-31 16:25:35 +02005024 LY_CHECK_GOTO(ret, cleanup);
5025
Michal Vasko7f45cf22020-10-01 12:49:44 +02005026 /* check that all refines were applied */
5027 for (i = 0; i < ctx->uses_rfns.count; ++i) {
5028 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02005029 "Refine(s) target node \"%s\" in grouping \"%s\" was not found.",
Michal Vasko891d7532020-10-07 09:41:38 +02005030 ((struct lysc_refine *)ctx->uses_rfns.objs[i])->nodeid->expr, grp->name);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005031 ret = LY_ENOTFOUND;
Radek Krejcic6b4f442020-08-12 14:45:18 +02005032 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02005033 LY_CHECK_GOTO(ret, cleanup);
Radek Krejcifc11bd72019-04-11 16:00:05 +02005034
5035cleanup:
Radek Krejcie86bf772018-12-14 11:39:53 +01005036 /* reload previous context's mod_def */
5037 ctx->mod_def = mod_old;
Michal Vasko7f45cf22020-10-01 12:49:44 +02005038
Radek Krejcie86bf772018-12-14 11:39:53 +01005039 /* remove the grouping from the stack for circular groupings dependency check */
5040 ly_set_rm_index(&ctx->groupings, ctx->groupings.count - 1, NULL);
5041 assert(ctx->groupings.count == grp_stack_count);
5042
Michal Vasko7f45cf22020-10-01 12:49:44 +02005043 ly_set_erase(&uses_child_set, NULL);
Radek Krejcie86bf772018-12-14 11:39:53 +01005044 return ret;
5045}
5046
Radek Krejci327de162019-06-14 12:52:07 +02005047static int
5048lys_compile_grouping_pathlog(struct lysc_ctx *ctx, struct lysp_node *node, char **path)
5049{
5050 struct lysp_node *iter;
5051 int len = 0;
5052
5053 *path = NULL;
5054 for (iter = node; iter && len >= 0; iter = iter->parent) {
5055 char *s = *path;
5056 char *id;
5057
5058 switch (iter->nodetype) {
5059 case LYS_USES:
Radek Krejci200f1062020-07-11 22:51:03 +02005060 LY_CHECK_RET(asprintf(&id, "{uses='%s'}", iter->name) == -1, -1);
Radek Krejci327de162019-06-14 12:52:07 +02005061 break;
5062 case LYS_GROUPING:
Radek Krejci200f1062020-07-11 22:51:03 +02005063 LY_CHECK_RET(asprintf(&id, "{grouping='%s'}", iter->name) == -1, -1);
Radek Krejci327de162019-06-14 12:52:07 +02005064 break;
5065 case LYS_AUGMENT:
Radek Krejci200f1062020-07-11 22:51:03 +02005066 LY_CHECK_RET(asprintf(&id, "{augment='%s'}", iter->name) == -1, -1);
Radek Krejci327de162019-06-14 12:52:07 +02005067 break;
5068 default:
5069 id = strdup(iter->name);
5070 break;
5071 }
5072
5073 if (!iter->parent) {
5074 /* print prefix */
5075 len = asprintf(path, "/%s:%s%s", ctx->mod->name, id, s ? s : "");
5076 } else {
5077 /* prefix is the same as in parent */
5078 len = asprintf(path, "/%s%s", id, s ? s : "");
5079 }
5080 free(s);
5081 free(id);
5082 }
5083
5084 if (len < 0) {
5085 free(*path);
5086 *path = NULL;
5087 } else if (len == 0) {
5088 *path = strdup("/");
5089 len = 1;
5090 }
5091 return len;
5092}
5093
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005094/**
5095 * @brief Validate groupings that were defined but not directly used in the schema itself.
5096 *
5097 * The grouping does not need to be compiled (and it is compiled here, but the result is forgotten immediately),
5098 * but to have the complete result of the schema validity, even such groupings are supposed to be checked.
5099 */
5100static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02005101lys_compile_grouping(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysp_grp *grp)
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005102{
5103 LY_ERR ret;
Radek Krejci327de162019-06-14 12:52:07 +02005104 char *path;
5105 int len;
5106
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005107 struct lysp_node_uses fake_uses = {
Michal Vasko7f45cf22020-10-01 12:49:44 +02005108 .parent = pnode,
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005109 .nodetype = LYS_USES,
5110 .flags = 0, .next = NULL,
5111 .name = grp->name,
5112 .dsc = NULL, .ref = NULL, .when = NULL, .iffeatures = NULL, .exts = NULL,
5113 .refines = NULL, .augments = NULL
5114 };
5115 struct lysc_node_container fake_container = {
5116 .nodetype = LYS_CONTAINER,
Michal Vasko7f45cf22020-10-01 12:49:44 +02005117 .flags = pnode ? (pnode->flags & LYS_FLAGS_COMPILED_MASK) : 0,
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005118 .module = ctx->mod,
5119 .sp = NULL, .parent = NULL, .next = NULL,
Michal Vasko22df3f02020-08-24 13:29:22 +02005120 .prev = (struct lysc_node *)&fake_container,
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005121 .name = "fake",
5122 .dsc = NULL, .ref = NULL, .exts = NULL, .iffeatures = NULL, .when = NULL,
5123 .child = NULL, .musts = NULL, .actions = NULL, .notifs = NULL
5124 };
5125
5126 if (grp->parent) {
5127 LOGWRN(ctx->ctx, "Locally scoped grouping \"%s\" not used.", grp->name);
5128 }
Radek Krejci327de162019-06-14 12:52:07 +02005129
5130 len = lys_compile_grouping_pathlog(ctx, grp->parent, &path);
5131 if (len < 0) {
5132 LOGMEM(ctx->ctx);
5133 return LY_EMEM;
5134 }
5135 strncpy(ctx->path, path, LYSC_CTX_BUFSIZE - 1);
Radek Krejci1deb5be2020-08-26 16:43:36 +02005136 ctx->path_len = (uint32_t)len;
Radek Krejci327de162019-06-14 12:52:07 +02005137 free(path);
5138
5139 lysc_update_path(ctx, NULL, "{grouping}");
5140 lysc_update_path(ctx, NULL, grp->name);
Michal Vasko22df3f02020-08-24 13:29:22 +02005141 ret = lys_compile_uses(ctx, &fake_uses, (struct lysc_node *)&fake_container, NULL);
Radek Krejci327de162019-06-14 12:52:07 +02005142 lysc_update_path(ctx, NULL, NULL);
5143 lysc_update_path(ctx, NULL, NULL);
5144
5145 ctx->path_len = 1;
5146 ctx->path[1] = '\0';
Radek Krejcif2de0ed2019-05-02 14:13:18 +02005147
5148 /* cleanup */
5149 lysc_node_container_free(ctx->ctx, &fake_container);
5150
5151 return ret;
5152}
Radek Krejcife909632019-02-12 15:34:42 +01005153
Radek Krejcie86bf772018-12-14 11:39:53 +01005154/**
Michal Vasko20424b42020-08-31 12:29:38 +02005155 * @brief Set config flags for a node.
5156 *
5157 * @param[in] ctx Compile context.
5158 * @param[in] node Compiled node config to set.
5159 * @param[in] parent Parent of @p node.
5160 * @return LY_ERR value.
5161 */
5162static LY_ERR
5163lys_compile_config(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_node *parent)
5164{
5165 if (node->nodetype == LYS_CASE) {
5166 /* case never has any config */
5167 assert(!(node->flags & LYS_CONFIG_MASK));
5168 return LY_SUCCESS;
5169 }
5170
5171 /* adjust parent to always get the ancestor with config */
5172 if (parent && (parent->nodetype == LYS_CASE)) {
5173 parent = parent->parent;
5174 assert(parent);
5175 }
5176
5177 if (ctx->options & (LYSC_OPT_RPC_INPUT | LYSC_OPT_RPC_OUTPUT)) {
5178 /* ignore config statements inside RPC/action data */
5179 node->flags &= ~LYS_CONFIG_MASK;
5180 node->flags |= (ctx->options & LYSC_OPT_RPC_INPUT) ? LYS_CONFIG_W : LYS_CONFIG_R;
5181 } else if (ctx->options & LYSC_OPT_NOTIFICATION) {
5182 /* ignore config statements inside Notification data */
5183 node->flags &= ~LYS_CONFIG_MASK;
5184 node->flags |= LYS_CONFIG_R;
5185 } else if (!(node->flags & LYS_CONFIG_MASK)) {
5186 /* config not explicitely set, inherit it from parent */
5187 if (parent) {
5188 node->flags |= parent->flags & LYS_CONFIG_MASK;
5189 } else {
5190 /* default is config true */
5191 node->flags |= LYS_CONFIG_W;
5192 }
5193 } else {
5194 /* config set explicitely */
5195 node->flags |= LYS_SET_CONFIG;
5196 }
5197
5198 if (parent && (parent->flags & LYS_CONFIG_R) && (node->flags & LYS_CONFIG_W)) {
5199 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02005200 "Configuration node cannot be child of any state data node.");
Michal Vasko20424b42020-08-31 12:29:38 +02005201 return LY_EVALID;
5202 }
5203
5204 return LY_SUCCESS;
5205}
5206
Michal Vasko7f45cf22020-10-01 12:49:44 +02005207static LY_ERR
5208lysp_ext_dup(const struct ly_ctx *ctx, struct lysp_ext_instance *ext, const struct lysp_ext_instance *orig_ext)
5209{
5210 LY_ERR ret = LY_SUCCESS;
5211
5212 *ext = *orig_ext;
5213 DUP_STRING(ctx, orig_ext->name, ext->name, ret);
5214 DUP_STRING(ctx, orig_ext->argument, ext->argument, ret);
5215
5216 return ret;
5217}
5218
5219static LY_ERR
5220lysp_restr_dup(const struct ly_ctx *ctx, struct lysp_restr *restr, const struct lysp_restr *orig_restr)
5221{
5222 LY_ERR ret = LY_SUCCESS;
5223
5224 if (orig_restr) {
5225 DUP_STRING(ctx, orig_restr->arg.str, restr->arg.str, ret);
5226 restr->arg.mod = orig_restr->arg.mod;
5227 DUP_STRING(ctx, orig_restr->emsg, restr->emsg, ret);
5228 DUP_STRING(ctx, orig_restr->eapptag, restr->eapptag, ret);
5229 DUP_STRING(ctx, orig_restr->dsc, restr->dsc, ret);
5230 DUP_STRING(ctx, orig_restr->ref, restr->ref, ret);
5231 DUP_ARRAY(ctx, orig_restr->exts, restr->exts, lysp_ext_dup);
5232 }
5233
5234 return ret;
5235}
5236
5237static LY_ERR
5238lysp_string_dup(const struct ly_ctx *ctx, const char **str, const char **orig_str)
5239{
5240 LY_ERR ret = LY_SUCCESS;
5241
5242 DUP_STRING(ctx, *orig_str, *str, ret);
5243
5244 return ret;
5245}
5246
5247static LY_ERR
5248lysp_qname_dup(const struct ly_ctx *ctx, struct lysp_qname *qname, const struct lysp_qname *orig_qname)
5249{
5250 LY_ERR ret = LY_SUCCESS;
5251
Michal Vaskoe9c050f2020-10-06 14:01:23 +02005252 if (!orig_qname->str) {
5253 return LY_SUCCESS;
5254 }
5255
Michal Vasko7f45cf22020-10-01 12:49:44 +02005256 DUP_STRING(ctx, orig_qname->str, qname->str, ret);
Michal Vaskoe9c050f2020-10-06 14:01:23 +02005257 assert(orig_qname->mod);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005258 qname->mod = orig_qname->mod;
5259
5260 return ret;
5261}
5262
5263static LY_ERR
5264lysp_type_enum_dup(const struct ly_ctx *ctx, struct lysp_type_enum *enm, const struct lysp_type_enum *orig_enm)
5265{
5266 LY_ERR ret = LY_SUCCESS;
5267
5268 DUP_STRING(ctx, orig_enm->name, enm->name, ret);
5269 DUP_STRING(ctx, orig_enm->dsc, enm->dsc, ret);
5270 DUP_STRING(ctx, orig_enm->ref, enm->ref, ret);
5271 enm->value = orig_enm->value;
5272 DUP_ARRAY(ctx, orig_enm->iffeatures, enm->iffeatures, lysp_qname_dup);
5273 DUP_ARRAY(ctx, orig_enm->exts, enm->exts, lysp_ext_dup);
5274 enm->flags = orig_enm->flags;
5275
5276 return ret;
5277}
5278
5279static LY_ERR
5280lysp_type_dup(const struct ly_ctx *ctx, struct lysp_type *type, const struct lysp_type *orig_type)
5281{
5282 LY_ERR ret = LY_SUCCESS;
5283
5284 DUP_STRING_GOTO(ctx, orig_type->name, type->name, ret, done);
5285
5286 if (orig_type->range) {
5287 type->range = calloc(1, sizeof *type->range);
5288 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx), LY_EMEM);
5289 LY_CHECK_RET(lysp_restr_dup(ctx, type->range, orig_type->range));
5290 }
5291
5292 if (orig_type->length) {
5293 type->length = calloc(1, sizeof *type->length);
5294 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx), LY_EMEM);
5295 LY_CHECK_RET(lysp_restr_dup(ctx, type->length, orig_type->length));
5296 }
5297
5298 DUP_ARRAY(ctx, orig_type->patterns, type->patterns, lysp_restr_dup);
5299 DUP_ARRAY(ctx, orig_type->enums, type->enums, lysp_type_enum_dup);
5300 DUP_ARRAY(ctx, orig_type->bits, type->bits, lysp_type_enum_dup);
5301 LY_CHECK_GOTO(ret = lyxp_expr_dup(ctx, orig_type->path, &type->path), done);
5302 DUP_ARRAY(ctx, orig_type->bases, type->bases, lysp_string_dup);
5303 DUP_ARRAY(ctx, orig_type->types, type->types, lysp_type_dup);
5304 DUP_ARRAY(ctx, orig_type->exts, type->exts, lysp_ext_dup);
5305
Michal Vaskoe9c050f2020-10-06 14:01:23 +02005306 type->mod = orig_type->mod;
Michal Vasko7f45cf22020-10-01 12:49:44 +02005307 type->compiled = orig_type->compiled;
5308
5309 type->fraction_digits = orig_type->fraction_digits;
5310 type->require_instance = orig_type->require_instance;
5311 type->flags = orig_type->flags;
5312
5313done:
5314 return ret;
5315}
5316
5317static LY_ERR
5318lysp_when_dup(const struct ly_ctx *ctx, struct lysp_when *when, const struct lysp_when *orig_when)
5319{
5320 LY_ERR ret = LY_SUCCESS;
5321
5322 DUP_STRING(ctx, orig_when->cond, when->cond, ret);
5323 DUP_STRING(ctx, orig_when->dsc, when->dsc, ret);
5324 DUP_STRING(ctx, orig_when->ref, when->ref, ret);
5325 DUP_ARRAY(ctx, orig_when->exts, when->exts, lysp_ext_dup);
5326
5327 return ret;
5328}
5329
5330static LY_ERR
5331lysp_node_common_dup(const struct ly_ctx *ctx, struct lysp_node *node, const struct lysp_node *orig)
5332{
5333 LY_ERR ret = LY_SUCCESS;
5334
5335 node->parent = NULL;
5336 node->nodetype = orig->nodetype;
5337 node->flags = orig->flags;
5338 node->next = NULL;
5339 DUP_STRING(ctx, orig->name, node->name, ret);
5340 DUP_STRING(ctx, orig->dsc, node->dsc, ret);
5341 DUP_STRING(ctx, orig->ref, node->ref, ret);
5342
5343 if (orig->when) {
5344 node->when = calloc(1, sizeof *node->when);
5345 LY_CHECK_ERR_RET(!node->when, LOGMEM(ctx), LY_EMEM);
5346 LY_CHECK_RET(lysp_when_dup(ctx, node->when, orig->when));
5347 }
5348
5349 DUP_ARRAY(ctx, orig->iffeatures, node->iffeatures, lysp_qname_dup);
5350 DUP_ARRAY(ctx, orig->exts, node->exts, lysp_ext_dup);
5351
5352 return ret;
5353}
5354
5355static LY_ERR
5356lysp_node_dup(const struct ly_ctx *ctx, struct lysp_node *node, const struct lysp_node *orig)
5357{
5358 LY_ERR ret = LY_SUCCESS;
5359 struct lysp_node_container *cont;
5360 const struct lysp_node_container *orig_cont;
5361 struct lysp_node_leaf *leaf;
5362 const struct lysp_node_leaf *orig_leaf;
5363 struct lysp_node_leaflist *llist;
5364 const struct lysp_node_leaflist *orig_llist;
5365 struct lysp_node_list *list;
5366 const struct lysp_node_list *orig_list;
5367 struct lysp_node_choice *choice;
5368 const struct lysp_node_choice *orig_choice;
5369 struct lysp_node_case *cas;
5370 const struct lysp_node_case *orig_cas;
5371 struct lysp_node_anydata *any;
5372 const struct lysp_node_anydata *orig_any;
5373
5374 assert(orig->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CHOICE | LYS_CASE | LYS_ANYDATA));
5375
5376 /* common part */
5377 LY_CHECK_RET(lysp_node_common_dup(ctx, node, orig));
5378
5379 /* specific part */
5380 switch (node->nodetype) {
5381 case LYS_CONTAINER:
5382 cont = (struct lysp_node_container *)node;
5383 orig_cont = (const struct lysp_node_container *)orig;
5384
5385 DUP_ARRAY(ctx, orig_cont->musts, cont->musts, lysp_restr_dup);
5386 DUP_STRING(ctx, orig_cont->presence, cont->presence, ret);
5387 /* we do not need the rest */
5388 break;
5389 case LYS_LEAF:
5390 leaf = (struct lysp_node_leaf *)node;
5391 orig_leaf = (const struct lysp_node_leaf *)orig;
5392
5393 DUP_ARRAY(ctx, orig_leaf->musts, leaf->musts, lysp_restr_dup);
5394 LY_CHECK_RET(lysp_type_dup(ctx, &leaf->type, &orig_leaf->type));
5395 DUP_STRING(ctx, orig_leaf->units, leaf->units, ret);
Michal Vaskoe9c050f2020-10-06 14:01:23 +02005396 LY_CHECK_RET(lysp_qname_dup(ctx, &leaf->dflt, &orig_leaf->dflt));
Michal Vasko7f45cf22020-10-01 12:49:44 +02005397 break;
5398 case LYS_LEAFLIST:
5399 llist = (struct lysp_node_leaflist *)node;
5400 orig_llist = (const struct lysp_node_leaflist *)orig;
5401
5402 DUP_ARRAY(ctx, orig_llist->musts, llist->musts, lysp_restr_dup);
5403 LY_CHECK_RET(lysp_type_dup(ctx, &llist->type, &orig_llist->type));
5404 DUP_STRING(ctx, orig_llist->units, llist->units, ret);
5405 DUP_ARRAY(ctx, orig_llist->dflts, llist->dflts, lysp_qname_dup);
5406 llist->min = orig_llist->min;
5407 llist->max = orig_llist->max;
5408 break;
5409 case LYS_LIST:
5410 list = (struct lysp_node_list *)node;
5411 orig_list = (const struct lysp_node_list *)orig;
5412
5413 DUP_ARRAY(ctx, orig_list->musts, list->musts, lysp_restr_dup);
5414 DUP_STRING(ctx, orig_list->key, list->key, ret);
5415 /* we do not need these arrays */
5416 DUP_ARRAY(ctx, orig_list->uniques, list->uniques, lysp_qname_dup);
5417 list->min = orig_list->min;
5418 list->max = orig_list->max;
5419 break;
5420 case LYS_CHOICE:
5421 choice = (struct lysp_node_choice *)node;
5422 orig_choice = (const struct lysp_node_choice *)orig;
5423
5424 /* we do not need children */
5425 LY_CHECK_RET(lysp_qname_dup(ctx, &choice->dflt, &orig_choice->dflt));
5426 break;
5427 case LYS_CASE:
5428 cas = (struct lysp_node_case *)node;
5429 orig_cas = (const struct lysp_node_case *)orig;
5430
5431 /* we do not need children */
5432 (void)cas;
5433 (void)orig_cas;
5434 break;
5435 case LYS_ANYDATA:
5436 case LYS_ANYXML:
5437 any = (struct lysp_node_anydata *)node;
5438 orig_any = (const struct lysp_node_anydata *)orig;
5439
5440 DUP_ARRAY(ctx, orig_any->musts, any->musts, lysp_restr_dup);
5441 break;
5442 default:
5443 LOGINT_RET(ctx);
5444 }
5445
5446 return ret;
5447}
5448
5449static LY_ERR
5450lysp_action_inout_dup(const struct ly_ctx *ctx, struct lysp_action_inout *inout, const struct lysp_action_inout *orig)
5451{
5452 inout->parent = NULL;
5453 inout->nodetype = orig->nodetype;
5454 DUP_ARRAY(ctx, orig->musts, inout->musts, lysp_restr_dup);
5455 /* we dot need these arrays */
5456 DUP_ARRAY(ctx, orig->exts, inout->exts, lysp_ext_dup);
5457
5458 return LY_SUCCESS;
5459}
5460
5461static LY_ERR
5462lysp_action_dup(const struct ly_ctx *ctx, struct lysp_action *act, const struct lysp_action *orig)
5463{
5464 LY_ERR ret = LY_SUCCESS;
5465
5466 act->parent = NULL;
5467 act->nodetype = orig->nodetype;
5468 act->flags = orig->flags;
5469 DUP_STRING(ctx, orig->name, act->name, ret);
5470 DUP_STRING(ctx, orig->dsc, act->dsc, ret);
5471 DUP_STRING(ctx, orig->ref, act->ref, ret);
5472 DUP_ARRAY(ctx, orig->iffeatures, act->iffeatures, lysp_qname_dup);
5473
5474 act->input.nodetype = orig->input.nodetype;
5475 act->output.nodetype = orig->output.nodetype;
5476 /* we do not need choldren of in/out */
5477 DUP_ARRAY(ctx, orig->exts, act->exts, lysp_ext_dup);
5478
5479 return ret;
5480}
5481
5482static LY_ERR
5483lysp_notif_dup(const struct ly_ctx *ctx, struct lysp_notif *notif, const struct lysp_notif *orig)
5484{
5485 LY_ERR ret = LY_SUCCESS;
5486
5487 notif->parent = NULL;
5488 notif->nodetype = orig->nodetype;
5489 notif->flags = orig->flags;
5490 DUP_STRING(ctx, orig->name, notif->name, ret);
5491 DUP_STRING(ctx, orig->dsc, notif->dsc, ret);
5492 DUP_STRING(ctx, orig->ref, notif->ref, ret);
5493 DUP_ARRAY(ctx, orig->iffeatures, notif->iffeatures, lysp_qname_dup);
5494 DUP_ARRAY(ctx, orig->musts, notif->musts, lysp_restr_dup);
5495 /* we do not need these arrays */
5496 DUP_ARRAY(ctx, orig->exts, notif->exts, lysp_ext_dup);
5497
5498 return ret;
5499}
5500
5501/**
5502 * @brief Duplicate a single parsed node. Only attributes that are used in compilation are copied.
5503 *
5504 * @param[in] ctx libyang context.
5505 * @param[in] pnode Node to duplicate.
5506 * @param[in] with_links Whether to also copy any links (child, parent pointers).
5507 * @param[out] dup_p Duplicated parsed node.
5508 * @return LY_ERR value.
5509 */
5510static LY_ERR
5511lysp_dup_single(const struct ly_ctx *ctx, const struct lysp_node *pnode, ly_bool with_links, struct lysp_node **dup_p)
5512{
Michal Vaskoaf702452020-10-02 09:02:55 +02005513 LY_ERR ret = LY_SUCCESS;
5514 void *mem = NULL;
Michal Vasko7f45cf22020-10-01 12:49:44 +02005515
5516 if (!pnode) {
5517 *dup_p = NULL;
5518 return LY_SUCCESS;
5519 }
5520
5521 switch (pnode->nodetype) {
5522 case LYS_CONTAINER:
5523 mem = calloc(1, sizeof(struct lysp_node_container));
Michal Vaskoaf702452020-10-02 09:02:55 +02005524 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5525 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005526 break;
5527 case LYS_LEAF:
5528 mem = calloc(1, sizeof(struct lysp_node_leaf));
Michal Vaskoaf702452020-10-02 09:02:55 +02005529 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5530 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005531 break;
5532 case LYS_LEAFLIST:
5533 mem = calloc(1, sizeof(struct lysp_node_leaflist));
Michal Vaskoaf702452020-10-02 09:02:55 +02005534 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5535 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005536 break;
5537 case LYS_LIST:
5538 mem = calloc(1, sizeof(struct lysp_node_list));
Michal Vaskoaf702452020-10-02 09:02:55 +02005539 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5540 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005541 break;
5542 case LYS_CHOICE:
5543 mem = calloc(1, sizeof(struct lysp_node_choice));
Michal Vaskoaf702452020-10-02 09:02:55 +02005544 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5545 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005546 break;
5547 case LYS_CASE:
5548 mem = calloc(1, sizeof(struct lysp_node_case));
Michal Vaskoaf702452020-10-02 09:02:55 +02005549 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5550 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005551 break;
5552 case LYS_ANYDATA:
5553 case LYS_ANYXML:
5554 mem = calloc(1, sizeof(struct lysp_node_anydata));
Michal Vaskoaf702452020-10-02 09:02:55 +02005555 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5556 LY_CHECK_GOTO(ret = lysp_node_dup(ctx, mem, pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005557 break;
5558 case LYS_INPUT:
5559 case LYS_OUTPUT:
5560 mem = calloc(1, sizeof(struct lysp_action_inout));
Michal Vaskoaf702452020-10-02 09:02:55 +02005561 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5562 LY_CHECK_GOTO(ret = lysp_action_inout_dup(ctx, mem, (struct lysp_action_inout *)pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005563 break;
5564 case LYS_ACTION:
5565 case LYS_RPC:
5566 mem = calloc(1, sizeof(struct lysp_action));
Michal Vaskoaf702452020-10-02 09:02:55 +02005567 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5568 LY_CHECK_GOTO(ret = lysp_action_dup(ctx, mem, (struct lysp_action *)pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005569 break;
5570 case LYS_NOTIF:
5571 mem = calloc(1, sizeof(struct lysp_notif));
Michal Vaskoaf702452020-10-02 09:02:55 +02005572 LY_CHECK_ERR_GOTO(!mem, LOGMEM(ctx); ret = LY_EMEM, cleanup);
5573 LY_CHECK_GOTO(ret = lysp_notif_dup(ctx, mem, (struct lysp_notif *)pnode), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02005574 break;
5575 default:
5576 LOGINT_RET(ctx);
5577 }
5578
5579 if (with_links) {
5580 /* copy also parent and child pointers */
5581 ((struct lysp_node *)mem)->parent = pnode->parent;
5582 switch (pnode->nodetype) {
5583 case LYS_CONTAINER:
5584 ((struct lysp_node_container *)mem)->child = ((struct lysp_node_container *)pnode)->child;
5585 break;
5586 case LYS_LIST:
5587 ((struct lysp_node_list *)mem)->child = ((struct lysp_node_list *)pnode)->child;
5588 break;
5589 case LYS_CHOICE:
5590 ((struct lysp_node_choice *)mem)->child = ((struct lysp_node_choice *)pnode)->child;
5591 break;
5592 case LYS_CASE:
5593 ((struct lysp_node_case *)mem)->child = ((struct lysp_node_case *)pnode)->child;
5594 break;
5595 default:
5596 break;
5597 }
5598 }
5599
Michal Vaskoaf702452020-10-02 09:02:55 +02005600cleanup:
5601 if (ret) {
5602 free(mem);
5603 } else {
5604 *dup_p = mem;
5605 }
5606 return ret;
Michal Vasko7f45cf22020-10-01 12:49:44 +02005607}
5608
5609#define AMEND_WRONG_NODETYPE(AMEND_STR, OP_STR, PROPERTY) \
5610 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, "Invalid %s of %s node - it is not possible to %s \"%s\" property.", \
5611 AMEND_STR, lys_nodetype2str(target->nodetype), OP_STR, PROPERTY);\
5612 ret = LY_EVALID; \
5613 goto cleanup;
5614
5615#define AMEND_CHECK_CARDINALITY(ARRAY, MAX, AMEND_STR, PROPERTY) \
5616 if (LY_ARRAY_COUNT(ARRAY) > MAX) { \
5617 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS, "Invalid %s of %s with too many (%"LY_PRI_ARRAY_COUNT_TYPE") %s properties.", \
5618 AMEND_STR, lys_nodetype2str(target->nodetype), LY_ARRAY_COUNT(ARRAY), PROPERTY); \
5619 ret = LY_EVALID; \
5620 goto cleanup; \
5621 }
5622
5623/**
5624 * @brief Apply refine.
5625 *
5626 * @param[in] ctx Compile context.
5627 * @param[in] rfn Refine to apply.
5628 * @param[in,out] target Refine target.
5629 * @return LY_ERR value.
5630 */
5631static LY_ERR
5632lys_apply_refine(struct lysc_ctx *ctx, struct lysp_refine *rfn, struct lysp_node *target)
5633{
5634 LY_ERR ret = LY_SUCCESS;
5635 LY_ARRAY_COUNT_TYPE u;
5636 struct lysp_qname *qname;
5637 struct lysp_restr **musts, *must;
5638 uint32_t *num;
5639
5640 /* default value */
5641 if (rfn->dflts) {
5642 switch (target->nodetype) {
5643 case LYS_LEAF:
5644 AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default");
5645
5646 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
5647 DUP_STRING_GOTO(ctx->ctx, rfn->dflts[0], ((struct lysp_node_leaf *)target)->dflt.str, ret, cleanup);
5648 ((struct lysp_node_leaf *)target)->dflt.mod = ctx->mod;
5649 break;
5650 case LYS_LEAFLIST:
5651 if (ctx->mod->version < LYS_VERSION_1_1) {
5652 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
5653 "Invalid refine of default in leaf-list - the default statement is allowed only in YANG 1.1 modules.");
5654 ret = LY_EVALID;
5655 goto cleanup;
5656 }
5657
5658 FREE_ARRAY(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, lysp_qname_free);
5659 ((struct lysp_node_leaflist *)target)->dflts = NULL;
5660 LY_ARRAY_FOR(rfn->dflts, u) {
5661 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, qname, ret, cleanup);
5662 DUP_STRING_GOTO(ctx->ctx, rfn->dflts[u], qname->str, ret, cleanup);
5663 qname->mod = ctx->mod;
5664 }
5665 break;
5666 case LYS_CHOICE:
5667 AMEND_CHECK_CARDINALITY(rfn->dflts, 1, "refine", "default");
5668
5669 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
5670 DUP_STRING_GOTO(ctx->ctx, rfn->dflts[0], ((struct lysp_node_choice *)target)->dflt.str, ret, cleanup);
5671 ((struct lysp_node_choice *)target)->dflt.mod = ctx->mod;
5672 break;
5673 default:
5674 AMEND_WRONG_NODETYPE("refine", "replace", "default");
5675 }
5676 }
5677
5678 /* description */
5679 if (rfn->dsc) {
5680 FREE_STRING(ctx->ctx, target->dsc);
5681 DUP_STRING_GOTO(ctx->ctx, rfn->dsc, target->dsc, ret, cleanup);
5682 }
5683
5684 /* reference */
5685 if (rfn->ref) {
5686 FREE_STRING(ctx->ctx, target->ref);
5687 DUP_STRING_GOTO(ctx->ctx, rfn->ref, target->ref, ret, cleanup);
5688 }
5689
5690 /* config */
5691 if (rfn->flags & LYS_CONFIG_MASK) {
5692 if (ctx->options & (LYSC_OPT_NOTIFICATION | LYSC_OPT_RPC_INPUT | LYSC_OPT_RPC_OUTPUT)) {
5693 LOGWRN(ctx->ctx, "Refining config inside %s has no effect (%s).",
5694 ctx->options & LYSC_OPT_NOTIFICATION ? "notification" : "RPC/action", ctx->path);
5695 } else {
5696 target->flags &= ~LYS_CONFIG_MASK;
5697 target->flags |= rfn->flags & LYS_CONFIG_MASK;
5698 }
5699 }
5700
5701 /* mandatory */
5702 if (rfn->flags & LYS_MAND_MASK) {
5703 switch (target->nodetype) {
5704 case LYS_LEAF:
5705 case LYS_CHOICE:
5706 case LYS_ANYDATA:
5707 case LYS_ANYXML:
5708 break;
5709 default:
5710 AMEND_WRONG_NODETYPE("refine", "replace", "mandatory");
5711 }
5712
5713 target->flags &= ~LYS_MAND_MASK;
5714 target->flags |= rfn->flags & LYS_MAND_MASK;
5715 }
5716
5717 /* presence */
5718 if (rfn->presence) {
5719 switch (target->nodetype) {
5720 case LYS_CONTAINER:
5721 break;
5722 default:
5723 AMEND_WRONG_NODETYPE("refine", "replace", "presence");
5724 }
5725
5726 FREE_STRING(ctx->ctx, ((struct lysp_node_container *)target)->presence);
5727 DUP_STRING_GOTO(ctx->ctx, rfn->presence, ((struct lysp_node_container *)target)->presence, ret, cleanup);
5728 }
5729
5730 /* must */
5731 if (rfn->musts) {
5732 switch (target->nodetype) {
5733 case LYS_CONTAINER:
5734 case LYS_LIST:
5735 case LYS_LEAF:
5736 case LYS_LEAFLIST:
5737 case LYS_ANYDATA:
5738 case LYS_ANYXML:
5739 musts = &((struct lysp_node_container *)target)->musts;
5740 break;
5741 default:
5742 AMEND_WRONG_NODETYPE("refine", "add", "must");
5743 }
5744
5745 LY_ARRAY_FOR(rfn->musts, u) {
5746 LY_ARRAY_NEW_GOTO(ctx->ctx, *musts, must, ret, cleanup);
5747 LY_CHECK_GOTO(ret = lysp_restr_dup(ctx->ctx, must, &rfn->musts[u]), cleanup);
5748 }
5749 }
5750
5751 /* min-elements */
5752 if (rfn->flags & LYS_SET_MIN) {
5753 switch (target->nodetype) {
5754 case LYS_LEAFLIST:
5755 num = &((struct lysp_node_leaflist *)target)->min;
5756 break;
5757 case LYS_LIST:
5758 num = &((struct lysp_node_list *)target)->min;
5759 break;
5760 default:
5761 AMEND_WRONG_NODETYPE("refine", "replace", "min-elements");
5762 }
5763
5764 *num = rfn->min;
5765 }
5766
5767 /* max-elements */
5768 if (rfn->flags & LYS_SET_MAX) {
5769 switch (target->nodetype) {
5770 case LYS_LEAFLIST:
5771 num = &((struct lysp_node_leaflist *)target)->max;
5772 break;
5773 case LYS_LIST:
5774 num = &((struct lysp_node_list *)target)->max;
5775 break;
5776 default:
5777 AMEND_WRONG_NODETYPE("refine", "replace", "max-elements");
5778 }
5779
5780 *num = rfn->max;
5781 }
5782
5783 /* if-feature */
5784 if (rfn->iffeatures) {
5785 switch (target->nodetype) {
5786 case LYS_LEAF:
5787 case LYS_LEAFLIST:
5788 case LYS_LIST:
5789 case LYS_CONTAINER:
5790 case LYS_CHOICE:
5791 case LYS_CASE:
5792 case LYS_ANYDATA:
5793 case LYS_ANYXML:
5794 break;
5795 default:
5796 AMEND_WRONG_NODETYPE("refine", "add", "if-feature");
5797 }
5798
5799 LY_ARRAY_FOR(rfn->iffeatures, u) {
5800 LY_ARRAY_NEW_GOTO(ctx->ctx, target->iffeatures, qname, ret, cleanup);
5801 DUP_STRING_GOTO(ctx->ctx, rfn->iffeatures[u].str, qname->str, ret, cleanup);
5802 qname->mod = ctx->mod;
5803 }
5804 }
5805
5806 /* extension */
5807 /* TODO refine extensions */
5808
5809cleanup:
5810 return ret;
5811}
5812
5813/**
5814 * @brief Apply deviate add.
5815 *
5816 * @param[in] ctx Compile context.
5817 * @param[in] d Deviate add to apply.
5818 * @param[in,out] target Deviation target.
5819 * @return LY_ERR value.
5820 */
5821static LY_ERR
5822lys_apply_deviate_add(struct lysc_ctx *ctx, struct lysp_deviate_add *d, struct lysp_node *target)
5823{
5824 LY_ERR ret = LY_SUCCESS;
5825 LY_ARRAY_COUNT_TYPE u;
5826 struct lysp_qname *qname;
5827 uint32_t *num;
5828 struct lysp_restr **musts, *must;
5829
5830#define DEV_CHECK_NONPRESENCE(TYPE, MEMBER, PROPERTY, VALUEMEMBER) \
5831 if (((TYPE)target)->MEMBER) { \
5832 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
5833 "Invalid deviation adding \"%s\" property which already exists (with value \"%s\").", \
5834 PROPERTY, ((TYPE)target)->VALUEMEMBER); \
5835 ret = LY_EVALID; \
5836 goto cleanup; \
5837 }
5838
5839 /* [units-stmt] */
5840 if (d->units) {
5841 switch (target->nodetype) {
5842 case LYS_LEAF:
5843 case LYS_LEAFLIST:
5844 break;
5845 default:
5846 AMEND_WRONG_NODETYPE("deviation", "add", "units");
5847 }
5848
5849 DEV_CHECK_NONPRESENCE(struct lysp_node_leaf *, units, "units", units);
5850 DUP_STRING_GOTO(ctx->ctx, d->units, ((struct lysp_node_leaf *)target)->units, ret, cleanup);
5851 }
5852
5853 /* *must-stmt */
5854 if (d->musts) {
5855 switch (target->nodetype) {
5856 case LYS_CONTAINER:
5857 case LYS_LIST:
5858 case LYS_LEAF:
5859 case LYS_LEAFLIST:
5860 case LYS_ANYDATA:
5861 case LYS_ANYXML:
5862 musts = &((struct lysp_node_container *)target)->musts;
5863 break;
5864 case LYS_NOTIF:
5865 musts = &((struct lysp_notif *)target)->musts;
5866 break;
5867 case LYS_INPUT:
5868 case LYS_OUTPUT:
5869 musts = &((struct lysp_action_inout *)target)->musts;
5870 break;
5871 default:
5872 AMEND_WRONG_NODETYPE("deviation", "add", "must");
5873 }
5874
5875 LY_ARRAY_FOR(d->musts, u) {
5876 LY_ARRAY_NEW_GOTO(ctx->ctx, *musts, must, ret, cleanup);
5877 LY_CHECK_GOTO(ret = lysp_restr_dup(ctx->ctx, must, &d->musts[u]), cleanup);
5878 }
5879 }
5880
5881 /* *unique-stmt */
5882 if (d->uniques) {
5883 switch (target->nodetype) {
5884 case LYS_LIST:
5885 break;
5886 default:
5887 AMEND_WRONG_NODETYPE("deviation", "add", "unique");
5888 }
5889
5890 LY_ARRAY_FOR(d->uniques, u) {
5891 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_list *)target)->uniques, qname, ret, cleanup);
5892 DUP_STRING_GOTO(ctx->ctx, d->uniques[u], qname->str, ret, cleanup);
5893 qname->mod = ctx->mod;
5894 }
5895 }
5896
5897 /* *default-stmt */
5898 if (d->dflts) {
5899 switch (target->nodetype) {
5900 case LYS_LEAF:
5901 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
5902 DEV_CHECK_NONPRESENCE(struct lysp_node_leaf *, dflt.str, "default", dflt.str);
5903
5904 DUP_STRING_GOTO(ctx->ctx, d->dflts[0], ((struct lysp_node_leaf *)target)->dflt.str, ret, cleanup);
5905 ((struct lysp_node_leaf *)target)->dflt.mod = ctx->mod;
5906 break;
5907 case LYS_LEAFLIST:
5908 LY_ARRAY_FOR(d->dflts, u) {
5909 LY_ARRAY_NEW_GOTO(ctx->ctx, ((struct lysp_node_leaflist *)target)->dflts, qname, ret, cleanup);
5910 DUP_STRING_GOTO(ctx->ctx, d->dflts[u], qname->str, ret, cleanup);
5911 qname->mod = ctx->mod;
5912 }
5913 break;
5914 case LYS_CHOICE:
5915 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
5916 DEV_CHECK_NONPRESENCE(struct lysp_node_choice *, dflt.str, "default", dflt.str);
5917
5918 DUP_STRING_GOTO(ctx->ctx, d->dflts[0], ((struct lysp_node_choice *)target)->dflt.str, ret, cleanup);
5919 ((struct lysp_node_choice *)target)->dflt.mod = ctx->mod;
5920 break;
5921 default:
5922 AMEND_WRONG_NODETYPE("deviation", "add", "default");
5923 }
5924 }
5925
5926 /* [config-stmt] */
5927 if (d->flags & LYS_CONFIG_MASK) {
5928 switch (target->nodetype) {
5929 case LYS_CONTAINER:
5930 case LYS_LEAF:
5931 case LYS_LEAFLIST:
5932 case LYS_LIST:
5933 case LYS_CHOICE:
5934 case LYS_ANYDATA:
5935 case LYS_ANYXML:
5936 break;
5937 default:
5938 AMEND_WRONG_NODETYPE("deviation", "add", "config");
5939 }
5940
5941 if (target->flags & LYS_CONFIG_MASK) {
5942 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
5943 "Invalid deviation adding \"config\" property which already exists (with value \"config %s\").",
5944 target->flags & LYS_CONFIG_W ? "true" : "false");
5945 ret = LY_EVALID;
5946 goto cleanup;
5947 }
5948
5949 target->flags |= d->flags & LYS_CONFIG_MASK;
5950 }
5951
5952 /* [mandatory-stmt] */
5953 if (d->flags & LYS_MAND_MASK) {
5954 switch (target->nodetype) {
5955 case LYS_LEAF:
5956 case LYS_CHOICE:
5957 case LYS_ANYDATA:
5958 case LYS_ANYXML:
5959 break;
5960 default:
5961 AMEND_WRONG_NODETYPE("deviation", "add", "mandatory");
5962 }
5963
5964 if (target->flags & LYS_MAND_MASK) {
5965 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
5966 "Invalid deviation adding \"mandatory\" property which already exists (with value \"mandatory %s\").",
5967 target->flags & LYS_MAND_TRUE ? "true" : "false");
5968 ret = LY_EVALID;
5969 goto cleanup;
5970 }
5971
5972 target->flags |= d->flags & LYS_MAND_MASK;
5973 }
5974
5975 /* [min-elements-stmt] */
5976 if (d->flags & LYS_SET_MIN) {
5977 switch (target->nodetype) {
5978 case LYS_LEAFLIST:
5979 num = &((struct lysp_node_leaflist *)target)->min;
5980 break;
5981 case LYS_LIST:
5982 num = &((struct lysp_node_list *)target)->min;
5983 break;
5984 default:
5985 AMEND_WRONG_NODETYPE("deviation", "add", "min-elements");
5986 }
5987
5988 if (target->flags & LYS_SET_MIN) {
5989 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
5990 "Invalid deviation adding \"min-elements\" property which already exists (with value \"%u\").", *num);
5991 ret = LY_EVALID;
5992 goto cleanup;
5993 }
5994
5995 *num = d->min;
5996 }
5997
5998 /* [max-elements-stmt] */
5999 if (d->flags & LYS_SET_MAX) {
6000 switch (target->nodetype) {
6001 case LYS_LEAFLIST:
6002 num = &((struct lysp_node_leaflist *)target)->max;
6003 break;
6004 case LYS_LIST:
6005 num = &((struct lysp_node_list *)target)->max;
6006 break;
6007 default:
6008 AMEND_WRONG_NODETYPE("deviation", "add", "max-elements");
6009 }
6010
6011 if (target->flags & LYS_SET_MAX) {
6012 if (*num) {
6013 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
6014 "Invalid deviation adding \"max-elements\" property which already exists (with value \"%u\").",
6015 *num);
6016 } else {
6017 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
6018 "Invalid deviation adding \"max-elements\" property which already exists (with value \"unbounded\").");
6019 }
6020 ret = LY_EVALID;
6021 goto cleanup;
6022 }
6023
6024 *num = d->max;
6025 }
6026
6027cleanup:
6028 return ret;
6029}
6030
6031/**
6032 * @brief Apply deviate delete.
6033 *
6034 * @param[in] ctx Compile context.
6035 * @param[in] d Deviate delete to apply.
6036 * @param[in,out] target Deviation target.
6037 * @return LY_ERR value.
6038 */
6039static LY_ERR
6040lys_apply_deviate_delete(struct lysc_ctx *ctx, struct lysp_deviate_del *d, struct lysp_node *target)
6041{
6042 LY_ERR ret = LY_SUCCESS;
6043 struct lysp_restr **musts;
6044 LY_ARRAY_COUNT_TYPE u, v;
6045 struct lysp_qname **uniques, **dflts;
6046
6047#define DEV_DEL_ARRAY(DEV_ARRAY, ORIG_ARRAY, DEV_MEMBER, ORIG_MEMBER, FREE_FUNC, PROPERTY) \
6048 LY_ARRAY_FOR(d->DEV_ARRAY, u) { \
6049 int found = 0; \
6050 LY_ARRAY_FOR(ORIG_ARRAY, v) { \
6051 if (!strcmp(d->DEV_ARRAY[u]DEV_MEMBER, (ORIG_ARRAY)[v]ORIG_MEMBER)) { \
6052 found = 1; \
6053 break; \
6054 } \
6055 } \
6056 if (!found) { \
6057 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
6058 "Invalid deviation deleting \"%s\" property \"%s\" which does not match any of the target's property values.", \
6059 PROPERTY, d->DEV_ARRAY[u]DEV_MEMBER); \
6060 ret = LY_EVALID; \
6061 goto cleanup; \
6062 } \
6063 LY_ARRAY_DECREMENT(ORIG_ARRAY); \
6064 FREE_FUNC(ctx->ctx, &(ORIG_ARRAY)[v]); \
6065 memmove(&(ORIG_ARRAY)[v], &(ORIG_ARRAY)[v + 1], (LY_ARRAY_COUNT(ORIG_ARRAY) - v) * sizeof *(ORIG_ARRAY)); \
6066 } \
6067 if (!LY_ARRAY_COUNT(ORIG_ARRAY)) { \
6068 LY_ARRAY_FREE(ORIG_ARRAY); \
6069 ORIG_ARRAY = NULL; \
6070 }
6071
6072#define DEV_CHECK_PRESENCE_VALUE(TYPE, MEMBER, DEVTYPE, PROPERTY, VALUE) \
6073 if (!((TYPE)target)->MEMBER) { \
6074 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT, DEVTYPE, PROPERTY, VALUE); \
6075 ret = LY_EVALID; \
6076 goto cleanup; \
6077 } else if (strcmp(((TYPE)target)->MEMBER, VALUE)) { \
6078 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE, \
6079 "Invalid deviation deleting \"%s\" property \"%s\" which does not match the target's property value \"%s\".", \
6080 PROPERTY, VALUE, ((TYPE)target)->MEMBER); \
6081 ret = LY_EVALID; \
6082 goto cleanup; \
6083 }
6084
6085 /* [units-stmt] */
6086 if (d->units) {
6087 switch (target->nodetype) {
6088 case LYS_LEAF:
6089 case LYS_LEAFLIST:
6090 break;
6091 default:
6092 AMEND_WRONG_NODETYPE("deviation", "delete", "units");
6093 }
6094
6095 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, units, "deleting", "units", d->units);
6096 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->units);
6097 ((struct lysp_node_leaf *)target)->units = NULL;
6098 }
6099
6100 /* *must-stmt */
6101 if (d->musts) {
6102 switch (target->nodetype) {
6103 case LYS_CONTAINER:
6104 case LYS_LIST:
6105 case LYS_LEAF:
6106 case LYS_LEAFLIST:
6107 case LYS_ANYDATA:
6108 case LYS_ANYXML:
6109 musts = &((struct lysp_node_container *)target)->musts;
6110 break;
6111 case LYS_NOTIF:
6112 musts = &((struct lysp_notif *)target)->musts;
6113 break;
6114 case LYS_INPUT:
6115 case LYS_OUTPUT:
6116 musts = &((struct lysp_action_inout *)target)->musts;
6117 break;
6118 default:
6119 AMEND_WRONG_NODETYPE("deviation", "delete", "must");
6120 }
6121
6122 DEV_DEL_ARRAY(musts, *musts, .arg.str, .arg.str, lysp_restr_free, "must");
6123 }
6124
6125 /* *unique-stmt */
6126 if (d->uniques) {
6127 switch (target->nodetype) {
6128 case LYS_LIST:
6129 break;
6130 default:
6131 AMEND_WRONG_NODETYPE("deviation", "delete", "unique");
6132 }
6133
6134 uniques = &((struct lysp_node_list *)target)->uniques;
6135 DEV_DEL_ARRAY(uniques, *uniques, , .str, lysp_qname_free, "unique");
6136 }
6137
6138 /* *default-stmt */
6139 if (d->dflts) {
6140 switch (target->nodetype) {
6141 case LYS_LEAF:
6142 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
6143 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_leaf *, dflt.str, "deleting", "default", d->dflts[0]);
6144
6145 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
6146 ((struct lysp_node_leaf *)target)->dflt.str = NULL;
6147 break;
6148 case LYS_LEAFLIST:
6149 dflts = &((struct lysp_node_leaflist *)target)->dflts;
6150 DEV_DEL_ARRAY(dflts, *dflts, , .str, lysp_qname_free, "default");
6151 break;
6152 case LYS_CHOICE:
6153 AMEND_CHECK_CARDINALITY(d->dflts, 1, "deviation", "default");
6154 DEV_CHECK_PRESENCE_VALUE(struct lysp_node_choice *, dflt.str, "deleting", "default", d->dflts[0]);
6155
6156 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
6157 ((struct lysp_node_choice *)target)->dflt.str = NULL;
6158 break;
6159 default:
6160 AMEND_WRONG_NODETYPE("deviation", "delete", "default");
6161 }
6162 }
6163
6164cleanup:
6165 return ret;
6166}
6167
6168/**
6169 * @brief Apply deviate replace.
6170 *
6171 * @param[in] ctx Compile context.
6172 * @param[in] d Deviate replace to apply.
6173 * @param[in,out] target Deviation target.
6174 * @return LY_ERR value.
6175 */
6176static LY_ERR
6177lys_apply_deviate_replace(struct lysc_ctx *ctx, struct lysp_deviate_rpl *d, struct lysp_node *target)
6178{
6179 LY_ERR ret = LY_SUCCESS;
6180 uint32_t *num;
6181
6182#define DEV_CHECK_PRESENCE(TYPE, MEMBER, DEVTYPE, PROPERTY, VALUE) \
6183 if (!((TYPE)target)->MEMBER) { \
6184 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT, DEVTYPE, PROPERTY, VALUE); \
6185 ret = LY_EVALID; \
6186 goto cleanup; \
6187 }
6188
6189 /* [type-stmt] */
6190 if (d->type) {
6191 switch (target->nodetype) {
6192 case LYS_LEAF:
6193 case LYS_LEAFLIST:
6194 break;
6195 default:
6196 AMEND_WRONG_NODETYPE("deviation", "replace", "type");
6197 }
6198
6199 lysp_type_free(ctx->ctx, &((struct lysp_node_leaf *)target)->type);
6200 lysp_type_dup(ctx->ctx, &((struct lysp_node_leaf *)target)->type, d->type);
6201 }
6202
6203 /* [units-stmt] */
6204 if (d->units) {
6205 switch (target->nodetype) {
6206 case LYS_LEAF:
6207 case LYS_LEAFLIST:
6208 break;
6209 default:
6210 AMEND_WRONG_NODETYPE("deviation", "replace", "units");
6211 }
6212
6213 DEV_CHECK_PRESENCE(struct lysp_node_leaf *, units, "replacing", "units", d->units);
6214 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->units);
6215 DUP_STRING_GOTO(ctx->ctx, d->units, ((struct lysp_node_leaf *)target)->units, ret, cleanup);
6216 }
6217
6218 /* [default-stmt] */
6219 if (d->dflt) {
6220 switch (target->nodetype) {
6221 case LYS_LEAF:
6222 DEV_CHECK_PRESENCE(struct lysp_node_leaf *, dflt.str, "replacing", "default", d->dflt);
6223
6224 FREE_STRING(ctx->ctx, ((struct lysp_node_leaf *)target)->dflt.str);
6225 DUP_STRING_GOTO(ctx->ctx, d->dflt, ((struct lysp_node_leaf *)target)->dflt.str, ret, cleanup);
6226 ((struct lysp_node_leaf *)target)->dflt.mod = ctx->mod;
6227 break;
6228 case LYS_CHOICE:
6229 DEV_CHECK_PRESENCE(struct lysp_node_choice *, dflt.str, "replacing", "default", d->dflt);
6230
6231 FREE_STRING(ctx->ctx, ((struct lysp_node_choice *)target)->dflt.str);
6232 DUP_STRING_GOTO(ctx->ctx, d->dflt, ((struct lysp_node_choice *)target)->dflt.str, ret, cleanup);
6233 ((struct lysp_node_choice *)target)->dflt.mod = ctx->mod;
6234 break;
6235 default:
6236 AMEND_WRONG_NODETYPE("deviation", "replace", "default");
6237 }
6238 }
6239
6240 /* [config-stmt] */
6241 if (d->flags & LYS_CONFIG_MASK) {
6242 switch (target->nodetype) {
6243 case LYS_CONTAINER:
6244 case LYS_LEAF:
6245 case LYS_LEAFLIST:
6246 case LYS_LIST:
6247 case LYS_CHOICE:
6248 case LYS_ANYDATA:
6249 case LYS_ANYXML:
6250 break;
6251 default:
6252 AMEND_WRONG_NODETYPE("deviation", "replace", "config");
6253 }
6254
6255 if (!(target->flags & LYS_CONFIG_MASK)) {
6256 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT,
6257 "replacing", "config", d->flags & LYS_CONFIG_W ? "config true" : "config false");
6258 ret = LY_EVALID;
6259 goto cleanup;
6260 }
6261
6262 target->flags &= ~LYS_CONFIG_MASK;
6263 target->flags |= d->flags & LYS_CONFIG_MASK;
6264 }
6265
6266 /* [mandatory-stmt] */
6267 if (d->flags & LYS_MAND_MASK) {
6268 switch (target->nodetype) {
6269 case LYS_LEAF:
6270 case LYS_CHOICE:
6271 case LYS_ANYDATA:
6272 case LYS_ANYXML:
6273 break;
6274 default:
6275 AMEND_WRONG_NODETYPE("deviation", "replace", "mandatory");
6276 }
6277
6278 if (!(target->flags & LYS_MAND_MASK)) {
6279 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DEV_NOT_PRESENT,
6280 "replacing", "mandatory", d->flags & LYS_MAND_TRUE ? "mandatory true" : "mandatory false");
6281 ret = LY_EVALID;
6282 goto cleanup;
6283 }
6284
6285 target->flags &= ~LYS_MAND_MASK;
6286 target->flags |= d->flags & LYS_MAND_MASK;
6287 }
6288
6289 /* [min-elements-stmt] */
6290 if (d->flags & LYS_SET_MIN) {
6291 switch (target->nodetype) {
6292 case LYS_LEAFLIST:
6293 num = &((struct lysp_node_leaflist *)target)->min;
6294 break;
6295 case LYS_LIST:
6296 num = &((struct lysp_node_list *)target)->min;
6297 break;
6298 default:
6299 AMEND_WRONG_NODETYPE("deviation", "replace", "min-elements");
6300 }
6301
6302 if (!(target->flags & LYS_SET_MIN)) {
6303 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
6304 "Invalid deviation replacing \"min-elements\" property which is not present.");
6305 ret = LY_EVALID;
6306 goto cleanup;
6307 }
6308
6309 *num = d->min;
6310 }
6311
6312 /* [max-elements-stmt] */
6313 if (d->flags & LYS_SET_MAX) {
6314 switch (target->nodetype) {
6315 case LYS_LEAFLIST:
6316 num = &((struct lysp_node_leaflist *)target)->max;
6317 break;
6318 case LYS_LIST:
6319 num = &((struct lysp_node_list *)target)->max;
6320 break;
6321 default:
6322 AMEND_WRONG_NODETYPE("deviation", "replace", "max-elements");
6323 }
6324
6325 if (!(target->flags & LYS_SET_MAX)) {
6326 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_REFERENCE,
6327 "Invalid deviation replacing \"max-elements\" property which is not present.");
6328 ret = LY_EVALID;
6329 goto cleanup;
6330 }
6331
6332 *num = d->max;
6333 }
6334
6335cleanup:
6336 return ret;
6337}
6338
6339/**
6340 * @brief Get module of a single nodeid node name test.
6341 *
6342 * @param[in] ctx libyang context.
6343 * @param[in] nametest Nametest with an optional prefix.
6344 * @param[in] nametest_len Length of @p nametest.
6345 * @param[in] local_mod Module to return in case of no prefix.
6346 * @param[out] name Optional pointer to the name test without the prefix.
6347 * @param[out] name_len Length of @p name.
6348 * @return Resolved module.
6349 */
6350static const struct lys_module *
6351lys_schema_node_get_module(const struct ly_ctx *ctx, const char *nametest, size_t nametest_len,
6352 const struct lys_module *local_mod, const char **name, size_t *name_len)
6353{
6354 const struct lys_module *target_mod;
6355 const char *ptr;
6356
6357 ptr = ly_strnchr(nametest, ':', nametest_len);
6358 if (ptr) {
6359 target_mod = ly_resolve_prefix(ctx, nametest, ptr - nametest, LY_PREF_SCHEMA, (void *)local_mod);
6360 if (!target_mod) {
6361 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
6362 "Invalid absolute-schema-nodeid nametest \"%.*s\" - prefix \"%.*s\" not defined in module \"%s\".",
6363 nametest_len, nametest, ptr - nametest, nametest, local_mod->name);
6364 return NULL;
6365 }
6366
6367 if (name) {
6368 *name = ptr + 1;
6369 *name_len = nametest_len - ((ptr - nametest) + 1);
6370 }
6371 } else {
6372 target_mod = local_mod;
6373 if (name) {
6374 *name = nametest;
6375 *name_len = nametest_len;
6376 }
6377 }
6378
6379 return target_mod;
6380}
6381
6382/**
6383 * @brief Check whether a parsed node matches a single schema nodeid name test.
6384 *
6385 * @param[in] pnode Parsed node to consider.
6386 * @param[in] pnode_mod Compiled @p pnode to-be module.
6387 * @param[in] mod Expected module.
6388 * @param[in] name Expected name.
6389 * @param[in] name_len Length of @p name.
6390 * @return Whether it is a match or not.
6391 */
6392static ly_bool
6393lysp_schema_nodeid_match_pnode(const struct lysp_node *pnode, const struct lys_module *pnode_mod,
6394 const struct lys_module *mod, const char *name, size_t name_len)
6395{
6396 const char *pname;
6397
6398 /* compare with the module of the node */
6399 if (pnode_mod != mod) {
6400 return 0;
6401 }
6402
6403 /* compare names */
6404 if (pnode->nodetype & (LYS_ACTION | LYS_RPC)) {
6405 pname = ((struct lysp_action *)pnode)->name;
6406 } else if (pnode->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
6407 pname = (pnode->nodetype & LYS_INPUT) ? "input" : "output";
6408 } else {
6409 pname = pnode->name;
6410 }
6411 if (ly_strncmp(pname, name, name_len)) {
6412 return 0;
6413 }
6414
6415 return 1;
6416}
6417
6418/**
6419 * @brief Check whether a compiled node matches a single schema nodeid name test.
6420 *
6421 * @param[in,out] node Compiled node to consider. On a match it is moved to its parent.
6422 * @param[in] mod Expected module.
6423 * @param[in] name Expected name.
6424 * @param[in] name_len Length of @p name.
6425 * @return Whether it is a match or not.
6426 */
6427static ly_bool
6428lysp_schema_nodeid_match_node(const struct lysc_node **node, const struct lys_module *mod, const char *name,
6429 size_t name_len)
6430{
6431 const struct lys_module *node_mod;
6432 const char *node_name;
6433
6434 /* compare with the module of the node */
6435 if ((*node)->nodetype == LYS_INPUT) {
6436 node_mod = ((struct lysc_node *)(((char *)*node) - offsetof(struct lysc_action, input)))->module;
6437 } else if ((*node)->nodetype == LYS_OUTPUT) {
6438 node_mod = ((struct lysc_node *)(((char *)*node) - offsetof(struct lysc_action, output)))->module;
6439 } else {
6440 node_mod = (*node)->module;
6441 }
6442 if (node_mod != mod) {
6443 return 0;
6444 }
6445
6446 /* compare names */
6447 if ((*node)->nodetype == LYS_INPUT) {
6448 node_name = "input";
6449 } else if ((*node)->nodetype == LYS_OUTPUT) {
6450 node_name = "output";
6451 } else {
6452 node_name = (*node)->name;
6453 }
6454 if (ly_strncmp(node_name, name, name_len)) {
6455 return 0;
6456 }
6457
6458 if ((*node)->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
6459 /* move up from input/output */
6460 if ((*node)->nodetype == LYS_INPUT) {
6461 (*node) = (struct lysc_node *)(((char *)*node) - offsetof(struct lysc_action, input));
6462 } else {
6463 (*node) = (struct lysc_node *)(((char *)*node) - offsetof(struct lysc_action, output));
6464 }
6465 } else if ((*node)->parent && ((*node)->parent->nodetype & (LYS_RPC | LYS_ACTION))) {
6466 /* move to the input/output */
6467 if ((*node)->flags & LYS_CONFIG_W) {
6468 *node = (struct lysc_node *)&((struct lysc_action *)(*node)->parent)->input;
6469 } else {
6470 *node = (struct lysc_node *)&((struct lysc_action *)(*node)->parent)->output;
6471 }
6472 } else {
6473 /* move to next parent */
6474 *node = (*node)->parent;
6475 }
6476
6477 return 1;
6478}
6479
6480/**
6481 * @brief Check whether a node matches specific schema nodeid.
6482 *
6483 * @param[in] exp Parsed nodeid to match.
6484 * @param[in] exp_mod Module to use for nodes in @p exp without a prefix.
6485 * @param[in] ctx_node Initial context node that should match, only for descendant paths.
6486 * @param[in] parent First compiled parent to consider. If @p pnode is NULL, it is condered the node to be matched.
6487 * @param[in] pnode Parsed node to be matched. May be NULL if the target node was already compiled.
6488 * @param[in] pnode_mod Compiled @p pnode to-be module.
6489 * @return Whether it is a match or not.
6490 */
6491static ly_bool
6492lysp_schema_nodeid_match(const struct lyxp_expr *exp, const struct lys_module *exp_mod, const struct lysc_node *ctx_node,
6493 const struct lysc_node *parent, const struct lysp_node *pnode, const struct lys_module *pnode_mod)
6494{
6495 uint32_t i;
6496 const struct lys_module *mod;
6497 const char *name;
6498 size_t name_len;
6499
6500 /* compare last node in the node ID */
6501 i = exp->used - 1;
6502
6503 /* get exp node ID module */
6504 mod = lys_schema_node_get_module(exp_mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_mod, &name, &name_len);
6505 assert(mod);
6506
6507 if (pnode) {
6508 /* compare on the last parsed-only node */
6509 if (!lysp_schema_nodeid_match_pnode(pnode, pnode_mod, mod, name, name_len)) {
6510 return 0;
6511 }
6512 } else {
6513 /* using parent directly */
6514 if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
6515 return 0;
6516 }
6517 }
6518
6519 /* now compare all the compiled parents */
6520 while (i > 1) {
6521 i -= 2;
6522 assert(exp->tokens[i] == LYXP_TOKEN_NAMETEST);
6523
6524 if (!parent) {
6525 /* no more parents but path continues */
6526 return 0;
6527 }
6528
6529 /* get exp node ID module */
6530 mod = lys_schema_node_get_module(exp_mod->ctx, exp->expr + exp->tok_pos[i], exp->tok_len[i], exp_mod, &name,
6531 &name_len);
6532 assert(mod);
6533
6534 /* compare with the parent */
6535 if (!lysp_schema_nodeid_match_node(&parent, mod, name, name_len)) {
6536 return 0;
6537 }
6538 }
6539
6540 if (ctx_node && (ctx_node != parent)) {
6541 /* descendant path has not finished in the context node */
6542 return 0;
6543 } else if (!ctx_node && parent) {
6544 /* some parent was not matched */
6545 return 0;
6546 }
6547
6548 return 1;
6549}
6550
6551static void
6552lysc_augment_free(const struct ly_ctx *ctx, struct lysc_augment *aug)
6553{
6554 if (aug) {
6555 lyxp_expr_free(ctx, aug->nodeid);
6556
6557 free(aug);
6558 }
6559}
6560
6561static void
6562lysc_deviation_free(const struct ly_ctx *ctx, struct lysc_deviation *dev)
6563{
6564 if (dev) {
6565 lyxp_expr_free(ctx, dev->nodeid);
6566 LY_ARRAY_FREE(dev->devs);
6567 LY_ARRAY_FREE(dev->dev_mods);
6568
6569 free(dev);
6570 }
6571}
6572
6573static void
6574lysc_refine_free(const struct ly_ctx *ctx, struct lysc_refine *rfn)
6575{
6576 if (rfn) {
6577 lyxp_expr_free(ctx, rfn->nodeid);
6578 LY_ARRAY_FREE(rfn->rfns);
6579
6580 free(rfn);
6581 }
6582}
6583
6584static void
6585lysp_dev_node_free(const struct ly_ctx *ctx, struct lysp_node *dev_pnode)
6586{
6587 if (!dev_pnode) {
6588 return;
6589 }
6590
6591 switch (dev_pnode->nodetype) {
6592 case LYS_CONTAINER:
6593 ((struct lysp_node_container *)dev_pnode)->child = NULL;
6594 break;
6595 case LYS_LIST:
6596 ((struct lysp_node_list *)dev_pnode)->child = NULL;
6597 break;
6598 case LYS_CHOICE:
6599 ((struct lysp_node_choice *)dev_pnode)->child = NULL;
6600 break;
6601 case LYS_CASE:
6602 ((struct lysp_node_case *)dev_pnode)->child = NULL;
6603 break;
6604 case LYS_LEAF:
6605 case LYS_LEAFLIST:
6606 case LYS_ANYXML:
6607 case LYS_ANYDATA:
6608 /* no children */
6609 break;
6610 case LYS_NOTIF:
6611 ((struct lysp_notif *)dev_pnode)->data = NULL;
6612 lysp_notif_free((struct ly_ctx *)ctx, (struct lysp_notif *)dev_pnode);
6613 free(dev_pnode);
6614 return;
6615 case LYS_RPC:
6616 case LYS_ACTION:
6617 ((struct lysp_action *)dev_pnode)->input.data = NULL;
6618 ((struct lysp_action *)dev_pnode)->output.data = NULL;
6619 lysp_action_free((struct ly_ctx *)ctx, (struct lysp_action *)dev_pnode);
6620 free(dev_pnode);
6621 return;
6622 case LYS_INPUT:
6623 case LYS_OUTPUT:
6624 ((struct lysp_action_inout *)dev_pnode)->data = NULL;
6625 lysp_action_inout_free((struct ly_ctx *)ctx, (struct lysp_action_inout *)dev_pnode);
6626 free(dev_pnode);
6627 return;
6628 default:
6629 LOGINT(ctx);
6630 return;
6631 }
6632
6633 lysp_node_free((struct ly_ctx *)ctx, dev_pnode);
6634}
6635
6636/**
6637 * @brief Compile and apply any precompiled deviations and refines targetting a node.
6638 *
6639 * @param[in] ctx Compile context.
6640 * @param[in] pnode Parsed node to consider.
6641 * @param[in] parent First compiled parent of @p pnode.
6642 * @param[out] dev_pnode Copy of parsed node @p pnode with deviations and refines, if any. NULL if there are none.
6643 * @param[out] no_supported Whether a not-supported deviation is defined for the node.
6644 * @return LY_ERR value.
6645 */
6646static LY_ERR
6647lys_compile_node_deviations_refines(struct lysc_ctx *ctx, const struct lysp_node *pnode, const struct lysc_node *parent,
6648 struct lysp_node **dev_pnode, ly_bool *not_supported)
6649{
6650 LY_ERR ret = LY_SUCCESS;
6651 uint32_t i;
6652 LY_ARRAY_COUNT_TYPE u;
6653 struct lys_module *orig_mod = ctx->mod, *orig_mod_def = ctx->mod_def;
6654 char orig_path[LYSC_CTX_BUFSIZE];
6655 struct lysc_refine *rfn;
6656 struct lysc_deviation *dev;
6657 struct lysp_deviation *dev_p;
6658 struct lysp_deviate *d;
6659
6660 *dev_pnode = NULL;
6661 *not_supported = 0;
6662
6663 for (i = 0; i < ctx->uses_rfns.count; ++i) {
6664 rfn = ctx->uses_rfns.objs[i];
6665
6666 if (!lysp_schema_nodeid_match(rfn->nodeid, ctx->mod, rfn->nodeid_ctx_node, parent, pnode, ctx->mod)) {
6667 /* not our target node */
6668 continue;
6669 }
6670
6671 if (!*dev_pnode) {
6672 /* first refine on this node, create a copy first */
6673 LY_CHECK_GOTO(ret = lysp_dup_single(ctx->ctx, pnode, 1, dev_pnode), cleanup);
6674 }
6675
6676 /* apply all the refines by changing (the copy of) the parsed node */
6677 LY_ARRAY_FOR(rfn->rfns, u) {
6678 /* apply refine, keep the current path and add to it */
6679 lysc_update_path(ctx, NULL, "{refine}");
6680 lysc_update_path(ctx, NULL, rfn->rfns[u]->nodeid);
6681 ret = lys_apply_refine(ctx, rfn->rfns[u], *dev_pnode);
6682 lysc_update_path(ctx, NULL, NULL);
6683 lysc_update_path(ctx, NULL, NULL);
6684 LY_CHECK_GOTO(ret, cleanup);
6685 }
6686
6687 /* refine was applied, remove it */
6688 lysc_refine_free(ctx->ctx, rfn);
6689 ly_set_rm_index(&ctx->uses_rfns, i, NULL);
6690
6691 /* all the refines for one target node are in one structure, we are done */
6692 break;
6693 }
6694
6695 for (i = 0; i < ctx->devs.count; ++i) {
6696 dev = ctx->devs.objs[i];
6697
6698 if (!lysp_schema_nodeid_match(dev->nodeid, dev->nodeid_mod, NULL, parent, pnode, ctx->mod_def)) {
6699 /* not our target node */
6700 continue;
6701 }
6702
6703 if (dev->not_supported) {
6704 /* it is not supported, no more deviations */
6705 *not_supported = 1;
6706 goto dev_applied;
6707 }
6708
6709 if (!*dev_pnode) {
6710 /* first deviation on this node, create a copy first */
6711 LY_CHECK_GOTO(ret = lysp_dup_single(ctx->ctx, pnode, 1, dev_pnode), cleanup);
6712 }
6713
6714 /* apply all the deviates by changing (the copy of) the parsed node */
6715 LY_ARRAY_FOR(dev->devs, u) {
6716 dev_p = dev->devs[u];
6717 LY_LIST_FOR(dev_p->deviates, d) {
6718 /* generate correct path */
6719 strcpy(orig_path, ctx->path);
6720 ctx->path_len = 1;
6721 ctx->mod = (struct lys_module *)dev->dev_mods[u];
6722 ctx->mod_def = (struct lys_module *)dev->dev_mods[u];
6723 lysc_update_path(ctx, NULL, "{deviation}");
6724 lysc_update_path(ctx, NULL, dev_p->nodeid);
6725
6726 switch (d->mod) {
6727 case LYS_DEV_ADD:
6728 ret = lys_apply_deviate_add(ctx, (struct lysp_deviate_add *)d, *dev_pnode);
6729 break;
6730 case LYS_DEV_DELETE:
6731 ret = lys_apply_deviate_delete(ctx, (struct lysp_deviate_del *)d, *dev_pnode);
6732 break;
6733 case LYS_DEV_REPLACE:
6734 ret = lys_apply_deviate_replace(ctx, (struct lysp_deviate_rpl *)d, *dev_pnode);
6735 break;
6736 default:
6737 LOGINT(ctx->ctx);
6738 ret = LY_EINT;
6739 }
6740
6741 /* restore previous path */
6742 strcpy(ctx->path, orig_path);
6743 ctx->path_len = strlen(ctx->path);
6744 ctx->mod = orig_mod;
6745 ctx->mod_def = orig_mod_def;
6746
6747 LY_CHECK_GOTO(ret, cleanup);
6748 }
6749 }
6750
6751dev_applied:
6752 /* deviation was applied, remove it */
6753 lysc_deviation_free(ctx->ctx, dev);
6754 ly_set_rm_index(&ctx->devs, i, NULL);
6755
6756 /* all the deviations for one target node are in one structure, we are done */
6757 break;
6758 }
6759
6760cleanup:
6761 if (ret) {
6762 lysp_dev_node_free(ctx->ctx, *dev_pnode);
6763 *dev_pnode = NULL;
6764 *not_supported = 0;
6765 }
6766 return ret;
6767}
6768
6769/**
6770 * @brief Compile and apply any precompiled top-level or uses augments targetting a node.
6771 *
6772 * @param[in] ctx Compile context.
6773 * @param[in] node Compiled node to consider.
6774 * @return LY_ERR value.
6775 */
6776static LY_ERR
6777lys_compile_node_augments(struct lysc_ctx *ctx, struct lysc_node *node)
6778{
6779 LY_ERR ret = LY_SUCCESS;
6780 struct lys_module *orig_mod = ctx->mod, *orig_mod_def = ctx->mod_def;
6781 uint32_t i;
6782 char orig_path[LYSC_CTX_BUFSIZE];
6783 struct lysc_augment *aug;
6784
6785 /* uses augments */
6786 for (i = 0; i < ctx->uses_augs.count; ) {
6787 aug = ctx->uses_augs.objs[i];
6788
6789 if (!lysp_schema_nodeid_match(aug->nodeid, ctx->mod, aug->nodeid_ctx_node, node, NULL, NULL)) {
6790 /* not our target node */
6791 ++i;
6792 continue;
6793 }
6794
6795 /* apply augment, keep the current path and add to it */
6796 lysc_update_path(ctx, NULL, "{augment}");
6797 lysc_update_path(ctx, NULL, aug->aug_p->nodeid);
6798 ret = lys_compile_augment(ctx, aug->aug_p, node);
6799 lysc_update_path(ctx, NULL, NULL);
6800 lysc_update_path(ctx, NULL, NULL);
6801 LY_CHECK_GOTO(ret, cleanup);
6802
6803 /* augment was applied, remove it (index may have changed because other augments could have been applied) */
Michal Vasko7f45cf22020-10-01 12:49:44 +02006804 ly_set_rm(&ctx->uses_augs, aug, NULL);
Michal Vaskoaf702452020-10-02 09:02:55 +02006805 lysc_augment_free(ctx->ctx, aug);
Michal Vasko7f45cf22020-10-01 12:49:44 +02006806 }
6807
6808 /* top-level augments */
6809 for (i = 0; i < ctx->augs.count; ) {
6810 aug = ctx->augs.objs[i];
6811
6812 if (!lysp_schema_nodeid_match(aug->nodeid, aug->nodeid_mod, NULL, node, NULL, NULL)) {
6813 /* not our target node */
6814 ++i;
6815 continue;
6816 }
6817
6818 /* apply augment, use the path and modules from the augment */
6819 strcpy(orig_path, ctx->path);
6820 ctx->path_len = 1;
6821 lysc_update_path(ctx, NULL, "{augment}");
6822 lysc_update_path(ctx, NULL, aug->aug_p->nodeid);
6823 ctx->mod = (struct lys_module *)aug->nodeid_mod;
6824 ctx->mod_def = (struct lys_module *)aug->nodeid_mod;
6825 ret = lys_compile_augment(ctx, aug->aug_p, node);
6826 strcpy(ctx->path, orig_path);
6827 ctx->path_len = strlen(ctx->path);
6828 LY_CHECK_GOTO(ret, cleanup);
6829
6830 /* augment was applied, remove it */
Michal Vasko7f45cf22020-10-01 12:49:44 +02006831 ly_set_rm(&ctx->augs, aug, NULL);
Michal Vaskoaf702452020-10-02 09:02:55 +02006832 lysc_augment_free(ctx->ctx, aug);
Michal Vasko7f45cf22020-10-01 12:49:44 +02006833 }
6834
6835cleanup:
6836 ctx->mod = orig_mod;
6837 ctx->mod_def = orig_mod_def;
6838 return ret;
6839}
6840
6841/**
6842 * @brief Prepare a top-level augment to be applied during data nodes compilation.
6843 *
6844 * @param[in] ctx Compile context.
6845 * @param[in] aug_p Parsed augment to be applied.
6846 * @param[in] mod_def Local module for @p aug_p.
6847 * @return LY_ERR value.
6848 */
6849static LY_ERR
6850lys_precompile_own_augment(struct lysc_ctx *ctx, struct lysp_augment *aug_p, const struct lys_module *mod_def)
6851{
6852 LY_ERR ret = LY_SUCCESS;
6853 struct lyxp_expr *exp = NULL;
6854 struct lysc_augment *aug;
6855 const struct lys_module *mod;
6856
6857 /* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
6858 ret = lyxp_expr_parse(ctx->ctx, aug_p->nodeid, strlen(aug_p->nodeid), 0, &exp);
6859 LY_CHECK_GOTO(ret, cleanup);
6860
6861 mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], mod_def, NULL, NULL);
6862 LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
6863 if (mod != ctx->mod) {
6864 /* augment for another module, ignore */
6865 goto cleanup;
6866 }
6867
6868 /* allocate new compiled augment and store it in the set */
6869 aug = calloc(1, sizeof *aug);
6870 LY_CHECK_ERR_GOTO(!aug, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
6871 LY_CHECK_GOTO(ret = ly_set_add(&ctx->augs, aug, LY_SET_OPT_USEASLIST, NULL), cleanup);
6872
6873 aug->nodeid = exp;
6874 exp = NULL;
6875 aug->nodeid_mod = mod_def;
6876 aug->aug_p = aug_p;
6877
6878cleanup:
6879 lyxp_expr_free(ctx->ctx, exp);
6880 return ret;
6881}
6882
6883/**
6884 * @brief Prepare all top-level augments for the current module to be applied during data nodes compilation.
6885 *
6886 * @param[in] ctx Compile context.
6887 * @return LY_ERR value.
6888 */
6889static LY_ERR
6890lys_precompile_own_augments(struct lysc_ctx *ctx)
6891{
6892 LY_ARRAY_COUNT_TYPE u, v, w;
6893 const struct lys_module *aug_mod;
6894
6895 LY_ARRAY_FOR(ctx->mod->augmented_by, u) {
6896 aug_mod = ctx->mod->augmented_by[u];
6897
6898 /* collect all module augments */
6899 LY_ARRAY_FOR(aug_mod->parsed->augments, v) {
6900 LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->augments[v], aug_mod));
6901 }
6902
6903 /* collect all submodules augments */
6904 LY_ARRAY_FOR(aug_mod->parsed->includes, v) {
6905 LY_ARRAY_FOR(aug_mod->parsed->includes[v].submodule->augments, w) {
6906 LY_CHECK_RET(lys_precompile_own_augment(ctx, &aug_mod->parsed->includes[v].submodule->augments[w], aug_mod));
6907 }
6908 }
6909 }
6910
6911 return LY_SUCCESS;
6912}
6913
6914/**
6915 * @brief Prepare a deviation to be applied during data nodes compilation.
6916 *
6917 * @param[in] ctx Compile context.
6918 * @param[in] dev_p Parsed deviation to be applied.
6919 * @param[in] mod_def Local module for @p dev_p.
6920 * @return LY_ERR value.
6921 */
6922static LY_ERR
6923lys_precompile_own_deviation(struct lysc_ctx *ctx, struct lysp_deviation *dev_p, const struct lys_module *mod_def)
6924{
6925 LY_ERR ret = LY_SUCCESS;
6926 struct lysc_deviation *dev = NULL;
6927 struct lyxp_expr *exp = NULL;
6928 struct lysp_deviation **new_dev;
6929 const struct lys_module *mod, **new_dev_mod;
6930 uint32_t i;
6931
6932 /* parse its target, it was already parsed and fully checked (except for the existence of the nodes) */
6933 ret = lyxp_expr_parse(ctx->ctx, dev_p->nodeid, strlen(dev_p->nodeid), 0, &exp);
6934 LY_CHECK_GOTO(ret, cleanup);
6935
6936 mod = lys_schema_node_get_module(ctx->ctx, exp->expr + exp->tok_pos[1], exp->tok_len[1], mod_def, NULL, NULL);
6937 LY_CHECK_ERR_GOTO(!mod, LOGINT(ctx->ctx); ret = LY_EINT, cleanup);
6938 if (mod != ctx->mod) {
6939 /* deviation for another module, ignore */
6940 goto cleanup;
6941 }
6942
6943 /* try to find the node in already compiled deviations */
6944 for (i = 0; i < ctx->devs.count; ++i) {
6945 if (lys_abs_schema_nodeid_match(ctx->ctx, exp, mod_def, ((struct lysc_deviation *)ctx->devs.objs[i])->nodeid,
6946 ((struct lysc_deviation *)ctx->devs.objs[i])->nodeid_mod)) {
6947 dev = ctx->devs.objs[i];
6948 break;
6949 }
6950 }
6951
6952 if (!dev) {
6953 /* allocate new compiled deviation */
6954 dev = calloc(1, sizeof *dev);
6955 LY_CHECK_ERR_GOTO(!dev, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
6956 LY_CHECK_GOTO(ret = ly_set_add(&ctx->devs, dev, LY_SET_OPT_USEASLIST, NULL), cleanup);
6957
6958 dev->nodeid = exp;
6959 exp = NULL;
6960 dev->nodeid_mod = mod_def;
6961 }
6962
6963 /* add new parsed deviation structure */
6964 LY_ARRAY_NEW_GOTO(ctx->ctx, dev->devs, new_dev, ret, cleanup);
6965 *new_dev = dev_p;
6966 LY_ARRAY_NEW_GOTO(ctx->ctx, dev->dev_mods, new_dev_mod, ret, cleanup);
6967 *new_dev_mod = mod_def;
6968
6969cleanup:
6970 lyxp_expr_free(ctx->ctx, exp);
6971 return ret;
6972}
6973
6974/**
6975 * @brief Prepare all deviations for the current module to be applied during data nodes compilation.
6976 *
6977 * @param[in] ctx Compile context.
6978 * @return LY_ERR value.
6979 */
6980static LY_ERR
6981lys_precompile_own_deviations(struct lysc_ctx *ctx)
6982{
6983 LY_ARRAY_COUNT_TYPE u, v, w;
6984 const struct lys_module *dev_mod;
6985 struct lysc_deviation *dev;
6986 struct lysp_deviate *d;
6987 int not_supported;
6988 uint32_t i;
6989
6990 LY_ARRAY_FOR(ctx->mod->deviated_by, u) {
6991 dev_mod = ctx->mod->deviated_by[u];
6992
6993 /* compile all module deviations */
6994 LY_ARRAY_FOR(dev_mod->parsed->deviations, v) {
6995 LY_CHECK_RET(lys_precompile_own_deviation(ctx, &dev_mod->parsed->deviations[v], dev_mod));
6996 }
6997
6998 /* compile all submodules deviations */
6999 LY_ARRAY_FOR(dev_mod->parsed->includes, v) {
7000 LY_ARRAY_FOR(dev_mod->parsed->includes[v].submodule->deviations, w) {
7001 LY_CHECK_RET(lys_precompile_own_deviation(ctx, &dev_mod->parsed->includes[v].submodule->deviations[w], dev_mod));
7002 }
7003 }
7004 }
7005
7006 /* set not-supported flags for all the deviations */
7007 for (i = 0; i < ctx->devs.count; ++i) {
7008 dev = ctx->devs.objs[i];
7009 not_supported = 0;
7010
7011 LY_ARRAY_FOR(dev->devs, u) {
7012 LY_LIST_FOR(dev->devs[u]->deviates, d) {
7013 if (d->mod == LYS_DEV_NOT_SUPPORTED) {
7014 not_supported = 1;
7015 break;
7016 }
7017 }
7018 if (not_supported) {
7019 break;
7020 }
7021 }
7022 if (not_supported && (LY_ARRAY_COUNT(dev->devs) > 1)) {
7023 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
7024 "Multiple deviations of \"%s\" with one of them being \"not-supported\".", dev->nodeid->expr);
7025 return LY_EVALID;
7026 }
7027
7028 dev->not_supported = not_supported;
7029 }
7030
7031 return LY_SUCCESS;
7032}
7033
Michal Vasko20424b42020-08-31 12:29:38 +02007034/**
Radek Krejcia3045382018-11-22 14:30:31 +01007035 * @brief Compile parsed schema node information.
7036 * @param[in] ctx Compile context
Michal Vasko7f45cf22020-10-01 12:49:44 +02007037 * @param[in] pnode Parsed schema node.
Radek Krejcia3045382018-11-22 14:30:31 +01007038 * @param[in] parent Compiled parent node where the current node is supposed to be connected. It is
7039 * NULL for top-level nodes, in such a case the module where the node will be connected is taken from
7040 * the compile context.
Radek Krejcib1b59152019-01-07 13:21:56 +01007041 * @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).
7042 * Zero means no uses, non-zero value with no status bit set mean the default status.
Radek Krejcia3045382018-11-22 14:30:31 +01007043 * @return LY_ERR value - LY_SUCCESS or LY_EVALID.
7044 */
Radek Krejci19a96102018-11-15 13:38:09 +01007045static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02007046lys_compile_node(struct lysc_ctx *ctx, struct lysp_node *pnode, struct lysc_node *parent, uint16_t uses_status,
7047 struct ly_set *child_set)
Radek Krejci19a96102018-11-15 13:38:09 +01007048{
Radek Krejci1c54f462020-05-12 17:25:34 +02007049 LY_ERR ret = LY_SUCCESS;
Radek Krejcic6b4f442020-08-12 14:45:18 +02007050 struct lysc_node *node = NULL;
Michal Vasko7f45cf22020-10-01 12:49:44 +02007051 struct lysp_node *dev_pnode = NULL, *orig_pnode = pnode;
Radek Krejci1deb5be2020-08-26 16:43:36 +02007052 LY_ARRAY_COUNT_TYPE u;
Michal Vasko7f45cf22020-10-01 12:49:44 +02007053 ly_bool not_supported;
Michal Vasko69730152020-10-09 16:30:07 +02007054
Michal Vasko22df3f02020-08-24 13:29:22 +02007055 LY_ERR (*node_compile_spec)(struct lysc_ctx *, struct lysp_node *, struct lysc_node *);
Radek Krejci19a96102018-11-15 13:38:09 +01007056
Michal Vasko7f45cf22020-10-01 12:49:44 +02007057 if (pnode->nodetype != LYS_USES) {
7058 lysc_update_path(ctx, parent, pnode->name);
Radek Krejci327de162019-06-14 12:52:07 +02007059 } else {
7060 lysc_update_path(ctx, NULL, "{uses}");
Michal Vasko7f45cf22020-10-01 12:49:44 +02007061 lysc_update_path(ctx, NULL, pnode->name);
Radek Krejci327de162019-06-14 12:52:07 +02007062 }
7063
Michal Vasko7f45cf22020-10-01 12:49:44 +02007064 switch (pnode->nodetype) {
Radek Krejci19a96102018-11-15 13:38:09 +01007065 case LYS_CONTAINER:
Michal Vasko22df3f02020-08-24 13:29:22 +02007066 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_container));
Radek Krejci19a96102018-11-15 13:38:09 +01007067 node_compile_spec = lys_compile_node_container;
7068 break;
7069 case LYS_LEAF:
Michal Vasko22df3f02020-08-24 13:29:22 +02007070 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_leaf));
Radek Krejci19a96102018-11-15 13:38:09 +01007071 node_compile_spec = lys_compile_node_leaf;
7072 break;
7073 case LYS_LIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02007074 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_list));
Radek Krejci9bb94eb2018-12-04 16:48:35 +01007075 node_compile_spec = lys_compile_node_list;
Radek Krejci19a96102018-11-15 13:38:09 +01007076 break;
7077 case LYS_LEAFLIST:
Michal Vasko22df3f02020-08-24 13:29:22 +02007078 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_leaflist));
Radek Krejci0e5d8382018-11-28 16:37:53 +01007079 node_compile_spec = lys_compile_node_leaflist;
Radek Krejci19a96102018-11-15 13:38:09 +01007080 break;
Radek Krejci19a96102018-11-15 13:38:09 +01007081 case LYS_CHOICE:
Michal Vasko22df3f02020-08-24 13:29:22 +02007082 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_choice));
Radek Krejci056d0a82018-12-06 16:57:25 +01007083 node_compile_spec = lys_compile_node_choice;
Radek Krejci19a96102018-11-15 13:38:09 +01007084 break;
Michal Vasko891d7532020-10-07 09:41:38 +02007085 case LYS_CASE:
Michal Vasko20424b42020-08-31 12:29:38 +02007086 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_case));
7087 node_compile_spec = lys_compile_node_case;
7088 break;
Radek Krejci19a96102018-11-15 13:38:09 +01007089 case LYS_ANYXML:
7090 case LYS_ANYDATA:
Michal Vasko22df3f02020-08-24 13:29:22 +02007091 node = (struct lysc_node *)calloc(1, sizeof(struct lysc_node_anydata));
Radek Krejci9800fb82018-12-13 14:26:23 +01007092 node_compile_spec = lys_compile_node_any;
Radek Krejci19a96102018-11-15 13:38:09 +01007093 break;
Radek Krejcie86bf772018-12-14 11:39:53 +01007094 case LYS_USES:
Michal Vasko7f45cf22020-10-01 12:49:44 +02007095 ret = lys_compile_uses(ctx, (struct lysp_node_uses *)pnode, parent, child_set);
Radek Krejci327de162019-06-14 12:52:07 +02007096 lysc_update_path(ctx, NULL, NULL);
7097 lysc_update_path(ctx, NULL, NULL);
7098 return ret;
Radek Krejci19a96102018-11-15 13:38:09 +01007099 default:
7100 LOGINT(ctx->ctx);
7101 return LY_EINT;
7102 }
7103 LY_CHECK_ERR_RET(!node, LOGMEM(ctx->ctx), LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007104
7105 /* compile any deviations for this node */
7106 LY_CHECK_ERR_RET(ret = lys_compile_node_deviations_refines(ctx, pnode, parent, &dev_pnode, &not_supported),
7107 free(node), ret);
7108 if (not_supported) {
7109 free(node);
7110 lysc_update_path(ctx, NULL, NULL);
7111 return LY_SUCCESS;
7112 } else if (dev_pnode) {
7113 pnode = dev_pnode;
7114 }
7115
7116 node->nodetype = pnode->nodetype;
Radek Krejci19a96102018-11-15 13:38:09 +01007117 node->module = ctx->mod;
7118 node->prev = node;
Michal Vasko7f45cf22020-10-01 12:49:44 +02007119 node->flags = pnode->flags & LYS_FLAGS_COMPILED_MASK;
Radek Krejci19a96102018-11-15 13:38:09 +01007120
7121 /* config */
Michal Vasko20424b42020-08-31 12:29:38 +02007122 ret = lys_compile_config(ctx, node, parent);
7123 LY_CHECK_GOTO(ret, error);
Radek Krejci19a96102018-11-15 13:38:09 +01007124
Michal Vasko20424b42020-08-31 12:29:38 +02007125 /* list ordering */
Radek Krejcia6d57732018-11-29 13:40:37 +01007126 if (node->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
7127 if ((node->flags & LYS_CONFIG_R) && (node->flags & LYS_ORDBY_MASK)) {
Radek Krejcifc11bd72019-04-11 16:00:05 +02007128 LOGWRN(ctx->ctx, "The ordered-by statement is ignored in lists representing %s (%s).",
Radek Krejci0f969882020-08-21 16:56:47 +02007129 (ctx->options & LYSC_OPT_RPC_OUTPUT) ? "RPC/action output parameters" :
7130 (ctx->options & LYSC_OPT_NOTIFICATION) ? "notification content" : "state data", ctx->path);
Radek Krejcia6d57732018-11-29 13:40:37 +01007131 node->flags &= ~LYS_ORDBY_MASK;
7132 node->flags |= LYS_ORDBY_SYSTEM;
7133 } else if (!(node->flags & LYS_ORDBY_MASK)) {
7134 /* default ordering is system */
7135 node->flags |= LYS_ORDBY_SYSTEM;
7136 }
7137 }
7138
Radek Krejci19a96102018-11-15 13:38:09 +01007139 /* status - it is not inherited by specification, but it does not make sense to have
7140 * current in deprecated or deprecated in obsolete, so we do print warning and inherit status */
Michal Vasko20424b42020-08-31 12:29:38 +02007141 LY_CHECK_GOTO(ret = lys_compile_status(ctx, &node->flags, uses_status ? uses_status : (parent ? parent->flags : 0)), error);
Radek Krejci19a96102018-11-15 13:38:09 +01007142
Radek Krejciec4da802019-05-02 13:02:41 +02007143 if (!(ctx->options & LYSC_OPT_FREE_SP)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02007144 node->sp = orig_pnode;
Radek Krejci19a96102018-11-15 13:38:09 +01007145 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02007146 DUP_STRING_GOTO(ctx->ctx, pnode->name, node->name, ret, error);
7147 DUP_STRING_GOTO(ctx->ctx, pnode->dsc, node->dsc, ret, error);
7148 DUP_STRING_GOTO(ctx->ctx, pnode->ref, node->ref, ret, error);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007149 COMPILE_ARRAY_GOTO(ctx, pnode->iffeatures, node->iffeatures, u, lys_compile_iffeature, ret, error);
Radek Krejci19a96102018-11-15 13:38:09 +01007150
Michal Vasko20424b42020-08-31 12:29:38 +02007151 /* insert into parent's children/compiled module (we can no longer free the node separately on error) */
Michal Vasko7f45cf22020-10-01 12:49:44 +02007152 LY_CHECK_GOTO(ret = lys_compile_node_connect(ctx, parent, node), cleanup);
7153
Michal Vasko4865ac42020-10-12 16:31:06 +02007154 if (pnode->when) {
7155 /* compile when */
7156 ret = lys_compile_when(ctx, pnode->when, pnode->flags, lysc_xpath_context(node), node, NULL);
7157 LY_CHECK_GOTO(ret, cleanup);
7158 }
7159
Michal Vasko7f45cf22020-10-01 12:49:44 +02007160 /* connect any augments */
7161 LY_CHECK_GOTO(ret = lys_compile_node_augments(ctx, node), cleanup);
Michal Vasko20424b42020-08-31 12:29:38 +02007162
Radek Krejci19a96102018-11-15 13:38:09 +01007163 /* nodetype-specific part */
Michal Vasko7f45cf22020-10-01 12:49:44 +02007164 LY_CHECK_GOTO(ret = node_compile_spec(ctx, pnode, node), cleanup);
Radek Krejci19a96102018-11-15 13:38:09 +01007165
Michal Vasko20424b42020-08-31 12:29:38 +02007166 /* final compilation tasks that require the node to be connected */
Michal Vasko7f45cf22020-10-01 12:49:44 +02007167 COMPILE_EXTS_GOTO(ctx, pnode->exts, node->exts, node, LYEXT_PAR_NODE, ret, cleanup);
Radek Krejcife909632019-02-12 15:34:42 +01007168 if (node->flags & LYS_MAND_TRUE) {
Michal Vasko20424b42020-08-31 12:29:38 +02007169 /* inherit LYS_MAND_TRUE in parent containers */
Radek Krejcife909632019-02-12 15:34:42 +01007170 lys_compile_mandatory_parents(parent, 1);
7171 }
7172
Michal Vasko7f45cf22020-10-01 12:49:44 +02007173 if (child_set) {
7174 /* add the new node into set */
7175 LY_CHECK_GOTO(ret = ly_set_add(child_set, node, LY_SET_OPT_USEASLIST, NULL), cleanup);
7176 }
7177
Radek Krejci327de162019-06-14 12:52:07 +02007178 lysc_update_path(ctx, NULL, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007179 lysp_dev_node_free(ctx->ctx, dev_pnode);
Radek Krejci19a96102018-11-15 13:38:09 +01007180 return LY_SUCCESS;
7181
7182error:
7183 lysc_node_free(ctx->ctx, node);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007184cleanup:
7185 if (dev_pnode) {
7186 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_OTHER, "Compilation of a deviated and/or refined node failed.");
7187 lysp_dev_node_free(ctx->ctx, dev_pnode);
7188 }
Radek Krejci19a96102018-11-15 13:38:09 +01007189 return ret;
7190}
7191
Michal Vaskoccc062a2020-08-13 08:34:50 +02007192/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02007193 * @brief Add a module reference into an array, checks for duplicities.
Michal Vaskoccc062a2020-08-13 08:34:50 +02007194 *
7195 * @param[in] ctx Compile context.
Michal Vasko7f45cf22020-10-01 12:49:44 +02007196 * @param[in] mod Module reference to add.
7197 * @param[in,out] mod_array Module sized array to add to.
Michal Vaskoccc062a2020-08-13 08:34:50 +02007198 * @return LY_ERR value.
7199 */
7200static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02007201lys_array_add_mod_ref(struct lysc_ctx *ctx, struct lys_module *mod, struct lys_module ***mod_array)
Michal Vaskoccc062a2020-08-13 08:34:50 +02007202{
Michal Vasko7f45cf22020-10-01 12:49:44 +02007203 LY_ARRAY_COUNT_TYPE u;
7204 struct lys_module **new_mod;
Michal Vaskoccc062a2020-08-13 08:34:50 +02007205
Michal Vasko7f45cf22020-10-01 12:49:44 +02007206 LY_ARRAY_FOR(*mod_array, u) {
7207 if ((*mod_array)[u] == mod) {
7208 /* already there */
7209 return LY_EEXIST;
Michal Vaskoccc062a2020-08-13 08:34:50 +02007210 }
7211 }
7212
Michal Vasko7f45cf22020-10-01 12:49:44 +02007213 /* add the new module ref */
7214 LY_ARRAY_NEW_RET(ctx->ctx, *mod_array, new_mod, LY_EMEM);
7215 *new_mod = mod;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007216
7217 return LY_SUCCESS;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007218}
7219
Michal Vaskoccc062a2020-08-13 08:34:50 +02007220/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02007221 * @brief Compile top-level augments and deviations defined in the current module.
Michal Vasko89b5c072020-10-06 13:52:44 +02007222 * Generally, just add the module refence to the target modules. But in case
7223 * of foreign augments, they are directly applied.
Michal Vaskoccc062a2020-08-13 08:34:50 +02007224 *
7225 * @param[in] ctx Compile context.
Michal Vaskoccc062a2020-08-13 08:34:50 +02007226 * @return LY_ERR value.
7227 */
7228static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02007229lys_precompile_augments_deviations(struct lysc_ctx *ctx)
Michal Vaskoccc062a2020-08-13 08:34:50 +02007230{
Michal Vasko7f45cf22020-10-01 12:49:44 +02007231 LY_ERR ret = LY_SUCCESS;
7232 LY_ARRAY_COUNT_TYPE u, v;
7233 const struct lysp_module *mod_p;
7234 const struct lysc_node *target;
Michal Vaskoccc062a2020-08-13 08:34:50 +02007235 struct lys_module *mod;
Michal Vasko7f45cf22020-10-01 12:49:44 +02007236 struct lysp_submodule *submod;
7237 ly_bool has_dev = 0;
7238 uint16_t flags;
7239 uint32_t idx, opt_prev = ctx->options;
Michal Vaskoccc062a2020-08-13 08:34:50 +02007240
Michal Vasko89b5c072020-10-06 13:52:44 +02007241 for (idx = 0; idx < ctx->ctx->implementing.count; ++idx) {
7242 if (ctx->mod == ctx->ctx->implementing.objs[idx]) {
7243 break;
7244 }
7245 }
7246 if (idx == ctx->ctx->implementing.count) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02007247 /* it was already implemented and all the augments and deviations fully applied */
7248 return LY_SUCCESS;
Michal Vaskoccc062a2020-08-13 08:34:50 +02007249 }
7250
Michal Vasko89b5c072020-10-06 13:52:44 +02007251 mod_p = ctx->mod->parsed;
7252
Michal Vasko7f45cf22020-10-01 12:49:44 +02007253 LY_ARRAY_FOR(mod_p->augments, u) {
7254 lysc_update_path(ctx, NULL, "{augment}");
7255 lysc_update_path(ctx, NULL, mod_p->augments[u].nodeid);
Michal Vaskoccc062a2020-08-13 08:34:50 +02007256
Michal Vasko7f45cf22020-10-01 12:49:44 +02007257 /* get target module */
7258 ret = lys_nodeid_check(ctx, mod_p->augments[u].nodeid, 1, &mod, NULL);
7259 LY_CHECK_RET(ret);
Michal Vaskoccc062a2020-08-13 08:34:50 +02007260
Michal Vasko7f45cf22020-10-01 12:49:44 +02007261 /* add this module into the target module augmented_by, if not there already from previous augments */
7262 lys_array_add_mod_ref(ctx, ctx->mod, &mod->augmented_by);
Michal Vaskoccc062a2020-08-13 08:34:50 +02007263
Michal Vasko7f45cf22020-10-01 12:49:44 +02007264 /* if we are compiling this module, we cannot add augments to it yet */
7265 if (mod != ctx->mod) {
7266 /* apply the augment, find the target node first */
7267 flags = 0;
7268 ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->mod_def, 0, &target, &flags);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007269 LY_CHECK_RET(ret);
7270
Michal Vasko7f45cf22020-10-01 12:49:44 +02007271 /* apply the augment */
7272 ctx->options |= flags;
7273 ret = lys_compile_augment(ctx, &mod_p->augments[u], (struct lysc_node *)target);
7274 ctx->options = opt_prev;
7275 LY_CHECK_RET(ret);
Radek Krejciccd20f12019-02-15 14:12:27 +01007276 }
Radek Krejci327de162019-06-14 12:52:07 +02007277
7278 lysc_update_path(ctx, NULL, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007279 lysc_update_path(ctx, NULL, NULL);
Radek Krejciccd20f12019-02-15 14:12:27 +01007280 }
7281
Michal Vasko7f45cf22020-10-01 12:49:44 +02007282 LY_ARRAY_FOR(mod_p->deviations, u) {
7283 /* get target module */
7284 lysc_update_path(ctx, NULL, "{deviation}");
7285 lysc_update_path(ctx, NULL, mod_p->deviations[u].nodeid);
7286 ret = lys_nodeid_check(ctx, mod_p->deviations[u].nodeid, 1, &mod, NULL);
7287 lysc_update_path(ctx, NULL, NULL);
7288 lysc_update_path(ctx, NULL, NULL);
7289 LY_CHECK_RET(ret);
Radek Krejciba03a5a2020-08-27 14:40:41 +02007290
Michal Vasko7f45cf22020-10-01 12:49:44 +02007291 /* add this module into the target module deviated_by, if not there already from previous deviations */
7292 lys_array_add_mod_ref(ctx, ctx->mod, &mod->deviated_by);
7293
7294 /* new deviation added to the target module */
7295 has_dev = 1;
7296 }
7297
7298 /* the same for augments and deviations in submodules */
7299 LY_ARRAY_FOR(mod_p->includes, v) {
7300 submod = mod_p->includes[v].submodule;
7301 LY_ARRAY_FOR(submod->augments, u) {
7302 lysc_update_path(ctx, NULL, "{augment}");
7303 lysc_update_path(ctx, NULL, submod->augments[u].nodeid);
7304
7305 ret = lys_nodeid_check(ctx, submod->augments[u].nodeid, 1, &mod, NULL);
7306 LY_CHECK_RET(ret);
7307
7308 lys_array_add_mod_ref(ctx, ctx->mod, &mod->augmented_by);
7309 if (mod != ctx->mod) {
7310 flags = 0;
7311 ret = lysc_resolve_schema_nodeid(ctx, mod_p->augments[u].nodeid, 0, NULL, ctx->mod_def, 0, &target, &flags);
7312 LY_CHECK_RET(ret);
7313
7314 ctx->options |= flags;
7315 ret = lys_compile_augment(ctx, &submod->augments[u], (struct lysc_node *)target);
7316 ctx->options = opt_prev;
7317 LY_CHECK_RET(ret);
Radek Krejcif538ce52019-03-05 10:46:14 +01007318 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02007319
7320 lysc_update_path(ctx, NULL, NULL);
7321 lysc_update_path(ctx, NULL, NULL);
Radek Krejcif538ce52019-03-05 10:46:14 +01007322 }
7323
Michal Vasko7f45cf22020-10-01 12:49:44 +02007324 LY_ARRAY_FOR(submod->deviations, u) {
7325 lysc_update_path(ctx, NULL, "{deviation}");
7326 lysc_update_path(ctx, NULL, submod->deviations[u].nodeid);
7327 ret = lys_nodeid_check(ctx, submod->deviations[u].nodeid, 1, &mod, NULL);
7328 lysc_update_path(ctx, NULL, NULL);
7329 lysc_update_path(ctx, NULL, NULL);
7330 LY_CHECK_RET(ret);
Radek Krejcifc11bd72019-04-11 16:00:05 +02007331
Michal Vasko7f45cf22020-10-01 12:49:44 +02007332 lys_array_add_mod_ref(ctx, ctx->mod, &mod->deviated_by);
7333 has_dev = 1;
Michal Vaskoe6143202020-07-03 13:02:08 +02007334 }
Radek Krejciccd20f12019-02-15 14:12:27 +01007335 }
7336
Michal Vasko7f45cf22020-10-01 12:49:44 +02007337 if (!has_dev) {
7338 /* no need to recompile any modules */
7339 return LY_SUCCESS;
7340 }
7341
7342 /* free all the modules in descending order */
7343 idx = ctx->ctx->list.count;
7344 do {
7345 --idx;
7346 mod = ctx->ctx->list.objs[idx];
7347 /* skip this module */
7348 if (mod == mod_p->mod) {
7349 continue;
7350 }
7351
7352 if (mod->implemented && mod->compiled) {
7353 /* keep information about features state in the module */
7354 lys_feature_precompile_revert(ctx, mod);
7355
7356 /* free the module */
7357 lysc_module_free(mod->compiled, NULL);
7358 mod->compiled = NULL;
7359 }
7360 } while (idx);
7361
7362 /* recompile all the modules in ascending order */
7363 for (idx = 0; idx < ctx->ctx->list.count; ++idx) {
7364 mod = ctx->ctx->list.objs[idx];
7365
7366 /* skip this module */
7367 if (mod == mod_p->mod) {
7368 continue;
7369 }
7370
7371 if (mod->implemented) {
7372 /* compile */
Michal Vasko89b5c072020-10-06 13:52:44 +02007373 LY_CHECK_GOTO(ret = lys_compile(mod, 0), cleanup);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007374 }
7375 }
Radek Krejciccd20f12019-02-15 14:12:27 +01007376
7377cleanup:
Radek Krejcid05cbd92018-12-05 14:26:40 +01007378 return ret;
7379}
7380
Radek Krejci335332a2019-09-05 13:03:35 +02007381static void *
7382lys_compile_extension_instance_storage(enum ly_stmt stmt, struct lysc_ext_substmt *substmts)
7383{
Radek Krejci1deb5be2020-08-26 16:43:36 +02007384 for (LY_ARRAY_COUNT_TYPE u = 0; substmts[u].stmt; ++u) {
Radek Krejci335332a2019-09-05 13:03:35 +02007385 if (substmts[u].stmt == stmt) {
7386 return substmts[u].storage;
7387 }
7388 }
7389 return NULL;
7390}
7391
7392LY_ERR
7393lys_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *ext, struct lysc_ext_substmt *substmts)
7394{
7395 LY_ERR ret = LY_EVALID, r;
Radek Krejci1deb5be2020-08-26 16:43:36 +02007396 LY_ARRAY_COUNT_TYPE u;
Radek Krejci335332a2019-09-05 13:03:35 +02007397 struct lysp_stmt *stmt;
Michal Vasko7f45cf22020-10-01 12:49:44 +02007398 struct lysp_qname qname;
Radek Krejci335332a2019-09-05 13:03:35 +02007399 void *parsed = NULL, **compiled = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +02007400
7401 /* check for invalid substatements */
7402 for (stmt = ext->child; stmt; stmt = stmt->next) {
Radek Krejcif56e2a42019-09-09 14:15:25 +02007403 if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
7404 continue;
7405 }
Radek Krejci335332a2019-09-05 13:03:35 +02007406 for (u = 0; substmts[u].stmt; ++u) {
7407 if (substmts[u].stmt == stmt->kw) {
7408 break;
7409 }
7410 }
7411 if (!substmts[u].stmt) {
Radek Krejciad5963b2019-09-06 16:03:05 +02007412 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
Michal Vasko69730152020-10-09 16:30:07 +02007413 stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
Radek Krejci335332a2019-09-05 13:03:35 +02007414 goto cleanup;
7415 }
Radek Krejci335332a2019-09-05 13:03:35 +02007416 }
7417
Radek Krejciad5963b2019-09-06 16:03:05 +02007418 /* TODO store inherited data, e.g. status first, but mark them somehow to allow to overwrite them and not detect duplicity */
7419
Radek Krejci335332a2019-09-05 13:03:35 +02007420 /* keep order of the processing the same as the order in the defined substmts,
7421 * the order is important for some of the statements depending on others (e.g. type needs status and units) */
7422 for (u = 0; substmts[u].stmt; ++u) {
Radek Krejci857189e2020-09-01 13:26:36 +02007423 ly_bool stmt_present = 0;
Radek Krejciad5963b2019-09-06 16:03:05 +02007424
Radek Krejci335332a2019-09-05 13:03:35 +02007425 for (stmt = ext->child; stmt; stmt = stmt->next) {
7426 if (substmts[u].stmt != stmt->kw) {
7427 continue;
7428 }
7429
Radek Krejciad5963b2019-09-06 16:03:05 +02007430 stmt_present = 1;
Radek Krejci335332a2019-09-05 13:03:35 +02007431 if (substmts[u].storage) {
7432 switch (stmt->kw) {
Radek Krejciad5963b2019-09-06 16:03:05 +02007433 case LY_STMT_STATUS:
7434 assert(substmts[u].cardinality < LY_STMT_CARD_SOME);
7435 LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, stmt->kw, &substmts[u].storage, /* TODO */ NULL), ret = r, cleanup);
7436 break;
7437 case LY_STMT_UNITS: {
7438 const char **units;
7439
7440 if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
7441 /* single item */
7442 if (*((const char **)substmts[u].storage)) {
7443 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPSTMT, stmt->stmt);
7444 goto cleanup;
7445 }
7446 units = (const char **)substmts[u].storage;
7447 } else {
7448 /* sized array */
7449 const char ***units_array = (const char ***)substmts[u].storage;
7450 LY_ARRAY_NEW_GOTO(ctx->ctx, *units_array, units, ret, cleanup);
7451 }
Radek Krejci011e4aa2020-09-04 15:22:31 +02007452 r = lydict_insert(ctx->ctx, stmt->arg, 0, units);
7453 LY_CHECK_ERR_GOTO(r, ret = r, cleanup);
Radek Krejciad5963b2019-09-06 16:03:05 +02007454 break;
7455 }
Radek Krejci335332a2019-09-05 13:03:35 +02007456 case LY_STMT_TYPE: {
7457 uint16_t *flags = lys_compile_extension_instance_storage(LY_STMT_STATUS, substmts);
7458 const char **units = lys_compile_extension_instance_storage(LY_STMT_UNITS, substmts);
7459
7460 if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
7461 /* single item */
Michal Vasko22df3f02020-08-24 13:29:22 +02007462 if (*(struct lysc_type **)substmts[u].storage) {
Radek Krejci335332a2019-09-05 13:03:35 +02007463 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPSTMT, stmt->stmt);
7464 goto cleanup;
7465 }
7466 compiled = substmts[u].storage;
7467 } else {
7468 /* sized array */
Michal Vasko22df3f02020-08-24 13:29:22 +02007469 struct lysc_type ***types = (struct lysc_type ***)substmts[u].storage, **type = NULL;
Radek Krejci335332a2019-09-05 13:03:35 +02007470 LY_ARRAY_NEW_GOTO(ctx->ctx, *types, type, ret, cleanup);
Michal Vasko22df3f02020-08-24 13:29:22 +02007471 compiled = (void *)type;
Radek Krejci335332a2019-09-05 13:03:35 +02007472 }
7473
Radek Krejciad5963b2019-09-06 16:03:05 +02007474 LY_CHECK_ERR_GOTO(r = lysp_stmt_parse(ctx, stmt, stmt->kw, &parsed, NULL), ret = r, cleanup);
Michal Vasko22df3f02020-08-24 13:29:22 +02007475 LY_CHECK_ERR_GOTO(r = lys_compile_type(ctx, ext->parent_type == LYEXT_PAR_NODE ? ((struct lysc_node *)ext->parent)->sp : NULL,
Michal Vasko69730152020-10-09 16:30:07 +02007476 flags ? *flags : 0, ctx->mod_def->parsed, ext->name, parsed, (struct lysc_type **)compiled,
7477 units && !*units ? units : NULL, NULL), lysp_type_free(ctx->ctx, parsed); free(parsed); ret = r, cleanup);
Radek Krejci38d85362019-09-05 16:26:38 +02007478 lysp_type_free(ctx->ctx, parsed);
7479 free(parsed);
Radek Krejci335332a2019-09-05 13:03:35 +02007480 break;
7481 }
Radek Krejciad5963b2019-09-06 16:03:05 +02007482 case LY_STMT_IF_FEATURE: {
7483 struct lysc_iffeature *iff = NULL;
7484
7485 if (substmts[u].cardinality < LY_STMT_CARD_SOME) {
7486 /* single item */
Michal Vasko22df3f02020-08-24 13:29:22 +02007487 if (((struct lysc_iffeature *)substmts[u].storage)->features) {
Radek Krejciad5963b2019-09-06 16:03:05 +02007488 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LY_VCODE_DUPSTMT, stmt->stmt);
7489 goto cleanup;
7490 }
Michal Vasko22df3f02020-08-24 13:29:22 +02007491 iff = (struct lysc_iffeature *)substmts[u].storage;
Radek Krejciad5963b2019-09-06 16:03:05 +02007492 } else {
7493 /* sized array */
Michal Vasko22df3f02020-08-24 13:29:22 +02007494 struct lysc_iffeature **iffs = (struct lysc_iffeature **)substmts[u].storage;
Radek Krejciad5963b2019-09-06 16:03:05 +02007495 LY_ARRAY_NEW_GOTO(ctx->ctx, *iffs, iff, ret, cleanup);
7496 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02007497 qname.str = stmt->arg;
7498 qname.mod = ctx->mod_def;
7499 LY_CHECK_ERR_GOTO(r = lys_compile_iffeature(ctx, &qname, iff), ret = r, cleanup);
Radek Krejciad5963b2019-09-06 16:03:05 +02007500 break;
7501 }
7502 /* TODO support other substatements (parse stmt to lysp and then compile lysp to lysc),
7503 * also note that in many statements their extensions are not taken into account */
Radek Krejci335332a2019-09-05 13:03:35 +02007504 default:
Radek Krejciad5963b2019-09-06 16:03:05 +02007505 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension (found in \"%s%s%s\") substatement.",
Michal Vasko69730152020-10-09 16:30:07 +02007506 stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
Radek Krejci335332a2019-09-05 13:03:35 +02007507 goto cleanup;
7508 }
7509 }
Radek Krejci335332a2019-09-05 13:03:35 +02007510 }
Radek Krejci335332a2019-09-05 13:03:35 +02007511
Michal Vasko69730152020-10-09 16:30:07 +02007512 if (((substmts[u].cardinality == LY_STMT_CARD_MAND) || (substmts[u].cardinality == LY_STMT_CARD_SOME)) && !stmt_present) {
Radek Krejciad5963b2019-09-06 16:03:05 +02007513 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SYNTAX_YANG, "Missing mandatory keyword \"%s\" as a child of \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +02007514 ly_stmt2str(substmts[u].stmt), ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
Radek Krejciad5963b2019-09-06 16:03:05 +02007515 goto cleanup;
7516 }
Radek Krejci335332a2019-09-05 13:03:35 +02007517 }
7518
7519 ret = LY_SUCCESS;
7520
7521cleanup:
Radek Krejci335332a2019-09-05 13:03:35 +02007522 return ret;
7523}
7524
Michal Vasko175012e2019-11-06 15:49:14 +01007525/**
Michal Vaskoecd62de2019-11-13 12:35:11 +01007526 * @brief Check when for cyclic dependencies.
Michal Vasko7f45cf22020-10-01 12:49:44 +02007527 *
Michal Vaskoecd62de2019-11-13 12:35:11 +01007528 * @param[in] set Set with all the referenced nodes.
7529 * @param[in] node Node whose "when" referenced nodes are in @p set.
7530 * @return LY_ERR value
7531 */
7532static LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +02007533lys_compile_unres_when_cyclic(struct lyxp_set *set, const struct lysc_node *node)
Michal Vaskoecd62de2019-11-13 12:35:11 +01007534{
7535 struct lyxp_set tmp_set;
7536 struct lyxp_set_scnode *xp_scnode;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007537 uint32_t i, j;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02007538 LY_ARRAY_COUNT_TYPE u;
Michal Vaskoecd62de2019-11-13 12:35:11 +01007539 struct lysc_when *when;
7540 LY_ERR ret = LY_SUCCESS;
7541
7542 memset(&tmp_set, 0, sizeof tmp_set);
7543
7544 /* prepare in_ctx of the set */
Michal Vaskod989ba02020-08-24 10:59:24 +02007545 for (i = 0; i < set->used; ++i) {
Michal Vaskoecd62de2019-11-13 12:35:11 +01007546 xp_scnode = &set->val.scnodes[i];
7547
Michal Vasko5c4e5892019-11-14 12:31:38 +01007548 if (xp_scnode->in_ctx != -1) {
7549 /* check node when, skip the context node (it was just checked) */
Michal Vaskoecd62de2019-11-13 12:35:11 +01007550 xp_scnode->in_ctx = 1;
7551 }
7552 }
7553
7554 for (i = 0; i < set->used; ++i) {
7555 xp_scnode = &set->val.scnodes[i];
7556 if (xp_scnode->in_ctx != 1) {
7557 /* already checked */
7558 continue;
7559 }
7560
Michal Vasko69730152020-10-09 16:30:07 +02007561 if ((xp_scnode->type != LYXP_NODE_ELEM) || (xp_scnode->scnode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) ||
7562 !xp_scnode->scnode->when) {
Michal Vaskoecd62de2019-11-13 12:35:11 +01007563 /* no when to check */
7564 xp_scnode->in_ctx = 0;
7565 continue;
7566 }
7567
7568 node = xp_scnode->scnode;
7569 do {
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007570 LY_ARRAY_FOR(node->when, u) {
7571 when = node->when[u];
Michal Vaskoc8a230d2020-08-14 12:17:10 +02007572 ret = lyxp_atomize(when->cond, LY_PREF_SCHEMA, when->module, when->context,
Michal Vasko69730152020-10-09 16:30:07 +02007573 when->context ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG, &tmp_set, LYXP_SCNODE_SCHEMA);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007574 if (ret != LY_SUCCESS) {
Michal Vaskof6e51882019-12-16 09:59:45 +01007575 LOGVAL(set->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when->cond->expr);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007576 goto cleanup;
7577 }
7578
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007579 for (j = 0; j < tmp_set.used; ++j) {
Michal Vaskoecd62de2019-11-13 12:35:11 +01007580 /* skip roots'n'stuff */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007581 if (tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) {
Michal Vaskoecd62de2019-11-13 12:35:11 +01007582 /* try to find this node in our set */
Radek Krejciaa6b53f2020-08-27 15:19:03 +02007583 uint32_t idx;
7584 if (lyxp_set_scnode_contains(set, tmp_set.val.scnodes[j].scnode, LYXP_NODE_ELEM, -1, &idx) && (set->val.scnodes[idx].in_ctx == -1)) {
Michal Vaskof6e51882019-12-16 09:59:45 +01007585 LOGVAL(set->ctx, LY_VLOG_LYSC, node, LY_VCODE_CIRC_WHEN, node->name, set->val.scnodes[idx].scnode->name);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007586 ret = LY_EVALID;
7587 goto cleanup;
7588 }
7589
7590 /* needs to be checked, if in both sets, will be ignored */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007591 tmp_set.val.scnodes[j].in_ctx = 1;
Michal Vaskoecd62de2019-11-13 12:35:11 +01007592 } else {
7593 /* no when, nothing to check */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007594 tmp_set.val.scnodes[j].in_ctx = 0;
Michal Vaskoecd62de2019-11-13 12:35:11 +01007595 }
7596 }
7597
7598 /* merge this set into the global when set */
7599 lyxp_set_scnode_merge(set, &tmp_set);
7600 }
7601
7602 /* check when of non-data parents as well */
7603 node = node->parent;
7604 } while (node && (node->nodetype & (LYS_CASE | LYS_CHOICE)));
7605
Michal Vasko251f56e2019-11-14 16:06:47 +01007606 /* this node when was checked (xp_scnode could have been reallocd) */
7607 set->val.scnodes[i].in_ctx = -1;
Michal Vaskoecd62de2019-11-13 12:35:11 +01007608 }
7609
7610cleanup:
Michal Vaskod3678892020-05-21 10:06:58 +02007611 lyxp_set_free_content(&tmp_set);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007612 return ret;
7613}
7614
7615/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02007616 * @brief Check when/must expressions of a node on a complete compiled schema tree.
7617 *
Michal Vasko175012e2019-11-06 15:49:14 +01007618 * @param[in] ctx Compile context.
7619 * @param[in] node Node to check.
7620 * @return LY_ERR value
7621 */
7622static LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +02007623lys_compile_unres_xpath(struct lysc_ctx *ctx, const struct lysc_node *node)
Michal Vasko175012e2019-11-06 15:49:14 +01007624{
Michal Vasko175012e2019-11-06 15:49:14 +01007625 struct lyxp_set tmp_set;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007626 uint32_t i;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02007627 LY_ARRAY_COUNT_TYPE u;
Radek Krejci1deb5be2020-08-26 16:43:36 +02007628 uint32_t opts;
Radek Krejci857189e2020-09-01 13:26:36 +02007629 ly_bool input_done = 0;
Michal Vasko175012e2019-11-06 15:49:14 +01007630 struct lysc_when **when = NULL;
7631 struct lysc_must *musts = NULL;
7632 LY_ERR ret = LY_SUCCESS;
Michal Vasko6b26e742020-07-17 15:02:10 +02007633 const struct lysc_node *op;
Michal Vasko175012e2019-11-06 15:49:14 +01007634
7635 memset(&tmp_set, 0, sizeof tmp_set);
Michal Vasko5d8756a2019-11-07 15:21:00 +01007636 opts = LYXP_SCNODE_SCHEMA;
Michal Vasko6b26e742020-07-17 15:02:10 +02007637 if (node->flags & LYS_CONFIG_R) {
Michal Vasko2b7e5582020-10-07 12:31:23 +02007638 for (op = node->parent; op && !(op->nodetype & (LYS_RPC | LYS_ACTION)); op = op->parent) {}
Michal Vasko6b26e742020-07-17 15:02:10 +02007639 if (op) {
7640 /* we are actually in output */
7641 opts = LYXP_SCNODE_OUTPUT;
7642 }
7643 }
Michal Vasko175012e2019-11-06 15:49:14 +01007644
7645 switch (node->nodetype) {
7646 case LYS_CONTAINER:
7647 when = ((struct lysc_node_container *)node)->when;
7648 musts = ((struct lysc_node_container *)node)->musts;
7649 break;
7650 case LYS_CHOICE:
7651 when = ((struct lysc_node_choice *)node)->when;
7652 break;
7653 case LYS_LEAF:
7654 when = ((struct lysc_node_leaf *)node)->when;
7655 musts = ((struct lysc_node_leaf *)node)->musts;
7656 break;
7657 case LYS_LEAFLIST:
7658 when = ((struct lysc_node_leaflist *)node)->when;
7659 musts = ((struct lysc_node_leaflist *)node)->musts;
7660 break;
7661 case LYS_LIST:
7662 when = ((struct lysc_node_list *)node)->when;
7663 musts = ((struct lysc_node_list *)node)->musts;
7664 break;
7665 case LYS_ANYXML:
7666 case LYS_ANYDATA:
7667 when = ((struct lysc_node_anydata *)node)->when;
7668 musts = ((struct lysc_node_anydata *)node)->musts;
7669 break;
7670 case LYS_CASE:
7671 when = ((struct lysc_node_case *)node)->when;
7672 break;
7673 case LYS_NOTIF:
Michal Vaskoceab6dd2020-10-09 16:53:36 +02007674 when = ((struct lysc_notif *)node)->when;
Michal Vasko175012e2019-11-06 15:49:14 +01007675 musts = ((struct lysc_notif *)node)->musts;
7676 break;
Michal Vasko1bf09392020-03-27 12:38:10 +01007677 case LYS_RPC:
Michal Vasko5d8756a2019-11-07 15:21:00 +01007678 case LYS_ACTION:
Michal Vaskoceab6dd2020-10-09 16:53:36 +02007679 /* first process when and input musts */
7680 when = ((struct lysc_action *)node)->when;
Michal Vasko5d8756a2019-11-07 15:21:00 +01007681 musts = ((struct lysc_action *)node)->input.musts;
7682 break;
Michal Vasko175012e2019-11-06 15:49:14 +01007683 default:
7684 /* nothing to check */
7685 break;
7686 }
7687
Michal Vasko175012e2019-11-06 15:49:14 +01007688 /* check "when" */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007689 LY_ARRAY_FOR(when, u) {
Michal Vaskoc8a230d2020-08-14 12:17:10 +02007690 ret = lyxp_atomize(when[u]->cond, LY_PREF_SCHEMA, when[u]->module, when[u]->context ? when[u]->context : node,
Michal Vasko69730152020-10-09 16:30:07 +02007691 when[u]->context ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG, &tmp_set, opts);
Michal Vasko175012e2019-11-06 15:49:14 +01007692 if (ret != LY_SUCCESS) {
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007693 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when[u]->cond->expr);
Michal Vasko175012e2019-11-06 15:49:14 +01007694 goto cleanup;
7695 }
7696
Michal Vaskodc052f32019-11-07 11:11:38 +01007697 ctx->path[0] = '\0';
7698 lysc_path((struct lysc_node *)node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007699 for (i = 0; i < tmp_set.used; ++i) {
Michal Vasko5c4e5892019-11-14 12:31:38 +01007700 /* skip roots'n'stuff */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007701 if ((tmp_set.val.scnodes[i].type == LYXP_NODE_ELEM) && (tmp_set.val.scnodes[i].in_ctx != -1)) {
7702 struct lysc_node *schema = tmp_set.val.scnodes[i].scnode;
Michal Vasko175012e2019-11-06 15:49:14 +01007703
Michal Vaskoecd62de2019-11-13 12:35:11 +01007704 /* XPath expression cannot reference "lower" status than the node that has the definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007705 ret = lysc_check_status(ctx, when[u]->flags, when[u]->module, node->name, schema->flags, schema->module,
Michal Vasko69730152020-10-09 16:30:07 +02007706 schema->name);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007707 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko5c4e5892019-11-14 12:31:38 +01007708
7709 /* check dummy node accessing */
7710 if (schema == node) {
Michal Vaskof6e51882019-12-16 09:59:45 +01007711 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LY_VCODE_DUMMY_WHEN, node->name);
Michal Vasko5c4e5892019-11-14 12:31:38 +01007712 ret = LY_EVALID;
7713 goto cleanup;
7714 }
Michal Vasko175012e2019-11-06 15:49:14 +01007715 }
7716 }
7717
Michal Vaskoecd62de2019-11-13 12:35:11 +01007718 /* check cyclic dependencies */
Michal Vasko004d3152020-06-11 19:59:22 +02007719 ret = lys_compile_unres_when_cyclic(&tmp_set, node);
Michal Vaskoecd62de2019-11-13 12:35:11 +01007720 LY_CHECK_GOTO(ret, cleanup);
7721
Michal Vaskod3678892020-05-21 10:06:58 +02007722 lyxp_set_free_content(&tmp_set);
Michal Vasko175012e2019-11-06 15:49:14 +01007723 }
7724
Michal Vasko5d8756a2019-11-07 15:21:00 +01007725check_musts:
Michal Vasko175012e2019-11-06 15:49:14 +01007726 /* check "must" */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007727 LY_ARRAY_FOR(musts, u) {
Michal Vaskoc8a230d2020-08-14 12:17:10 +02007728 ret = lyxp_atomize(musts[u].cond, LY_PREF_SCHEMA, musts[u].module, node, LYXP_NODE_ELEM, &tmp_set, opts);
Michal Vasko175012e2019-11-06 15:49:14 +01007729 if (ret != LY_SUCCESS) {
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007730 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_SEMANTICS, "Invalid must restriction \"%s\".", musts[u].cond->expr);
Michal Vasko175012e2019-11-06 15:49:14 +01007731 goto cleanup;
7732 }
7733
Michal Vaskodc052f32019-11-07 11:11:38 +01007734 ctx->path[0] = '\0';
7735 lysc_path((struct lysc_node *)node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007736 for (i = 0; i < tmp_set.used; ++i) {
Michal Vasko175012e2019-11-06 15:49:14 +01007737 /* skip roots'n'stuff */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007738 if (tmp_set.val.scnodes[i].type == LYXP_NODE_ELEM) {
Michal Vasko175012e2019-11-06 15:49:14 +01007739 /* XPath expression cannot reference "lower" status than the node that has the definition */
Radek Krejci7eb54ba2020-05-18 16:30:04 +02007740 ret = lysc_check_status(ctx, node->flags, musts[u].module, node->name, tmp_set.val.scnodes[i].scnode->flags,
Michal Vasko69730152020-10-09 16:30:07 +02007741 tmp_set.val.scnodes[i].scnode->module, tmp_set.val.scnodes[i].scnode->name);
Michal Vasko175012e2019-11-06 15:49:14 +01007742 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko175012e2019-11-06 15:49:14 +01007743 }
7744 }
7745
Michal Vaskod3678892020-05-21 10:06:58 +02007746 lyxp_set_free_content(&tmp_set);
Michal Vasko175012e2019-11-06 15:49:14 +01007747 }
7748
Michal Vasko1bf09392020-03-27 12:38:10 +01007749 if ((node->nodetype & (LYS_RPC | LYS_ACTION)) && !input_done) {
Michal Vasko5d8756a2019-11-07 15:21:00 +01007750 /* now check output musts */
7751 input_done = 1;
Michal Vaskoceab6dd2020-10-09 16:53:36 +02007752 when = NULL;
Michal Vasko5d8756a2019-11-07 15:21:00 +01007753 musts = ((struct lysc_action *)node)->output.musts;
7754 opts = LYXP_SCNODE_OUTPUT;
7755 goto check_musts;
7756 }
7757
Michal Vasko175012e2019-11-06 15:49:14 +01007758cleanup:
Michal Vaskod3678892020-05-21 10:06:58 +02007759 lyxp_set_free_content(&tmp_set);
Michal Vasko175012e2019-11-06 15:49:14 +01007760 return ret;
7761}
7762
Michal Vasko7f45cf22020-10-01 12:49:44 +02007763/**
7764 * @brief Check leafref for its target existence on a complete compiled schema tree.
7765 *
7766 * @param[in] ctx Compile context.
7767 * @param[in] node Context node for the leafref.
7768 * @param[in] lref Leafref to resolve.
7769 * @return LY_ERR value.
7770 */
Michal Vasko8d544252020-03-02 10:19:52 +01007771static LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +02007772lys_compile_unres_leafref(struct lysc_ctx *ctx, const struct lysc_node *node, struct lysc_type_leafref *lref)
7773{
Michal Vasko6b26e742020-07-17 15:02:10 +02007774 const struct lysc_node *target = NULL, *siter;
Michal Vasko004d3152020-06-11 19:59:22 +02007775 struct ly_path *p;
7776 struct lysc_type *type;
7777
7778 assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
7779
7780 /* try to find the target */
Michal Vasko00cbf532020-06-15 13:58:47 +02007781 LY_CHECK_RET(ly_path_compile(ctx->ctx, node->module, node, lref->path, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +02007782 lysc_is_output(node) ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT, LY_PATH_TARGET_MANY,
7783 LY_PREF_SCHEMA, (void *)lref->path_mod, &p));
Michal Vasko004d3152020-06-11 19:59:22 +02007784
7785 /* get the target node */
Michal Vaskofd69e1d2020-07-03 11:57:17 +02007786 target = p[LY_ARRAY_COUNT(p) - 1].node;
Michal Vasko004d3152020-06-11 19:59:22 +02007787 ly_path_free(node->module->ctx, p);
7788
7789 if (!(target->nodetype & (LYS_LEAF | LYS_LEAFLIST))) {
7790 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02007791 "Invalid leafref path \"%s\" - target node is %s instead of leaf or leaf-list.",
7792 lref->path->expr, lys_nodetype2str(target->nodetype));
Michal Vasko004d3152020-06-11 19:59:22 +02007793 return LY_EVALID;
7794 }
7795
7796 /* check status */
7797 ctx->path[0] = '\0';
7798 lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
7799 ctx->path_len = strlen(ctx->path);
7800 if (lysc_check_status(ctx, node->flags, node->module, node->name, target->flags, target->module, target->name)) {
7801 return LY_EVALID;
7802 }
7803 ctx->path_len = 1;
7804 ctx->path[1] = '\0';
7805
7806 /* check config */
Michal Vasko6b26e742020-07-17 15:02:10 +02007807 if (lref->require_instance) {
Radek Krejci1e008d22020-08-17 11:37:37 +02007808 for (siter = node->parent; siter && !(siter->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); siter = siter->parent) {}
Michal Vasko6b26e742020-07-17 15:02:10 +02007809 if (!siter && (node->flags & LYS_CONFIG_W) && (target->flags & LYS_CONFIG_R)) {
Michal Vasko004d3152020-06-11 19:59:22 +02007810 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_REFERENCE, "Invalid leafref path \"%s\" - target is supposed"
Michal Vasko69730152020-10-09 16:30:07 +02007811 " to represent configuration data (as the leafref does), but it does not.", lref->path->expr);
Michal Vasko004d3152020-06-11 19:59:22 +02007812 return LY_EVALID;
7813 }
7814 }
7815
7816 /* store the target's type and check for circular chain of leafrefs */
7817 lref->realtype = ((struct lysc_node_leaf *)target)->type;
7818 for (type = lref->realtype; type && type->basetype == LY_TYPE_LEAFREF; type = ((struct lysc_type_leafref *)type)->realtype) {
7819 if (type == (struct lysc_type *)lref) {
7820 /* circular chain detected */
7821 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02007822 "Invalid leafref path \"%s\" - circular chain of leafrefs detected.", lref->path->expr);
Michal Vasko004d3152020-06-11 19:59:22 +02007823 return LY_EVALID;
7824 }
7825 }
7826
7827 /* check if leafref and its target are under common if-features */
7828 if (lys_compile_leafref_features_validate(node, target)) {
7829 LOGVAL(ctx->ctx, LY_VLOG_LYSC, node, LYVE_REFERENCE,
Michal Vasko69730152020-10-09 16:30:07 +02007830 "Invalid leafref path \"%s\" - set of features applicable to the leafref target is not a subset of"
7831 " features applicable to the leafref itself.", lref->path->expr);
Michal Vasko004d3152020-06-11 19:59:22 +02007832 return LY_EVALID;
7833 }
7834
7835 return LY_SUCCESS;
7836}
7837
7838static LY_ERR
Michal Vasko8d544252020-03-02 10:19:52 +01007839lys_compile_ietf_netconf_wd_annotation(struct lysc_ctx *ctx, struct lys_module *mod)
7840{
7841 struct lysc_ext_instance *ext;
7842 struct lysp_ext_instance *ext_p = NULL;
7843 struct lysp_stmt *stmt;
7844 const struct lys_module *ext_mod;
7845 LY_ERR ret = LY_SUCCESS;
7846
7847 /* create the parsed extension instance manually */
7848 ext_p = calloc(1, sizeof *ext_p);
7849 LY_CHECK_ERR_GOTO(!ext_p, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
Radek Krejci011e4aa2020-09-04 15:22:31 +02007850 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, "md:annotation", 0, &ext_p->name), cleanup);
7851 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, "default", 0, &ext_p->argument), cleanup);
Michal Vasko8d544252020-03-02 10:19:52 +01007852 ext_p->insubstmt = LYEXT_SUBSTMT_SELF;
7853 ext_p->insubstmt_index = 0;
7854
Radek Krejci87e25252020-09-15 13:28:31 +02007855 ext_p->child = stmt = calloc(1, sizeof *ext_p->child);
7856 LY_CHECK_ERR_GOTO(!stmt, LOGMEM(ctx->ctx); ret = LY_EMEM, cleanup);
Radek Krejci011e4aa2020-09-04 15:22:31 +02007857 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, "type", 0, &stmt->stmt), cleanup);
7858 LY_CHECK_GOTO(ret = lydict_insert(ctx->ctx, "boolean", 0, &stmt->arg), cleanup);
Michal Vasko8d544252020-03-02 10:19:52 +01007859 stmt->kw = LY_STMT_TYPE;
Michal Vasko8d544252020-03-02 10:19:52 +01007860
7861 /* allocate new extension instance */
7862 LY_ARRAY_NEW_GOTO(mod->ctx, mod->compiled->exts, ext, ret, cleanup);
7863
7864 /* manually get extension definition module */
7865 ext_mod = ly_ctx_get_module_latest(ctx->ctx, "ietf-yang-metadata");
7866
7867 /* compile the extension instance */
7868 LY_CHECK_GOTO(ret = lys_compile_ext(ctx, ext_p, ext, mod->compiled, LYEXT_PAR_MODULE, ext_mod), cleanup);
7869
7870cleanup:
7871 lysp_ext_instance_free(ctx->ctx, ext_p);
7872 free(ext_p);
7873 return ret;
7874}
7875
Michal Vasko7f45cf22020-10-01 12:49:44 +02007876/**
7877 * @brief Compile default value(s) for leaf or leaf-list expecting a complete compiled schema tree.
7878 *
7879 * @param[in] ctx Compile context.
7880 * @param[in] node Leaf or leaf-list to compile the default value(s) for.
7881 * @param[in] type Type of the default value.
7882 * @param[in] dflt Default value.
7883 * @param[in] dflt_mod Local module for @p dflt.
7884 * @param[in,out] storage Storage for the compiled default value.
7885 * @return LY_ERR value.
7886 */
Michal Vasko004d3152020-06-11 19:59:22 +02007887static LY_ERR
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007888lys_compile_unres_dflt(struct lysc_ctx *ctx, struct lysc_node *node, struct lysc_type *type, const char *dflt,
Radek Krejci0f969882020-08-21 16:56:47 +02007889 const struct lys_module *dflt_mod, struct lyd_value *storage)
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007890{
7891 LY_ERR ret;
7892 struct ly_err_item *err = NULL;
7893
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007894 ret = type->plugin->store(ctx->ctx, type, dflt, strlen(dflt), 0, LY_PREF_SCHEMA, (void *)dflt_mod, LYD_HINT_SCHEMA,
Michal Vasko69730152020-10-09 16:30:07 +02007895 node, storage, &err);
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007896 if (ret == LY_EINCOMPLETE) {
7897 /* we have no data so we will not be resolving it */
7898 ret = LY_SUCCESS;
7899 }
7900
7901 if (ret) {
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007902 ctx->path[0] = '\0';
7903 lysc_path(node, LYSC_PATH_LOG, ctx->path, LYSC_CTX_BUFSIZE);
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007904 if (err) {
7905 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02007906 "Invalid default - value does not fit the type (%s).", err->msg);
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007907 ly_err_free(err);
7908 } else {
7909 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko69730152020-10-09 16:30:07 +02007910 "Invalid default - value does not fit the type.");
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007911 }
7912 return ret;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007913 }
Michal Vaskofeca4fb2020-10-05 08:58:40 +02007914
7915 ++((struct lysc_type *)storage->realtype)->refcount;
7916 return LY_SUCCESS;
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007917}
7918
Michal Vasko7f45cf22020-10-01 12:49:44 +02007919/**
7920 * @brief Compile default value of a leaf expecting a complete compiled schema tree.
7921 *
7922 * @param[in] ctx Compile context.
7923 * @param[in] leaf Leaf that the default value is for.
7924 * @param[in] dflt Default value to compile.
7925 * @return LY_ERR value.
7926 */
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007927static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02007928lys_compile_unres_leaf_dlft(struct lysc_ctx *ctx, struct lysc_node_leaf *leaf, struct lysp_qname *dflt)
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007929{
7930 LY_ERR ret;
7931
7932 assert(!leaf->dflt);
7933
7934 if (leaf->flags & (LYS_MAND_TRUE | LYS_KEY)) {
7935 /* ignore default values for keys and mandatory leaves */
7936 return LY_SUCCESS;
7937 }
7938
7939 /* allocate the default value */
7940 leaf->dflt = calloc(1, sizeof *leaf->dflt);
7941 LY_CHECK_ERR_RET(!leaf->dflt, LOGMEM(ctx->ctx), LY_EMEM);
7942
7943 /* store the default value */
Michal Vasko7f45cf22020-10-01 12:49:44 +02007944 ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)leaf, leaf->type, dflt->str, dflt->mod, leaf->dflt);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007945 if (ret) {
7946 free(leaf->dflt);
7947 leaf->dflt = NULL;
7948 }
7949
7950 return ret;
7951}
7952
Michal Vasko7f45cf22020-10-01 12:49:44 +02007953/**
7954 * @brief Compile default values of a leaf-list expecting a complete compiled schema tree.
7955 *
7956 * @param[in] ctx Compile context.
7957 * @param[in] llist Leaf-list that the default value(s) are for.
7958 * @param[in] dflt Default value to compile, in case of a single value.
7959 * @param[in] dflts Sized array of default values, in case of more values.
7960 * @return LY_ERR value.
7961 */
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007962static LY_ERR
Michal Vasko7f45cf22020-10-01 12:49:44 +02007963lys_compile_unres_llist_dflts(struct lysc_ctx *ctx, struct lysc_node_leaflist *llist, struct lysp_qname *dflt,
7964 struct lysp_qname *dflts)
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007965{
7966 LY_ERR ret;
7967 LY_ARRAY_COUNT_TYPE orig_count, u, v;
7968
7969 assert(dflt || dflts);
7970
7971 if (llist->dflts) {
7972 /* there were already some defaults and we are adding new by deviations */
7973 assert(dflts);
7974 orig_count = LY_ARRAY_COUNT(llist->dflts);
7975 } else {
7976 orig_count = 0;
7977 }
7978
7979 /* allocate new items */
7980 if (dflts) {
7981 LY_ARRAY_CREATE_RET(ctx->ctx, llist->dflts, orig_count + LY_ARRAY_COUNT(dflts), LY_EMEM);
7982 } else {
7983 LY_ARRAY_CREATE_RET(ctx->ctx, llist->dflts, orig_count + 1, LY_EMEM);
7984 }
7985
7986 /* fill each new default value */
7987 if (dflts) {
7988 LY_ARRAY_FOR(dflts, u) {
7989 llist->dflts[orig_count + u] = calloc(1, sizeof **llist->dflts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007990 ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)llist, llist->type, dflts[u].str, dflts[u].mod,
7991 llist->dflts[orig_count + u]);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007992 LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count + u]), ret);
7993 LY_ARRAY_INCREMENT(llist->dflts);
7994 }
7995 } else {
7996 llist->dflts[orig_count] = calloc(1, sizeof **llist->dflts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02007997 ret = lys_compile_unres_dflt(ctx, (struct lysc_node *)llist, llist->type, dflt->str, dflt->mod,
7998 llist->dflts[orig_count]);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02007999 LY_CHECK_ERR_RET(ret, free(llist->dflts[orig_count]), ret);
8000 LY_ARRAY_INCREMENT(llist->dflts);
8001 }
8002
8003 /* check default value uniqueness */
8004 if (llist->flags & LYS_CONFIG_W) {
8005 /* configuration data values must be unique - so check the default values */
8006 for (u = orig_count; u < LY_ARRAY_COUNT(llist->dflts); ++u) {
8007 for (v = 0; v < u; ++v) {
8008 if (!llist->dflts[u]->realtype->plugin->compare(llist->dflts[u], llist->dflts[v])) {
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008009 lysc_update_path(ctx, llist->parent, llist->name);
8010 LOGVAL(ctx->ctx, LY_VLOG_STR, ctx->path, LYVE_SEMANTICS,
Michal Vasko7f45cf22020-10-01 12:49:44 +02008011 "Configuration leaf-list has multiple defaults of the same value \"%s\".",
8012 llist->dflts[u]->canonical);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008013 lysc_update_path(ctx, NULL, NULL);
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008014 return LY_EVALID;
8015 }
8016 }
8017 }
8018 }
8019
8020 return LY_SUCCESS;
8021}
8022
Michal Vasko7f45cf22020-10-01 12:49:44 +02008023/**
8024 * @brief Finish compilation of all the unres sets of a compile context.
8025 *
8026 * @param[in] ctx Compile context with unres sets.
8027 * @return LY_ERR value.
8028 */
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008029static LY_ERR
Michal Vasko004d3152020-06-11 19:59:22 +02008030lys_compile_unres(struct lysc_ctx *ctx)
8031{
8032 struct lysc_node *node;
8033 struct lysc_type *type, *typeiter;
8034 struct lysc_type_leafref *lref;
Michal Vasko7f45cf22020-10-01 12:49:44 +02008035 struct lysc_augment *aug;
8036 struct lysc_deviation *dev;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02008037 LY_ARRAY_COUNT_TYPE v;
Michal Vasko004d3152020-06-11 19:59:22 +02008038 uint32_t i;
8039
8040 /* for leafref, we need 2 rounds - first detects circular chain by storing the first referred type (which
8041 * can be also leafref, in case it is already resolved, go through the chain and check that it does not
8042 * point to the starting leafref type). The second round stores the first non-leafref type for later data validation. */
8043 for (i = 0; i < ctx->leafrefs.count; ++i) {
8044 node = ctx->leafrefs.objs[i];
8045 assert(node->nodetype & (LYS_LEAF | LYS_LEAFLIST));
8046 type = ((struct lysc_node_leaf *)node)->type;
8047 if (type->basetype == LY_TYPE_LEAFREF) {
8048 LY_CHECK_RET(lys_compile_unres_leafref(ctx, node, (struct lysc_type_leafref *)type));
8049 } else if (type->basetype == LY_TYPE_UNION) {
8050 LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
8051 if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
8052 lref = (struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v];
8053 LY_CHECK_RET(lys_compile_unres_leafref(ctx, node, lref));
8054 }
8055 }
8056 }
8057 }
8058 for (i = 0; i < ctx->leafrefs.count; ++i) {
8059 /* store pointer to the real type */
8060 type = ((struct lysc_node_leaf *)ctx->leafrefs.objs[i])->type;
8061 if (type->basetype == LY_TYPE_LEAFREF) {
Michal Vasko22df3f02020-08-24 13:29:22 +02008062 for (typeiter = ((struct lysc_type_leafref *)type)->realtype;
Michal Vasko004d3152020-06-11 19:59:22 +02008063 typeiter->basetype == LY_TYPE_LEAFREF;
Michal Vasko22df3f02020-08-24 13:29:22 +02008064 typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
8065 ((struct lysc_type_leafref *)type)->realtype = typeiter;
Michal Vasko004d3152020-06-11 19:59:22 +02008066 } else if (type->basetype == LY_TYPE_UNION) {
Michal Vasko22df3f02020-08-24 13:29:22 +02008067 LY_ARRAY_FOR(((struct lysc_type_union *)type)->types, v) {
8068 if (((struct lysc_type_union *)type)->types[v]->basetype == LY_TYPE_LEAFREF) {
8069 for (typeiter = ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype;
Michal Vasko004d3152020-06-11 19:59:22 +02008070 typeiter->basetype == LY_TYPE_LEAFREF;
Michal Vasko22df3f02020-08-24 13:29:22 +02008071 typeiter = ((struct lysc_type_leafref *)typeiter)->realtype) {}
8072 ((struct lysc_type_leafref *)((struct lysc_type_union *)type)->types[v])->realtype = typeiter;
Michal Vasko004d3152020-06-11 19:59:22 +02008073 }
8074 }
8075 }
8076 }
8077
8078 /* check xpath */
8079 for (i = 0; i < ctx->xpath.count; ++i) {
8080 LY_CHECK_RET(lys_compile_unres_xpath(ctx, ctx->xpath.objs[i]));
8081 }
8082
8083 /* finish incomplete default values compilation */
8084 for (i = 0; i < ctx->dflts.count; ++i) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02008085 struct lysc_unres_dflt *r = ctx->dflts.objs[i];
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008086 if (r->leaf->nodetype == LYS_LEAF) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02008087 LY_CHECK_RET(lys_compile_unres_leaf_dlft(ctx, r->leaf, r->dflt));
Michal Vaskoba99a3e2020-08-18 15:50:05 +02008088 } else {
Michal Vasko7f45cf22020-10-01 12:49:44 +02008089 LY_CHECK_RET(lys_compile_unres_llist_dflts(ctx, r->llist, r->dflt, r->dflts));
Michal Vasko004d3152020-06-11 19:59:22 +02008090 }
Michal Vasko004d3152020-06-11 19:59:22 +02008091 }
8092
Michal Vasko7f45cf22020-10-01 12:49:44 +02008093 /* check that all augments were applied */
8094 for (i = 0; i < ctx->augs.count; ++i) {
8095 aug = ctx->augs.objs[i];
8096 LOGVAL(ctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
8097 "Augment target node \"%s\" from module \"%s\" was not found.", aug->nodeid->expr,
8098 aug->nodeid_mod->name);
8099 }
8100 if (ctx->augs.count) {
8101 return LY_ENOTFOUND;
8102 }
8103
8104 /* check that all deviations were applied */
8105 for (i = 0; i < ctx->devs.count; ++i) {
8106 dev = ctx->devs.objs[i];
8107 LOGVAL(ctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE,
8108 "Deviation(s) target node \"%s\" from module \"%s\" was not found.", dev->nodeid->expr,
8109 dev->nodeid_mod->name);
8110 }
8111 if (ctx->devs.count) {
8112 return LY_ENOTFOUND;
8113 }
8114
8115 return LY_SUCCESS;
8116}
8117
Michal Vasko89b5c072020-10-06 13:52:44 +02008118void
8119lys_precompile_augments_deviations_revert(struct ly_ctx *ctx, const struct lys_module *mod)
Michal Vasko7f45cf22020-10-01 12:49:44 +02008120{
8121 uint32_t i;
8122 LY_ARRAY_COUNT_TYPE u, count;
8123 struct lys_module *m;
8124
Michal Vasko89b5c072020-10-06 13:52:44 +02008125 for (i = 0; i < ctx->list.count; ++i) {
8126 m = ctx->list.objs[i];
Michal Vasko7f45cf22020-10-01 12:49:44 +02008127
8128 if (m->augmented_by) {
8129 count = LY_ARRAY_COUNT(m->augmented_by);
8130 for (u = 0; u < count; ++u) {
8131 if (m->augmented_by[u] == mod) {
8132 /* keep the order */
8133 if (u < count - 1) {
8134 memmove(m->augmented_by + u, m->augmented_by + u + 1, (count - u) * sizeof *m->augmented_by);
8135 }
8136 LY_ARRAY_DECREMENT(m->augmented_by);
8137 break;
8138 }
8139 }
8140 if (!LY_ARRAY_COUNT(m->augmented_by)) {
8141 LY_ARRAY_FREE(m->augmented_by);
8142 m->augmented_by = NULL;
8143 }
8144 }
8145
8146 if (m->deviated_by) {
8147 count = LY_ARRAY_COUNT(m->deviated_by);
8148 for (u = 0; u < count; ++u) {
8149 if (m->deviated_by[u] == mod) {
8150 /* keep the order */
8151 if (u < count - 1) {
8152 memmove(m->deviated_by + u, m->deviated_by + u + 1, (count - u) * sizeof *m->deviated_by);
8153 }
8154 LY_ARRAY_DECREMENT(m->deviated_by);
8155 break;
8156 }
8157 }
8158 if (!LY_ARRAY_COUNT(m->deviated_by)) {
8159 LY_ARRAY_FREE(m->deviated_by);
8160 m->deviated_by = NULL;
8161 }
8162 }
8163 }
8164}
8165
8166/**
8167 * @brief Compile features in the current module and all its submodules.
8168 *
8169 * @param[in] ctx Compile context.
8170 * @return LY_ERR value.
8171 */
8172static LY_ERR
8173lys_compile_features(struct lysc_ctx *ctx)
8174{
8175 struct lysp_submodule *submod;
8176 LY_ARRAY_COUNT_TYPE u, v;
8177
8178 if (!ctx->mod->features) {
8179 /* features are compiled directly into the module structure,
8180 * but it must be done in two steps to allow forward references (via if-feature) between the features themselves */
8181 LY_CHECK_RET(lys_feature_precompile(ctx, NULL, NULL, ctx->mod->parsed->features, &ctx->mod->features));
8182 LY_ARRAY_FOR(ctx->mod->parsed->includes, v) {
8183 submod = ctx->mod->parsed->includes[v].submodule;
8184 LY_CHECK_RET(lys_feature_precompile(ctx, NULL, NULL, submod->features, &ctx->mod->features));
8185 }
8186 }
8187
8188 /* finish feature compilation, not only for the main module, but also for the submodules.
8189 * Due to possible forward references, it must be done when all the features (including submodules)
8190 * are present. */
8191 LY_ARRAY_FOR(ctx->mod->parsed->features, u) {
8192 LY_CHECK_RET(lys_feature_precompile_finish(ctx, &ctx->mod->parsed->features[u], ctx->mod->features));
8193 }
8194
8195 lysc_update_path(ctx, NULL, "{submodule}");
8196 LY_ARRAY_FOR(ctx->mod->parsed->includes, v) {
8197 submod = ctx->mod->parsed->includes[v].submodule;
8198
8199 lysc_update_path(ctx, NULL, submod->name);
8200 LY_ARRAY_FOR(submod->features, u) {
8201 LY_CHECK_RET(lys_feature_precompile_finish(ctx, &submod->features[u], ctx->mod->features));
8202 }
8203 lysc_update_path(ctx, NULL, NULL);
8204 }
8205 lysc_update_path(ctx, NULL, NULL);
8206
8207 return LY_SUCCESS;
8208}
8209
8210/**
8211 * @brief Compile identites in the current module and all its submodules.
8212 *
8213 * @param[in] ctx Compile context.
8214 * @return LY_ERR value.
8215 */
8216static LY_ERR
8217lys_compile_identities(struct lysc_ctx *ctx)
8218{
8219 struct lysp_submodule *submod;
8220 LY_ARRAY_COUNT_TYPE u;
8221
8222 if (!ctx->mod->identities) {
8223 LY_CHECK_RET(lys_identity_precompile(ctx, NULL, NULL, ctx->mod->parsed->identities, &ctx->mod->identities));
8224 LY_ARRAY_FOR(ctx->mod->parsed->includes, u) {
8225 submod = ctx->mod->parsed->includes[u].submodule;
8226 LY_CHECK_RET(lys_identity_precompile(ctx, NULL, NULL, submod->identities, &ctx->mod->identities));
8227 }
8228 }
8229
8230 if (ctx->mod->parsed->identities) {
8231 LY_CHECK_RET(lys_compile_identities_derived(ctx, ctx->mod->parsed->identities, ctx->mod->identities));
8232 }
8233 lysc_update_path(ctx, NULL, "{submodule}");
8234 LY_ARRAY_FOR(ctx->mod->parsed->includes, u) {
8235
8236 submod = ctx->mod->parsed->includes[u].submodule;
8237 if (submod->identities) {
8238 lysc_update_path(ctx, NULL, submod->name);
8239 LY_CHECK_RET(lys_compile_identities_derived(ctx, submod->identities, ctx->mod->identities));
8240 lysc_update_path(ctx, NULL, NULL);
8241 }
8242 }
8243 lysc_update_path(ctx, NULL, NULL);
8244
Michal Vasko004d3152020-06-11 19:59:22 +02008245 return LY_SUCCESS;
8246}
8247
Radek Krejci19a96102018-11-15 13:38:09 +01008248LY_ERR
Michal Vasko7a0b0762020-09-02 16:37:01 +02008249lys_compile(struct lys_module *mod, uint32_t options)
Radek Krejci19a96102018-11-15 13:38:09 +01008250{
8251 struct lysc_ctx ctx = {0};
8252 struct lysc_module *mod_c;
8253 struct lysp_module *sp;
Michal Vasko7f45cf22020-10-01 12:49:44 +02008254 struct lysp_submodule *submod;
8255 struct lysp_node *pnode;
Radek Krejcif2de0ed2019-05-02 14:13:18 +02008256 struct lysp_grp *grps;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02008257 LY_ARRAY_COUNT_TYPE u, v;
Radek Krejci7eb54ba2020-05-18 16:30:04 +02008258 uint32_t i;
Radek Krejcid05cbd92018-12-05 14:26:40 +01008259 LY_ERR ret = LY_SUCCESS;
Radek Krejci19a96102018-11-15 13:38:09 +01008260
Michal Vasko7a0b0762020-09-02 16:37:01 +02008261 LY_CHECK_ARG_RET(NULL, mod, mod->parsed, !mod->compiled, mod->ctx, LY_EINVAL);
Radek Krejci096235c2019-01-11 11:12:19 +01008262
Michal Vasko7a0b0762020-09-02 16:37:01 +02008263 if (!mod->implemented) {
Radek Krejci096235c2019-01-11 11:12:19 +01008264 /* just imported modules are not compiled */
8265 return LY_SUCCESS;
8266 }
8267
Michal Vasko7f45cf22020-10-01 12:49:44 +02008268 /* context will be changed */
8269 ++mod->ctx->module_set_id;
8270
Michal Vasko7a0b0762020-09-02 16:37:01 +02008271 sp = mod->parsed;
Radek Krejci19a96102018-11-15 13:38:09 +01008272
Michal Vasko7a0b0762020-09-02 16:37:01 +02008273 ctx.ctx = mod->ctx;
8274 ctx.mod = mod;
8275 ctx.mod_def = mod;
Radek Krejciec4da802019-05-02 13:02:41 +02008276 ctx.options = options;
Radek Krejci327de162019-06-14 12:52:07 +02008277 ctx.path_len = 1;
8278 ctx.path[0] = '/';
Radek Krejci19a96102018-11-15 13:38:09 +01008279
Michal Vasko7a0b0762020-09-02 16:37:01 +02008280 mod->compiled = mod_c = calloc(1, sizeof *mod_c);
8281 LY_CHECK_ERR_RET(!mod_c, LOGMEM(mod->ctx), LY_EMEM);
8282 mod_c->mod = mod;
Radek Krejci19a96102018-11-15 13:38:09 +01008283
Michal Vasko7f45cf22020-10-01 12:49:44 +02008284 /* process imports */
Michal Vasko7c8439f2020-08-05 13:25:19 +02008285 LY_ARRAY_FOR(sp->imports, u) {
8286 LY_CHECK_GOTO(ret = lys_compile_import(&ctx, &sp->imports[u]), error);
8287 }
Radek Krejci0935f412019-08-20 16:15:18 +02008288
Michal Vasko7f45cf22020-10-01 12:49:44 +02008289 /* features */
8290 LY_CHECK_GOTO(ret = lys_compile_features(&ctx), error);
Radek Krejci14915cc2020-09-14 17:28:13 +02008291
8292 /* identities, work similarly to features with the precompilation */
Michal Vasko7f45cf22020-10-01 12:49:44 +02008293 LY_CHECK_GOTO(ret = lys_compile_identities(&ctx), error);
8294
8295 /* augments and deviations */
8296 LY_CHECK_GOTO(ret = lys_precompile_augments_deviations(&ctx), error);
8297
8298 /* compile augments and deviations of our module from other modules so they can be applied during compilation */
8299 LY_CHECK_GOTO(ret = lys_precompile_own_augments(&ctx), error);
8300 LY_CHECK_GOTO(ret = lys_precompile_own_deviations(&ctx), error);
Radek Krejci19a96102018-11-15 13:38:09 +01008301
Radek Krejci95710c92019-02-11 15:49:55 +01008302 /* data nodes */
Michal Vasko7f45cf22020-10-01 12:49:44 +02008303 LY_LIST_FOR(sp->data, pnode) {
8304 LY_CHECK_GOTO(ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL), error);
Radek Krejci19a96102018-11-15 13:38:09 +01008305 }
Radek Krejci95710c92019-02-11 15:49:55 +01008306
Michal Vasko7f45cf22020-10-01 12:49:44 +02008307 /* top-level RPCs and notifications */
8308 COMPILE_OP_ARRAY_GOTO(&ctx, sp->rpcs, mod_c->rpcs, NULL, u, lys_compile_action, 0, ret, error);
8309 COMPILE_OP_ARRAY_GOTO(&ctx, sp->notifs, mod_c->notifs, NULL, u, lys_compile_notif, 0, ret, error);
Radek Krejciccd20f12019-02-15 14:12:27 +01008310
Michal Vasko7f45cf22020-10-01 12:49:44 +02008311 /* extension instances */
Radek Krejci0935f412019-08-20 16:15:18 +02008312 COMPILE_EXTS_GOTO(&ctx, sp->exts, mod_c->exts, mod_c, LYEXT_PAR_MODULE, ret, error);
Radek Krejci19a96102018-11-15 13:38:09 +01008313
Michal Vasko7f45cf22020-10-01 12:49:44 +02008314 /* the same for submodules */
8315 LY_ARRAY_FOR(sp->includes, u) {
8316 submod = sp->includes[u].submodule;
8317 LY_LIST_FOR(submod->data, pnode) {
8318 ret = lys_compile_node(&ctx, pnode, NULL, 0, NULL);
8319 LY_CHECK_GOTO(ret, error);
8320 }
8321
8322 COMPILE_OP_ARRAY_GOTO(&ctx, submod->rpcs, mod_c->rpcs, NULL, v, lys_compile_action, 0, ret, error);
8323 COMPILE_OP_ARRAY_GOTO(&ctx, submod->notifs, mod_c->notifs, NULL, v, lys_compile_notif, 0, ret, error);
8324
8325 COMPILE_EXTS_GOTO(&ctx, submod->exts, mod_c->exts, mod_c, LYEXT_PAR_MODULE, ret, error);
8326 }
8327
Michal Vasko004d3152020-06-11 19:59:22 +02008328 /* finish compilation for all unresolved items in the context */
8329 LY_CHECK_GOTO(ret = lys_compile_unres(&ctx), error);
Radek Krejci474f9b82019-07-24 11:36:37 +02008330
Radek Krejcif2de0ed2019-05-02 14:13:18 +02008331 /* validate non-instantiated groupings from the parsed schema,
8332 * without it we would accept even the schemas with invalid grouping specification */
8333 ctx.options |= LYSC_OPT_GROUPING;
8334 LY_ARRAY_FOR(sp->groupings, u) {
8335 if (!(sp->groupings[u].flags & LYS_USED_GRP)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02008336 LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &sp->groupings[u]), error);
Radek Krejcif2de0ed2019-05-02 14:13:18 +02008337 }
8338 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02008339 LY_LIST_FOR(sp->data, pnode) {
8340 grps = (struct lysp_grp *)lysp_node_groupings(pnode);
Radek Krejcif2de0ed2019-05-02 14:13:18 +02008341 LY_ARRAY_FOR(grps, u) {
8342 if (!(grps[u].flags & LYS_USED_GRP)) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02008343 LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &grps[u]), error);
Radek Krejcif2de0ed2019-05-02 14:13:18 +02008344 }
8345 }
8346 }
Michal Vasko7f45cf22020-10-01 12:49:44 +02008347 LY_ARRAY_FOR(sp->includes, u) {
8348 submod = sp->includes[u].submodule;
8349 LY_ARRAY_FOR(submod->groupings, u) {
8350 if (!(submod->groupings[u].flags & LYS_USED_GRP)) {
8351 LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &submod->groupings[u]), error);
8352 }
8353 }
8354 LY_LIST_FOR(submod->data, pnode) {
8355 grps = (struct lysp_grp *)lysp_node_groupings(pnode);
8356 LY_ARRAY_FOR(grps, u) {
8357 if (!(grps[u].flags & LYS_USED_GRP)) {
8358 LY_CHECK_GOTO(ret = lys_compile_grouping(&ctx, pnode, &grps[u]), error);
8359 }
8360 }
8361 }
Radek Krejci474f9b82019-07-24 11:36:37 +02008362 }
8363
Michal Vasko8d544252020-03-02 10:19:52 +01008364#if 0
8365 /* hack for NETCONF's edit-config's operation attribute. It is not defined in the schema, but since libyang
8366 * implements YANG metadata (annotations), we need its definition. Because the ietf-netconf schema is not the
8367 * internal part of libyang, we cannot add the annotation into the schema source, but we do it here to have
8368 * the anotation definitions available in the internal schema structure. */
8369 if (ly_strequal(mod->name, "ietf-netconf", 0)) {
8370 if (lyp_add_ietf_netconf_annotations(mod)) {
8371 lys_free(mod, NULL, 1, 1);
8372 return NULL;
8373 }
8374 }
8375#endif
8376
8377 /* add ietf-netconf-with-defaults "default" metadata to the compiled module */
Michal Vasko7a0b0762020-09-02 16:37:01 +02008378 if (!strcmp(mod->name, "ietf-netconf-with-defaults")) {
8379 LY_CHECK_GOTO(ret = lys_compile_ietf_netconf_wd_annotation(&ctx, mod), error);
Michal Vasko8d544252020-03-02 10:19:52 +01008380 }
8381
Michal Vasko7f45cf22020-10-01 12:49:44 +02008382 /* there can be no leftover deviations */
8383 LY_CHECK_ERR_GOTO(ctx.devs.count, LOGINT(ctx.ctx); ret = LY_EINT, error);
8384
8385 for (i = 0; i < ctx.dflts.count; ++i) {
8386 lysc_unres_dflt_free(ctx.ctx, ctx.dflts.objs[i]);
8387 }
8388 ly_set_erase(&ctx.dflts, NULL);
Michal Vasko004d3152020-06-11 19:59:22 +02008389 ly_set_erase(&ctx.xpath, NULL);
8390 ly_set_erase(&ctx.leafrefs, NULL);
Radek Krejcie86bf772018-12-14 11:39:53 +01008391 ly_set_erase(&ctx.groupings, NULL);
Radek Krejci99b5b2a2019-04-30 16:57:04 +02008392 ly_set_erase(&ctx.tpdf_chain, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +02008393 ly_set_erase(&ctx.augs, NULL);
8394 ly_set_erase(&ctx.devs, NULL);
8395 ly_set_erase(&ctx.uses_augs, NULL);
8396 ly_set_erase(&ctx.uses_rfns, NULL);
Radek Krejcia3045382018-11-22 14:30:31 +01008397
Radek Krejciec4da802019-05-02 13:02:41 +02008398 if (ctx.options & LYSC_OPT_FREE_SP) {
Michal Vasko7a0b0762020-09-02 16:37:01 +02008399 lysp_module_free(mod->parsed);
8400 mod->parsed = NULL;
Radek Krejci19a96102018-11-15 13:38:09 +01008401 }
8402
Radek Krejci19a96102018-11-15 13:38:09 +01008403 return LY_SUCCESS;
8404
8405error:
Michal Vasko89b5c072020-10-06 13:52:44 +02008406 lys_precompile_augments_deviations_revert(ctx.ctx, mod);
Michal Vasko7a0b0762020-09-02 16:37:01 +02008407 lys_feature_precompile_revert(&ctx, mod);
Michal Vasko7f45cf22020-10-01 12:49:44 +02008408 for (i = 0; i < ctx.dflts.count; ++i) {
8409 lysc_unres_dflt_free(ctx.ctx, ctx.dflts.objs[i]);
8410 }
8411 ly_set_erase(&ctx.dflts, NULL);
Michal Vasko004d3152020-06-11 19:59:22 +02008412 ly_set_erase(&ctx.xpath, NULL);
8413 ly_set_erase(&ctx.leafrefs, NULL);
Radek Krejcie86bf772018-12-14 11:39:53 +01008414 ly_set_erase(&ctx.groupings, NULL);
Radek Krejci99b5b2a2019-04-30 16:57:04 +02008415 ly_set_erase(&ctx.tpdf_chain, NULL);
Michal Vasko7f45cf22020-10-01 12:49:44 +02008416 for (i = 0; i < ctx.augs.count; ++i) {
8417 lysc_augment_free(ctx.ctx, ctx.augs.objs[i]);
8418 }
8419 ly_set_erase(&ctx.augs, NULL);
8420 for (i = 0; i < ctx.devs.count; ++i) {
8421 lysc_deviation_free(ctx.ctx, ctx.devs.objs[i]);
8422 }
8423 ly_set_erase(&ctx.devs, NULL);
8424 for (i = 0; i < ctx.uses_augs.count; ++i) {
8425 lysc_augment_free(ctx.ctx, ctx.uses_augs.objs[i]);
8426 }
8427 ly_set_erase(&ctx.uses_augs, NULL);
8428 for (i = 0; i < ctx.uses_rfns.count; ++i) {
8429 lysc_refine_free(ctx.ctx, ctx.uses_rfns.objs[i]);
8430 }
8431 ly_set_erase(&ctx.uses_rfns, NULL);
Radek Krejci19a96102018-11-15 13:38:09 +01008432 lysc_module_free(mod_c, NULL);
Michal Vasko7a0b0762020-09-02 16:37:01 +02008433 mod->compiled = NULL;
Radek Krejci95710c92019-02-11 15:49:55 +01008434
Radek Krejci19a96102018-11-15 13:38:09 +01008435 return ret;
8436}