blob: 71449ba7b9a72002bf98f26ce04d434ab36da467 [file] [log] [blame]
Radek Krejci0935f412019-08-20 16:15:18 +02001/**
2 * @file plugins_exts.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskoddd76592022-01-17 13:34:48 +01004 * @author Michal Vasko <mvasko@cesnet.cz>
5 * @brief helper functions for extension plugins
Radek Krejci0935f412019-08-20 16:15:18 +02006 *
Michal Vasko94ccc592024-09-02 14:53:34 +02007 * Copyright (c) 2019 - 2024 CESNET, z.s.p.o.
Radek Krejci0935f412019-08-20 16:15:18 +02008 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
Radek Krejci0935f412019-08-20 16:15:18 +020015
16#include "plugins_exts.h"
17
Michal Vasko193dacd2022-10-13 08:43:05 +020018#include <assert.h>
Radek Krejci47fab892020-11-05 17:02:41 +010019#include <stdint.h>
Michal Vasko193dacd2022-10-13 08:43:05 +020020#include <stdlib.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020021
Michal Vasko193dacd2022-10-13 08:43:05 +020022#include "dict.h"
Michal Vasko8f702ee2024-02-20 15:44:24 +010023#include "ly_common.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020024#include "parser_internal.h"
Radek Krejcif8d7f9a2021-03-10 14:32:36 +010025#include "printer_internal.h"
Radek Krejci5f9a3672021-03-05 21:35:22 +010026#include "schema_compile.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020027#include "schema_compile_amend.h"
28#include "schema_compile_node.h"
29#include "schema_features.h"
30#include "tree_schema_internal.h"
31
32LIBYANG_API_DEF const struct lysp_module *
33lyplg_ext_parse_get_cur_pmod(const struct lysp_ctx *pctx)
34{
35 return PARSER_CUR_PMOD(pctx);
36}
37
38LIBYANG_API_DEF LY_ERR
39lyplg_ext_parse_extension_instance(struct lysp_ctx *pctx, struct lysp_ext_instance *ext)
40{
41 LY_ERR rc = LY_SUCCESS;
42 LY_ARRAY_COUNT_TYPE u;
43 struct lysp_stmt *stmt;
44
45 /* check for invalid substatements */
46 LY_LIST_FOR(ext->child, stmt) {
47 if (stmt->flags & (LYS_YIN_ATTR | LYS_YIN_ARGUMENT)) {
48 continue;
49 }
50 LY_ARRAY_FOR(ext->substmts, u) {
51 if (ext->substmts[u].stmt == stmt->kw) {
52 break;
53 }
54 }
55 if (u == LY_ARRAY_COUNT(ext->substmts)) {
56 LOGVAL(PARSER_CTX(pctx), LYVE_SYNTAX_YANG, "Invalid keyword \"%s\" as a child of \"%s%s%s\" extension instance.",
57 stmt->stmt, ext->name, ext->argument ? " " : "", ext->argument ? ext->argument : "");
58 rc = LY_EVALID;
59 goto cleanup;
60 }
61 }
62
63 /* parse all the known statements */
64 LY_ARRAY_FOR(ext->substmts, u) {
65 LY_LIST_FOR(ext->child, stmt) {
66 if (ext->substmts[u].stmt != stmt->kw) {
67 continue;
68 }
69
70 if ((rc = lys_parse_ext_instance_stmt(pctx, &ext->substmts[u], stmt))) {
71 goto cleanup;
72 }
73 }
74 }
75
76cleanup:
77 return rc;
78}
79
80/**
81 * @brief Compile an instance extension statement.
82 *
83 * @param[in] ctx Compile context.
Michal Vaskoa6bab1e2024-09-05 12:24:20 +020084 * @param[in] parsed_p Parsed ext instance substatement structure.
Michal Vasko193dacd2022-10-13 08:43:05 +020085 * @param[in] ext Compiled ext instance.
86 * @param[in] substmt Compled ext instance substatement info.
Michal Vasko193dacd2022-10-13 08:43:05 +020087 * @return LY_ERR value.
88 */
89static LY_ERR
Michal Vaskoa6bab1e2024-09-05 12:24:20 +020090lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, void **parsed_p, struct lysc_ext_instance *ext,
Michal Vaskoa0ba01e2022-10-19 13:26:57 +020091 struct lysc_ext_substmt *substmt)
Michal Vasko193dacd2022-10-13 08:43:05 +020092{
93 LY_ERR rc = LY_SUCCESS;
94 ly_bool length_restr = 0;
95 LY_DATA_TYPE basetype;
96
Michal Vaskoa6bab1e2024-09-05 12:24:20 +020097 assert(*parsed_p);
Michal Vaskod595eff2023-02-20 11:29:28 +010098
Michal Vasko193dacd2022-10-13 08:43:05 +020099 /* compilation wthout any storage */
100 if (substmt->stmt == LY_STMT_IF_FEATURE) {
101 ly_bool enabled;
102
103 /* evaluate */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200104 LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, *parsed_p, &enabled), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200105 if (!enabled) {
106 /* it is disabled, remove the whole extension instance */
107 rc = LY_ENOT;
108 }
109 }
110
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200111 if (!substmt->storage_p) {
Michal Vaskod595eff2023-02-20 11:29:28 +0100112 /* nothing to store */
Michal Vasko193dacd2022-10-13 08:43:05 +0200113 goto cleanup;
114 }
115
116 switch (substmt->stmt) {
117 case LY_STMT_NOTIFICATION:
118 case LY_STMT_INPUT:
119 case LY_STMT_OUTPUT:
120 case LY_STMT_ACTION:
121 case LY_STMT_RPC:
122 case LY_STMT_ANYDATA:
123 case LY_STMT_ANYXML:
124 case LY_STMT_CASE:
125 case LY_STMT_CHOICE:
126 case LY_STMT_CONTAINER:
127 case LY_STMT_LEAF:
128 case LY_STMT_LEAF_LIST:
129 case LY_STMT_LIST:
130 case LY_STMT_USES: {
131 const uint16_t flags;
132 struct lysp_node *pnodes, *pnode;
133 struct lysc_node *node;
134
Michal Vaskofbd037c2022-11-08 10:34:20 +0100135 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200136 pnodes = *parsed_p;
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200137
138 /* compile nodes */
139 LY_LIST_FOR(pnodes, pnode) {
140 if (pnode->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
141 /* manual compile */
142 node = calloc(1, sizeof(struct lysc_node_action_inout));
143 LY_CHECK_ERR_GOTO(!node, LOGMEM(ctx->ctx); rc = LY_EMEM, cleanup);
144 LY_CHECK_GOTO(rc = lys_compile_node_action_inout(ctx, pnode, node), cleanup);
145 LY_CHECK_GOTO(rc = lys_compile_node_connect(ctx, NULL, node), cleanup);
146 } else {
147 /* ctx->ext substatement storage is used as the document root */
148 LY_CHECK_GOTO(rc = lys_compile_node(ctx, pnode, NULL, flags, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200149 }
150 }
151 break;
152 }
153 case LY_STMT_ARGUMENT:
154 case LY_STMT_CONTACT:
155 case LY_STMT_DESCRIPTION:
156 case LY_STMT_ERROR_APP_TAG:
157 case LY_STMT_ERROR_MESSAGE:
158 case LY_STMT_KEY:
159 case LY_STMT_MODIFIER:
160 case LY_STMT_NAMESPACE:
161 case LY_STMT_ORGANIZATION:
162 case LY_STMT_PRESENCE:
163 case LY_STMT_REFERENCE:
164 case LY_STMT_UNITS:
165 /* just make a copy */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200166 LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, *parsed_p, 0, (const char **)substmt->storage_p), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200167 break;
168
169 case LY_STMT_BIT:
170 basetype = LY_TYPE_BITS;
171 /* fallthrough */
172 case LY_STMT_ENUM:
173 if (substmt->stmt == LY_STMT_ENUM) {
174 basetype = LY_TYPE_ENUM;
175 }
176
177 /* compile */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200178 rc = lys_compile_type_enums(ctx, *parsed_p, basetype, NULL, (struct lysc_type_bitenum_item **)substmt->storage_p);
Michal Vasko708a8bf2024-06-13 09:44:51 +0200179 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200180 break;
181
182 case LY_STMT_CONFIG: {
Michal Vasko118eb522023-01-12 11:04:51 +0100183 uint16_t flags;
Michal Vasko193dacd2022-10-13 08:43:05 +0200184
185 if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) {
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200186 memcpy(&flags, parsed_p, 2);
Michal Vasko193dacd2022-10-13 08:43:05 +0200187 if (flags & LYS_CONFIG_MASK) {
188 /* explicitly set */
Michal Vasko118eb522023-01-12 11:04:51 +0100189 flags |= LYS_SET_CONFIG;
Michal Vasko193dacd2022-10-13 08:43:05 +0200190 } else if (ext->parent_stmt & LY_STMT_DATA_NODE_MASK) {
191 /* inherit */
Michal Vasko118eb522023-01-12 11:04:51 +0100192 flags = ((struct lysc_node *)ext->parent)->flags & LYS_CONFIG_MASK;
Michal Vasko193dacd2022-10-13 08:43:05 +0200193 } else {
194 /* default config */
Michal Vasko118eb522023-01-12 11:04:51 +0100195 flags = LYS_CONFIG_W;
Michal Vasko193dacd2022-10-13 08:43:05 +0200196 }
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200197 memcpy(substmt->storage_p, &flags, 2);
Michal Vasko193dacd2022-10-13 08:43:05 +0200198 } /* else leave zero */
199 break;
200 }
201 case LY_STMT_MUST: {
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200202 const struct lysp_restr *restrs = *parsed_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200203
204 /* sized array */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200205 COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)substmt->storage_p, lys_compile_must, rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200206 break;
207 }
208 case LY_STMT_WHEN: {
209 const uint16_t flags;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200210 const struct lysp_when *when = *parsed_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200211
212 /* read compiled status */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100213 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
Michal Vasko193dacd2022-10-13 08:43:05 +0200214
215 /* compile */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200216 LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, (struct lysc_when **)substmt->storage_p), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200217 break;
218 }
219 case LY_STMT_FRACTION_DIGITS:
220 case LY_STMT_REQUIRE_INSTANCE:
221 /* just make a copy */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200222 memcpy(substmt->storage_p, parsed_p, 1);
Michal Vasko193dacd2022-10-13 08:43:05 +0200223 break;
224
225 case LY_STMT_MANDATORY:
226 case LY_STMT_ORDERED_BY:
227 case LY_STMT_STATUS:
228 /* just make a copy */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200229 memcpy(substmt->storage_p, parsed_p, 2);
Michal Vasko193dacd2022-10-13 08:43:05 +0200230 break;
231
232 case LY_STMT_MAX_ELEMENTS:
233 case LY_STMT_MIN_ELEMENTS:
234 /* just make a copy */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200235 memcpy(substmt->storage_p, parsed_p, 4);
Michal Vasko193dacd2022-10-13 08:43:05 +0200236 break;
237
238 case LY_STMT_POSITION:
239 case LY_STMT_VALUE:
240 /* just make a copy */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200241 memcpy(substmt->storage_p, parsed_p, 8);
Michal Vasko193dacd2022-10-13 08:43:05 +0200242 break;
243
244 case LY_STMT_IDENTITY:
245 /* compile */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200246 rc = lys_identity_precompile(ctx, NULL, NULL, *parsed_p, (struct lysc_ident **)substmt->storage_p);
Michal Vasko708a8bf2024-06-13 09:44:51 +0200247 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200248 break;
249
250 case LY_STMT_LENGTH:
251 length_restr = 1;
252 /* fallthrough */
253 case LY_STMT_RANGE:
254 /* compile, use uint64 default range */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200255 rc = lys_compile_type_range(ctx, *parsed_p, LY_TYPE_UINT64, length_restr, 0, NULL, (struct lysc_range **)substmt->storage_p);
Michal Vasko708a8bf2024-06-13 09:44:51 +0200256 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200257 break;
258
259 case LY_STMT_PATTERN:
260 /* compile */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200261 rc = lys_compile_type_patterns(ctx, *parsed_p, NULL, (struct lysc_pattern ***)substmt->storage_p);
Michal Vasko708a8bf2024-06-13 09:44:51 +0200262 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200263 break;
264
265 case LY_STMT_TYPE: {
266 const uint16_t flags;
267 const char *units;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200268 const struct lysp_type *ptype = *parsed_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200269
270 /* read compiled info */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100271 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
272 lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units);
Michal Vasko193dacd2022-10-13 08:43:05 +0200273
274 /* compile */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200275 rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, (struct lysc_type **)substmt->storage_p, &units, NULL);
Michal Vasko708a8bf2024-06-13 09:44:51 +0200276 LY_CHECK_GOTO(rc, cleanup);
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200277 LY_ATOMIC_INC_BARRIER((*(struct lysc_type **)substmt->storage_p)->refcount);
Michal Vasko193dacd2022-10-13 08:43:05 +0200278 break;
279 }
280 case LY_STMT_EXTENSION_INSTANCE: {
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200281 struct lysp_ext_instance *extps = *parsed_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200282
283 /* compile sized array */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200284 COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)substmt->storage_p, ext, rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200285 break;
286 }
287 case LY_STMT_AUGMENT:
288 case LY_STMT_GROUPING:
289 case LY_STMT_BASE:
290 case LY_STMT_BELONGS_TO:
291 case LY_STMT_DEFAULT:
292 case LY_STMT_DEVIATE:
293 case LY_STMT_DEVIATION:
294 case LY_STMT_EXTENSION:
295 case LY_STMT_FEATURE:
296 case LY_STMT_IF_FEATURE:
297 case LY_STMT_IMPORT:
298 case LY_STMT_INCLUDE:
299 case LY_STMT_MODULE:
300 case LY_STMT_PATH:
301 case LY_STMT_PREFIX:
302 case LY_STMT_REFINE:
303 case LY_STMT_REVISION:
304 case LY_STMT_REVISION_DATE:
305 case LY_STMT_SUBMODULE:
306 case LY_STMT_TYPEDEF:
307 case LY_STMT_UNIQUE:
308 case LY_STMT_YANG_VERSION:
309 case LY_STMT_YIN_ELEMENT:
310 LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" compilation is not supported.", lyplg_ext_stmt2str(substmt->stmt));
311 rc = LY_EVALID;
312 goto cleanup;
313
314 default:
315 LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension "
316 "(found in \"%s%s%s\") substatement.", lyplg_ext_stmt2str(substmt->stmt), ext->def->name,
317 ext->argument ? " " : "", ext->argument ? ext->argument : "");
318 rc = LY_EVALID;
319 goto cleanup;
320 }
321
322cleanup:
323 return rc;
324}
325
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200326LIBYANG_API_DEF LY_ERR
327lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *extp,
328 struct lysc_ext_instance *ext)
Michal Vasko193dacd2022-10-13 08:43:05 +0200329{
330 LY_ERR rc = LY_SUCCESS;
331 LY_ARRAY_COUNT_TYPE u, v;
332 enum ly_stmt stmtp;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200333 void **storagep;
Michal Vasko193dacd2022-10-13 08:43:05 +0200334 struct ly_set storagep_compiled = {0};
335
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200336 LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL);
337
Michal Vasko193dacd2022-10-13 08:43:05 +0200338 /* note into the compile context that we are processing extension now */
339 ctx->ext = ext;
340
341 LY_ARRAY_FOR(extp->substmts, u) {
342 stmtp = extp->substmts[u].stmt;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200343 storagep = extp->substmts[u].storage_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200344
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200345 if (!*storagep || ly_set_contains(&storagep_compiled, storagep, NULL)) {
Michal Vaskod595eff2023-02-20 11:29:28 +0100346 /* nothing parsed or already compiled (for example, if it is a linked list of parsed nodes) */
Michal Vasko193dacd2022-10-13 08:43:05 +0200347 continue;
348 }
349
350 LY_ARRAY_FOR(ext->substmts, v) {
351 if (stmtp != ext->substmts[v].stmt) {
352 continue;
353 }
354
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200355 if ((rc = lys_compile_ext_instance_stmt(ctx, storagep, ext, &ext->substmts[v]))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200356 goto cleanup;
357 }
358
359 /* parsed substatement compiled */
360 break;
361 }
362
363 /* compiled */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200364 ly_set_add(&storagep_compiled, storagep, 1, NULL);
Michal Vasko193dacd2022-10-13 08:43:05 +0200365 }
366
367cleanup:
368 ctx->ext = NULL;
369 ly_set_erase(&storagep_compiled, NULL);
370 return rc;
371}
372
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100373LIBYANG_API_DEF struct ly_ctx *
Michal Vasko193dacd2022-10-13 08:43:05 +0200374lyplg_ext_compile_get_ctx(const struct lysc_ctx *ctx)
Radek Krejci5f9a3672021-03-05 21:35:22 +0100375{
376 return ctx->ctx;
377}
378
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100379LIBYANG_API_DEF uint32_t *
Michal Vasko193dacd2022-10-13 08:43:05 +0200380lyplg_ext_compile_get_options(const struct lysc_ctx *ctx)
Radek Krejci5f9a3672021-03-05 21:35:22 +0100381{
Michal Vasko7c565922021-06-10 14:58:27 +0200382 return &((struct lysc_ctx *)ctx)->compile_opts;
Radek Krejci5f9a3672021-03-05 21:35:22 +0100383}
384
Michal Vasko6a914fb2022-01-17 10:36:14 +0100385LIBYANG_API_DEF const struct lys_module *
Michal Vasko193dacd2022-10-13 08:43:05 +0200386lyplg_ext_compile_get_cur_mod(const struct lysc_ctx *ctx)
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100387{
388 return ctx->cur_mod;
389}
390
Michal Vasko6a914fb2022-01-17 10:36:14 +0100391LIBYANG_API_DEF struct lysp_module *
Michal Vasko193dacd2022-10-13 08:43:05 +0200392lyplg_ext_compile_get_pmod(const struct lysc_ctx *ctx)
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100393{
394 return ctx->pmod;
395}
Michal Vaskoddd76592022-01-17 13:34:48 +0100396
Michal Vasko193dacd2022-10-13 08:43:05 +0200397LIBYANG_API_DEF struct ly_out **
398lyplg_ext_print_get_out(const struct lyspr_ctx *ctx)
399{
400 return &((struct lyspr_ctx *)ctx)->out;
401}
402
403LIBYANG_API_DEF uint32_t *
404lyplg_ext_print_get_options(const struct lyspr_ctx *ctx)
405{
406 return &((struct lyspr_ctx *)ctx)->options;
407}
408
409LIBYANG_API_DEF uint16_t *
410lyplg_ext_print_get_level(const struct lyspr_ctx *ctx)
411{
412 return &((struct lyspr_ctx *)ctx)->level;
413}
414
aPiecek03cb4872022-10-24 10:31:51 +0200415LIBYANG_API_DECL LY_ERR
416lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_ext_instance *ext,
417 lyplg_ext_sprinter_ctree_override_clb clb)
418{
419 LY_ERR rc = LY_SUCCESS;
420 uint32_t i;
421 struct lysc_node *schema;
422
Michal Vaskocba757c2024-09-10 14:46:07 +0200423 LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
aPiecek03cb4872022-10-24 10:31:51 +0200424
425 LY_ARRAY_FOR(ext->substmts, i) {
426 switch (ext->substmts[i].stmt) {
427 case LY_STMT_NOTIFICATION:
428 case LY_STMT_INPUT:
429 case LY_STMT_OUTPUT:
430 case LY_STMT_ACTION:
431 case LY_STMT_RPC:
432 case LY_STMT_ANYDATA:
433 case LY_STMT_ANYXML:
434 case LY_STMT_CASE:
435 case LY_STMT_CHOICE:
436 case LY_STMT_CONTAINER:
437 case LY_STMT_LEAF:
438 case LY_STMT_LEAF_LIST:
439 case LY_STMT_LIST:
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200440 schema = *ext->substmts[i].storage_p;
aPiecek03cb4872022-10-24 10:31:51 +0200441 if (schema) {
442 rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb);
443 return rc;
444 }
445 default:
446 break;
447 }
448 }
449
450 return rc;
451}
452
453LIBYANG_API_DECL LY_ERR
454lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_ext_instance *ext,
455 lyplg_ext_sprinter_ptree_override_clb clb)
456{
457 LY_ERR rc = LY_SUCCESS;
458 uint32_t i;
459 struct lysp_node *schema;
460
Michal Vaskocba757c2024-09-10 14:46:07 +0200461 LY_CHECK_ARG_RET(NULL, ctx, ext, LY_EINVAL);
aPiecek03cb4872022-10-24 10:31:51 +0200462
463 LY_ARRAY_FOR(ext->substmts, i) {
464 switch (ext->substmts[i].stmt) {
465 case LY_STMT_NOTIFICATION:
466 case LY_STMT_INPUT:
467 case LY_STMT_OUTPUT:
468 case LY_STMT_ACTION:
469 case LY_STMT_RPC:
470 case LY_STMT_ANYDATA:
471 case LY_STMT_ANYXML:
472 case LY_STMT_CASE:
473 case LY_STMT_CHOICE:
474 case LY_STMT_CONTAINER:
475 case LY_STMT_LEAF:
476 case LY_STMT_LEAF_LIST:
477 case LY_STMT_LIST:
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200478 schema = *ext->substmts[i].storage_p;
aPiecek03cb4872022-10-24 10:31:51 +0200479 if (schema) {
480 rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb);
481 return rc;
482 }
483 default:
484 break;
485 }
486 }
487
488 return rc;
489}
490
491LIBYANG_API_DECL LY_ERR
492lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_node *nodes,
493 lyplg_ext_sprinter_ctree_override_clb clb)
494{
495 struct lyspr_tree_schema *new;
496
Michal Vaskocba757c2024-09-10 14:46:07 +0200497 LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
aPiecek03cb4872022-10-24 10:31:51 +0200498
499 if (!nodes) {
500 return LY_SUCCESS;
501 }
502
503 LY_ARRAY_NEW_RET(NULL, ((struct lyspr_tree_ctx *)ctx)->schemas, new, LY_EMEM);
504 new->compiled = 1;
505 new->ctree = nodes;
506 new->cn_overr = clb;
507
508 return LY_SUCCESS;
509}
510
511LIBYANG_API_DECL LY_ERR
512lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_node *nodes,
513 lyplg_ext_sprinter_ptree_override_clb clb)
514{
515 struct lyspr_tree_schema *new;
516
Michal Vaskocba757c2024-09-10 14:46:07 +0200517 LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
aPiecek03cb4872022-10-24 10:31:51 +0200518
519 if (!nodes) {
520 return LY_SUCCESS;
521 }
522
523 LY_ARRAY_NEW_RET(NULL, ((struct lyspr_tree_ctx *)ctx)->schemas, new, LY_EMEM);
524 new->compiled = 0;
525 new->ptree = nodes;
526 new->pn_overr = clb;
527
528 return LY_SUCCESS;
529}
530
531LIBYANG_API_DECL LY_ERR
532lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv, void (*free_clb)(void *plugin_priv))
533{
Michal Vaskocba757c2024-09-10 14:46:07 +0200534 LY_CHECK_ARG_RET(NULL, ctx, LY_EINVAL);
aPiecek03cb4872022-10-24 10:31:51 +0200535
536 ((struct lyspr_tree_ctx *)ctx)->plugin_priv = plugin_priv;
537 ((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb;
538
539 return LY_SUCCESS;
540}
541
Michal Vasko193dacd2022-10-13 08:43:05 +0200542LIBYANG_API_DEF const char *
543lyplg_ext_stmt2str(enum ly_stmt stmt)
544{
545 if (stmt == LY_STMT_EXTENSION_INSTANCE) {
546 return "extension instance";
547 } else {
Michal Vaskob872d0f2022-12-08 09:36:54 +0100548 return lys_stmt_str(stmt);
Michal Vasko193dacd2022-10-13 08:43:05 +0200549 }
550}
551
552LIBYANG_API_DEF enum ly_stmt
553lyplg_ext_nodetype2stmt(uint16_t nodetype)
554{
555 switch (nodetype) {
556 case LYS_CONTAINER:
557 return LY_STMT_CONTAINER;
558 case LYS_CHOICE:
559 return LY_STMT_CHOICE;
560 case LYS_LEAF:
561 return LY_STMT_LEAF;
562 case LYS_LEAFLIST:
563 return LY_STMT_LEAF_LIST;
564 case LYS_LIST:
565 return LY_STMT_LIST;
566 case LYS_ANYXML:
567 return LY_STMT_ANYXML;
568 case LYS_ANYDATA:
569 return LY_STMT_ANYDATA;
570 case LYS_CASE:
571 return LY_STMT_CASE;
572 case LYS_RPC:
573 return LY_STMT_RPC;
574 case LYS_ACTION:
575 return LY_STMT_ACTION;
576 case LYS_NOTIF:
577 return LY_STMT_NOTIFICATION;
578 case LYS_USES:
579 return LY_STMT_USES;
580 case LYS_INPUT:
581 return LY_STMT_INPUT;
582 case LYS_OUTPUT:
583 return LY_STMT_OUTPUT;
584 default:
585 return LY_STMT_NONE;
586 }
587}
588
589LY_ERR
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200590lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, void ***storage_pp)
Michal Vasko193dacd2022-10-13 08:43:05 +0200591{
592 LY_ARRAY_COUNT_TYPE u;
593 enum ly_stmt match = 0;
594
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200595 *storage_pp = NULL;
Michal Vasko193dacd2022-10-13 08:43:05 +0200596
597 if (!(stmt & LY_STMT_NODE_MASK)) {
598 /* matching a non-node statement */
599 match = stmt;
600 }
601
602 LY_ARRAY_FOR(ext->substmts, u) {
603 if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) {
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200604 *storage_pp = ext->substmts[u].storage_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200605 return LY_SUCCESS;
606 }
607 }
608
609 return LY_ENOT;
610}
611
612LIBYANG_API_DEF LY_ERR
Michal Vaskofbd037c2022-11-08 10:34:20 +0100613lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
Michal Vasko193dacd2022-10-13 08:43:05 +0200614{
Michal Vaskob9878502022-11-11 10:00:05 +0100615 LY_ERR rc = LY_SUCCESS;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200616 void **s_p;
Michal Vasko193dacd2022-10-13 08:43:05 +0200617
Michal Vasko250ffba2022-11-08 11:31:05 +0100618 /* get pointer to the storage, is set even on error */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200619 rc = lyplg_ext_get_storage_p(ext, stmt, &s_p);
Michal Vasko193dacd2022-10-13 08:43:05 +0200620
Michal Vasko250ffba2022-11-08 11:31:05 +0100621 /* assign */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200622 if (s_p) {
623 memcpy(storage, s_p, storage_size);
Michal Vaskob9878502022-11-11 10:00:05 +0100624 } else {
625 memset(storage, 0, storage_size);
626 }
627
628 return rc;
Michal Vasko193dacd2022-10-13 08:43:05 +0200629}
630
631LIBYANG_API_DEF LY_ERR
Michal Vaskofbd037c2022-11-08 10:34:20 +0100632lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size, const void **storage)
Michal Vasko193dacd2022-10-13 08:43:05 +0200633{
634 LY_ARRAY_COUNT_TYPE u;
635 const struct lysp_ext_instance *extp = NULL;
636 enum ly_stmt match = 0;
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200637 void **s_p = NULL;
Michal Vasko193dacd2022-10-13 08:43:05 +0200638
Michal Vaskocba757c2024-09-10 14:46:07 +0200639 LY_CHECK_ARG_RET(NULL, ext, ext->module->parsed, LY_EINVAL);
640
Michal Vasko193dacd2022-10-13 08:43:05 +0200641 /* find the parsed ext instance */
642 LY_ARRAY_FOR(ext->module->parsed->exts, u) {
643 extp = &ext->module->parsed->exts[u];
644
645 if (ext->def == extp->def->compiled) {
646 break;
647 }
648 extp = NULL;
649 }
650 assert(extp);
651
652 if (!(stmt & LY_STMT_NODE_MASK)) {
653 /* matching a non-node statement */
654 match = stmt;
655 }
656
657 /* get the substatement */
658 LY_ARRAY_FOR(extp->substmts, u) {
659 if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) {
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200660 s_p = extp->substmts[u].storage_p;
Michal Vaskofbd037c2022-11-08 10:34:20 +0100661 break;
Michal Vasko193dacd2022-10-13 08:43:05 +0200662 }
663 }
664
Michal Vasko250ffba2022-11-08 11:31:05 +0100665 /* assign */
Michal Vaskoa6bab1e2024-09-05 12:24:20 +0200666 if (s_p) {
667 memcpy(storage, s_p, storage_size);
Michal Vaskob9878502022-11-11 10:00:05 +0100668 } else {
669 memset(storage, 0, storage_size);
670 }
671
672 return LY_SUCCESS;
Michal Vasko193dacd2022-10-13 08:43:05 +0200673}
674
Michal Vaskoddd76592022-01-17 13:34:48 +0100675LIBYANG_API_DEF LY_ERR
676lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data, ly_bool *ext_data_free)
677{
Michal Vasko40a7a442022-12-09 13:01:38 +0100678 LY_ERR rc;
679
Michal Vaskoddd76592022-01-17 13:34:48 +0100680 if (!ctx->ext_clb) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200681 lyplg_ext_compile_log(NULL, ext, LY_LLERR, LY_EINVAL, "Failed to get extension data, no callback set.");
Michal Vaskoddd76592022-01-17 13:34:48 +0100682 return LY_EINVAL;
683 }
684
Michal Vasko40a7a442022-12-09 13:01:38 +0100685 if ((rc = ctx->ext_clb(ext, ctx->ext_clb_data, ext_data, ext_data_free))) {
686 lyplg_ext_compile_log(NULL, ext, LY_LLERR, rc, "Callback for getting ext data failed.");
687 }
688 return rc;
Michal Vaskoddd76592022-01-17 13:34:48 +0100689}