blob: 9fde053b0ef69cdd33c496534897dbc6b07d5a42 [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 Vaskoddd76592022-01-17 13:34:48 +01007 * Copyright (c) 2019 - 2022 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
Radek Krejci5f9a3672021-03-05 21:35:22 +010022#include "common.h"
Michal Vasko193dacd2022-10-13 08:43:05 +020023#include "dict.h"
24#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.
84 * @param[in] parsed Parsed ext instance substatement structure.
85 * @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
90lys_compile_ext_instance_stmt(struct lysc_ctx *ctx, const void *parsed, 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
97 /* compilation wthout any storage */
98 if (substmt->stmt == LY_STMT_IF_FEATURE) {
99 ly_bool enabled;
100
101 /* evaluate */
102 LY_CHECK_GOTO(rc = lys_eval_iffeatures(ctx->ctx, parsed, &enabled), cleanup);
103 if (!enabled) {
104 /* it is disabled, remove the whole extension instance */
105 rc = LY_ENOT;
106 }
107 }
108
109 if (!substmt->storage || !parsed) {
110 /* nothing to store or nothing parsed to compile */
111 goto cleanup;
112 }
113
114 switch (substmt->stmt) {
115 case LY_STMT_NOTIFICATION:
116 case LY_STMT_INPUT:
117 case LY_STMT_OUTPUT:
118 case LY_STMT_ACTION:
119 case LY_STMT_RPC:
120 case LY_STMT_ANYDATA:
121 case LY_STMT_ANYXML:
122 case LY_STMT_CASE:
123 case LY_STMT_CHOICE:
124 case LY_STMT_CONTAINER:
125 case LY_STMT_LEAF:
126 case LY_STMT_LEAF_LIST:
127 case LY_STMT_LIST:
128 case LY_STMT_USES: {
129 const uint16_t flags;
130 struct lysp_node *pnodes, *pnode;
131 struct lysc_node *node;
132
Michal Vaskofbd037c2022-11-08 10:34:20 +0100133 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
Michal Vasko193dacd2022-10-13 08:43:05 +0200134 pnodes = (struct lysp_node *)parsed;
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200135
136 /* compile nodes */
137 LY_LIST_FOR(pnodes, pnode) {
138 if (pnode->nodetype & (LYS_INPUT | LYS_OUTPUT)) {
139 /* manual compile */
140 node = calloc(1, sizeof(struct lysc_node_action_inout));
141 LY_CHECK_ERR_GOTO(!node, LOGMEM(ctx->ctx); rc = LY_EMEM, cleanup);
142 LY_CHECK_GOTO(rc = lys_compile_node_action_inout(ctx, pnode, node), cleanup);
143 LY_CHECK_GOTO(rc = lys_compile_node_connect(ctx, NULL, node), cleanup);
144 } else {
145 /* ctx->ext substatement storage is used as the document root */
146 LY_CHECK_GOTO(rc = lys_compile_node(ctx, pnode, NULL, flags, NULL), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200147 }
148 }
149 break;
150 }
151 case LY_STMT_ARGUMENT:
152 case LY_STMT_CONTACT:
153 case LY_STMT_DESCRIPTION:
154 case LY_STMT_ERROR_APP_TAG:
155 case LY_STMT_ERROR_MESSAGE:
156 case LY_STMT_KEY:
157 case LY_STMT_MODIFIER:
158 case LY_STMT_NAMESPACE:
159 case LY_STMT_ORGANIZATION:
160 case LY_STMT_PRESENCE:
161 case LY_STMT_REFERENCE:
162 case LY_STMT_UNITS:
163 /* just make a copy */
164 LY_CHECK_GOTO(rc = lydict_insert(ctx->ctx, parsed, 0, substmt->storage), cleanup);
165 break;
166
167 case LY_STMT_BIT:
168 basetype = LY_TYPE_BITS;
169 /* fallthrough */
170 case LY_STMT_ENUM:
171 if (substmt->stmt == LY_STMT_ENUM) {
172 basetype = LY_TYPE_ENUM;
173 }
174
175 /* compile */
176 LY_CHECK_GOTO(rc = lys_compile_type_enums(ctx, parsed, basetype, NULL, substmt->storage), cleanup);
177 break;
178
179 case LY_STMT_CONFIG: {
180 const uint16_t flags = (uintptr_t)parsed;
181
182 if (!(ctx->compile_opts & LYS_COMPILE_NO_CONFIG)) {
183 if (flags & LYS_CONFIG_MASK) {
184 /* explicitly set */
185 *(uint16_t *)substmt->storage = flags | LYS_SET_CONFIG;
186 } else if (ext->parent_stmt & LY_STMT_DATA_NODE_MASK) {
187 /* inherit */
188 *(uint16_t *)substmt->storage = ((struct lysc_node *)ext->parent)->flags & LYS_CONFIG_MASK;
189 } else {
190 /* default config */
191 *(uint16_t *)substmt->storage = LYS_CONFIG_W;
192 }
193 } /* else leave zero */
194 break;
195 }
196 case LY_STMT_MUST: {
197 const struct lysp_restr *restrs = parsed;
Michal Vasko193dacd2022-10-13 08:43:05 +0200198
199 /* sized array */
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200200 COMPILE_ARRAY_GOTO(ctx, restrs, *(struct lysc_must **)substmt->storage, lys_compile_must, rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200201 break;
202 }
203 case LY_STMT_WHEN: {
204 const uint16_t flags;
205 const struct lysp_when *when = parsed;
206
207 /* read compiled status */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100208 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
Michal Vasko193dacd2022-10-13 08:43:05 +0200209
210 /* compile */
211 LY_CHECK_GOTO(rc = lys_compile_when(ctx, when, flags, NULL, NULL, NULL, substmt->storage), cleanup);
212 break;
213 }
214 case LY_STMT_FRACTION_DIGITS:
215 case LY_STMT_REQUIRE_INSTANCE:
216 /* just make a copy */
217 *(uint8_t *)substmt->storage = (uintptr_t)parsed;
218 break;
219
220 case LY_STMT_MANDATORY:
221 case LY_STMT_ORDERED_BY:
222 case LY_STMT_STATUS:
223 /* just make a copy */
224 *(uint16_t *)substmt->storage = (uintptr_t)parsed;
225 break;
226
227 case LY_STMT_MAX_ELEMENTS:
228 case LY_STMT_MIN_ELEMENTS:
229 /* just make a copy */
230 *(uint32_t *)substmt->storage = (uintptr_t)parsed;
231 break;
232
233 case LY_STMT_POSITION:
234 case LY_STMT_VALUE:
235 /* just make a copy */
236 *(int64_t *)substmt->storage = (uintptr_t)parsed;
237 break;
238
239 case LY_STMT_IDENTITY:
240 /* compile */
241 LY_CHECK_GOTO(rc = lys_identity_precompile(ctx, NULL, NULL, parsed, substmt->storage), cleanup);
242 break;
243
244 case LY_STMT_LENGTH:
245 length_restr = 1;
246 /* fallthrough */
247 case LY_STMT_RANGE:
248 /* compile, use uint64 default range */
249 LY_CHECK_GOTO(rc = lys_compile_type_range(ctx, parsed, LY_TYPE_UINT64, length_restr, 0, NULL, substmt->storage),
250 cleanup);
251 break;
252
253 case LY_STMT_PATTERN:
254 /* compile */
255 LY_CHECK_GOTO(rc = lys_compile_type_patterns(ctx, parsed, NULL, substmt->storage), cleanup);
256 break;
257
258 case LY_STMT_TYPE: {
259 const uint16_t flags;
260 const char *units;
261 const struct lysp_type *ptype = parsed;
262
263 /* read compiled info */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100264 lyplg_ext_get_storage(ext, LY_STMT_STATUS, sizeof flags, (const void **)&flags);
265 lyplg_ext_get_storage(ext, LY_STMT_UNITS, sizeof units, (const void **)&units);
Michal Vasko193dacd2022-10-13 08:43:05 +0200266
267 /* compile */
268 LY_CHECK_GOTO(rc = lys_compile_type(ctx, NULL, flags, ext->def->name, ptype, substmt->storage, &units, NULL), cleanup);
269 break;
270 }
271 case LY_STMT_EXTENSION_INSTANCE: {
272 struct lysp_ext_instance *extps = (struct lysp_ext_instance *)parsed;
Michal Vasko193dacd2022-10-13 08:43:05 +0200273
274 /* compile sized array */
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200275 COMPILE_EXTS_GOTO(ctx, extps, *(struct lysc_ext_instance **)substmt->storage, ext, rc, cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +0200276 break;
277 }
278 case LY_STMT_AUGMENT:
279 case LY_STMT_GROUPING:
280 case LY_STMT_BASE:
281 case LY_STMT_BELONGS_TO:
282 case LY_STMT_DEFAULT:
283 case LY_STMT_DEVIATE:
284 case LY_STMT_DEVIATION:
285 case LY_STMT_EXTENSION:
286 case LY_STMT_FEATURE:
287 case LY_STMT_IF_FEATURE:
288 case LY_STMT_IMPORT:
289 case LY_STMT_INCLUDE:
290 case LY_STMT_MODULE:
291 case LY_STMT_PATH:
292 case LY_STMT_PREFIX:
293 case LY_STMT_REFINE:
294 case LY_STMT_REVISION:
295 case LY_STMT_REVISION_DATE:
296 case LY_STMT_SUBMODULE:
297 case LY_STMT_TYPEDEF:
298 case LY_STMT_UNIQUE:
299 case LY_STMT_YANG_VERSION:
300 case LY_STMT_YIN_ELEMENT:
301 LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" compilation is not supported.", lyplg_ext_stmt2str(substmt->stmt));
302 rc = LY_EVALID;
303 goto cleanup;
304
305 default:
306 LOGVAL(ctx->ctx, LYVE_SYNTAX_YANG, "Statement \"%s\" is not supported as an extension "
307 "(found in \"%s%s%s\") substatement.", lyplg_ext_stmt2str(substmt->stmt), ext->def->name,
308 ext->argument ? " " : "", ext->argument ? ext->argument : "");
309 rc = LY_EVALID;
310 goto cleanup;
311 }
312
313cleanup:
314 return rc;
315}
316
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200317LIBYANG_API_DEF LY_ERR
318lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *extp,
319 struct lysc_ext_instance *ext)
Michal Vasko193dacd2022-10-13 08:43:05 +0200320{
321 LY_ERR rc = LY_SUCCESS;
322 LY_ARRAY_COUNT_TYPE u, v;
323 enum ly_stmt stmtp;
324 const void *storagep;
325 struct ly_set storagep_compiled = {0};
326
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200327 LY_CHECK_ARG_RET(ctx ? ctx->ctx : NULL, ctx, extp, ext, LY_EINVAL);
328
Michal Vasko193dacd2022-10-13 08:43:05 +0200329 /* note into the compile context that we are processing extension now */
330 ctx->ext = ext;
331
332 LY_ARRAY_FOR(extp->substmts, u) {
333 stmtp = extp->substmts[u].stmt;
334 storagep = *(void **)extp->substmts[u].storage;
335
336 if (ly_set_contains(&storagep_compiled, storagep, NULL)) {
337 /* this parsed statement has already been compiled (for example, if it is a linked list of parsed nodes) */
338 continue;
339 }
340
341 LY_ARRAY_FOR(ext->substmts, v) {
342 if (stmtp != ext->substmts[v].stmt) {
343 continue;
344 }
345
Michal Vaskoa0ba01e2022-10-19 13:26:57 +0200346 if ((rc = lys_compile_ext_instance_stmt(ctx, storagep, ext, &ext->substmts[v]))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200347 goto cleanup;
348 }
349
350 /* parsed substatement compiled */
351 break;
352 }
353
354 /* compiled */
355 ly_set_add(&storagep_compiled, storagep, 1, NULL);
356 }
357
358cleanup:
359 ctx->ext = NULL;
360 ly_set_erase(&storagep_compiled, NULL);
361 return rc;
362}
363
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100364LIBYANG_API_DEF struct ly_ctx *
Michal Vasko193dacd2022-10-13 08:43:05 +0200365lyplg_ext_compile_get_ctx(const struct lysc_ctx *ctx)
Radek Krejci5f9a3672021-03-05 21:35:22 +0100366{
367 return ctx->ctx;
368}
369
Jan Kundrátc53a7ec2021-12-09 16:01:19 +0100370LIBYANG_API_DEF uint32_t *
Michal Vasko193dacd2022-10-13 08:43:05 +0200371lyplg_ext_compile_get_options(const struct lysc_ctx *ctx)
Radek Krejci5f9a3672021-03-05 21:35:22 +0100372{
Michal Vasko7c565922021-06-10 14:58:27 +0200373 return &((struct lysc_ctx *)ctx)->compile_opts;
Radek Krejci5f9a3672021-03-05 21:35:22 +0100374}
375
Michal Vasko6a914fb2022-01-17 10:36:14 +0100376LIBYANG_API_DEF const struct lys_module *
Michal Vasko193dacd2022-10-13 08:43:05 +0200377lyplg_ext_compile_get_cur_mod(const struct lysc_ctx *ctx)
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100378{
379 return ctx->cur_mod;
380}
381
Michal Vasko6a914fb2022-01-17 10:36:14 +0100382LIBYANG_API_DEF struct lysp_module *
Michal Vasko193dacd2022-10-13 08:43:05 +0200383lyplg_ext_compile_get_pmod(const struct lysc_ctx *ctx)
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100384{
385 return ctx->pmod;
386}
Michal Vaskoddd76592022-01-17 13:34:48 +0100387
Michal Vasko193dacd2022-10-13 08:43:05 +0200388LIBYANG_API_DEF struct ly_out **
389lyplg_ext_print_get_out(const struct lyspr_ctx *ctx)
390{
391 return &((struct lyspr_ctx *)ctx)->out;
392}
393
394LIBYANG_API_DEF uint32_t *
395lyplg_ext_print_get_options(const struct lyspr_ctx *ctx)
396{
397 return &((struct lyspr_ctx *)ctx)->options;
398}
399
400LIBYANG_API_DEF uint16_t *
401lyplg_ext_print_get_level(const struct lyspr_ctx *ctx)
402{
403 return &((struct lyspr_ctx *)ctx)->level;
404}
405
aPiecek03cb4872022-10-24 10:31:51 +0200406LIBYANG_API_DECL LY_ERR
407lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_ext_instance *ext,
408 lyplg_ext_sprinter_ctree_override_clb clb)
409{
410 LY_ERR rc = LY_SUCCESS;
411 uint32_t i;
412 struct lysc_node *schema;
413
414 LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
415
416 LY_ARRAY_FOR(ext->substmts, i) {
417 switch (ext->substmts[i].stmt) {
418 case LY_STMT_NOTIFICATION:
419 case LY_STMT_INPUT:
420 case LY_STMT_OUTPUT:
421 case LY_STMT_ACTION:
422 case LY_STMT_RPC:
423 case LY_STMT_ANYDATA:
424 case LY_STMT_ANYXML:
425 case LY_STMT_CASE:
426 case LY_STMT_CHOICE:
427 case LY_STMT_CONTAINER:
428 case LY_STMT_LEAF:
429 case LY_STMT_LEAF_LIST:
430 case LY_STMT_LIST:
431 schema = *((struct lysc_node **)ext->substmts[i].storage);
432 if (schema) {
433 rc = lyplg_ext_sprinter_ctree_add_nodes(ctx, schema, clb);
434 return rc;
435 }
436 default:
437 break;
438 }
439 }
440
441 return rc;
442}
443
444LIBYANG_API_DECL LY_ERR
445lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_ext_instance *ext,
446 lyplg_ext_sprinter_ptree_override_clb clb)
447{
448 LY_ERR rc = LY_SUCCESS;
449 uint32_t i;
450 struct lysp_node *schema;
451
452 LY_CHECK_ARG_RET2(NULL, ctx, ext, LY_EINVAL);
453
454 LY_ARRAY_FOR(ext->substmts, i) {
455 switch (ext->substmts[i].stmt) {
456 case LY_STMT_NOTIFICATION:
457 case LY_STMT_INPUT:
458 case LY_STMT_OUTPUT:
459 case LY_STMT_ACTION:
460 case LY_STMT_RPC:
461 case LY_STMT_ANYDATA:
462 case LY_STMT_ANYXML:
463 case LY_STMT_CASE:
464 case LY_STMT_CHOICE:
465 case LY_STMT_CONTAINER:
466 case LY_STMT_LEAF:
467 case LY_STMT_LEAF_LIST:
468 case LY_STMT_LIST:
469 schema = *((struct lysp_node **)ext->substmts[i].storage);
470 if (schema) {
471 rc = lyplg_ext_sprinter_ptree_add_nodes(ctx, schema, clb);
472 return rc;
473 }
474 default:
475 break;
476 }
477 }
478
479 return rc;
480}
481
482LIBYANG_API_DECL LY_ERR
483lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_node *nodes,
484 lyplg_ext_sprinter_ctree_override_clb clb)
485{
486 struct lyspr_tree_schema *new;
487
488 LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
489
490 if (!nodes) {
491 return LY_SUCCESS;
492 }
493
494 LY_ARRAY_NEW_RET(NULL, ((struct lyspr_tree_ctx *)ctx)->schemas, new, LY_EMEM);
495 new->compiled = 1;
496 new->ctree = nodes;
497 new->cn_overr = clb;
498
499 return LY_SUCCESS;
500}
501
502LIBYANG_API_DECL LY_ERR
503lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_node *nodes,
504 lyplg_ext_sprinter_ptree_override_clb clb)
505{
506 struct lyspr_tree_schema *new;
507
508 LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
509
510 if (!nodes) {
511 return LY_SUCCESS;
512 }
513
514 LY_ARRAY_NEW_RET(NULL, ((struct lyspr_tree_ctx *)ctx)->schemas, new, LY_EMEM);
515 new->compiled = 0;
516 new->ptree = nodes;
517 new->pn_overr = clb;
518
519 return LY_SUCCESS;
520}
521
522LIBYANG_API_DECL LY_ERR
523lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv, void (*free_clb)(void *plugin_priv))
524{
525 LY_CHECK_ARG_RET1(NULL, ctx, LY_EINVAL);
526
527 ((struct lyspr_tree_ctx *)ctx)->plugin_priv = plugin_priv;
528 ((struct lyspr_tree_ctx *)ctx)->free_plugin_priv = free_clb;
529
530 return LY_SUCCESS;
531}
532
Michal Vasko193dacd2022-10-13 08:43:05 +0200533LIBYANG_API_DEF const char *
534lyplg_ext_stmt2str(enum ly_stmt stmt)
535{
536 if (stmt == LY_STMT_EXTENSION_INSTANCE) {
537 return "extension instance";
538 } else {
539 return stmt_attr_info[stmt].name;
540 }
541}
542
543LIBYANG_API_DEF enum ly_stmt
544lyplg_ext_nodetype2stmt(uint16_t nodetype)
545{
546 switch (nodetype) {
547 case LYS_CONTAINER:
548 return LY_STMT_CONTAINER;
549 case LYS_CHOICE:
550 return LY_STMT_CHOICE;
551 case LYS_LEAF:
552 return LY_STMT_LEAF;
553 case LYS_LEAFLIST:
554 return LY_STMT_LEAF_LIST;
555 case LYS_LIST:
556 return LY_STMT_LIST;
557 case LYS_ANYXML:
558 return LY_STMT_ANYXML;
559 case LYS_ANYDATA:
560 return LY_STMT_ANYDATA;
561 case LYS_CASE:
562 return LY_STMT_CASE;
563 case LYS_RPC:
564 return LY_STMT_RPC;
565 case LYS_ACTION:
566 return LY_STMT_ACTION;
567 case LYS_NOTIF:
568 return LY_STMT_NOTIFICATION;
569 case LYS_USES:
570 return LY_STMT_USES;
571 case LYS_INPUT:
572 return LY_STMT_INPUT;
573 case LYS_OUTPUT:
574 return LY_STMT_OUTPUT;
575 default:
576 return LY_STMT_NONE;
577 }
578}
579
580LY_ERR
581lyplg_ext_get_storage_p(const struct lysc_ext_instance *ext, int stmt, const void ***storage_p)
582{
583 LY_ARRAY_COUNT_TYPE u;
584 enum ly_stmt match = 0;
585
586 *storage_p = NULL;
587
588 if (!(stmt & LY_STMT_NODE_MASK)) {
589 /* matching a non-node statement */
590 match = stmt;
591 }
592
593 LY_ARRAY_FOR(ext->substmts, u) {
594 if ((match && (ext->substmts[u].stmt == match)) || (!match && (ext->substmts[u].stmt & stmt))) {
595 *storage_p = ext->substmts[u].storage;
596 return LY_SUCCESS;
597 }
598 }
599
600 return LY_ENOT;
601}
602
Michal Vasko250ffba2022-11-08 11:31:05 +0100603static LY_ERR
604lyplg_ext_set_storage(const struct ly_ctx *ctx, const void **s, uint32_t storage_size, const void **storage)
605{
606 if (s) {
607 /* matters for little-endian */
608 switch (storage_size) {
609 case 1:
610 *(uint8_t *)storage = (uintptr_t)*s;
611 break;
612 case 2:
613 *(uint16_t *)storage = (uintptr_t)*s;
614 break;
615 case 4:
616 *(uint32_t *)storage = (uintptr_t)*s;
617 break;
618 case 8:
619 *(uint64_t *)storage = (uintptr_t)*s;
620 break;
621 default:
622 LOGERR(ctx, LY_EINVAL, "Invalid storage size %" PRIu32 ".", storage_size);
623 return LY_EINVAL;
624 }
625
626 return LY_SUCCESS;
627 } else {
628 /* zero */
629 switch (storage_size) {
630 case 1:
631 *(uint8_t *)storage = (uintptr_t)s;
632 break;
633 case 2:
634 *(uint16_t *)storage = (uintptr_t)s;
635 break;
636 case 4:
637 *(uint32_t *)storage = (uintptr_t)s;
638 break;
639 case 8:
640 *(uint64_t *)storage = (uintptr_t)s;
641 break;
642 default:
643 LOGERR(ctx, LY_EINVAL, "Invalid storage size %" PRIu32 ".", storage_size);
644 return LY_EINVAL;
645 }
646 return LY_ENOT;
647 }
648}
649
Michal Vasko193dacd2022-10-13 08:43:05 +0200650LIBYANG_API_DEF LY_ERR
Michal Vaskofbd037c2022-11-08 10:34:20 +0100651lyplg_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 +0200652{
Michal Vasko250ffba2022-11-08 11:31:05 +0100653 LY_ERR rc1, rc2;
Michal Vasko193dacd2022-10-13 08:43:05 +0200654 const void **s;
655
Michal Vasko250ffba2022-11-08 11:31:05 +0100656 /* get pointer to the storage, is set even on error */
657 rc1 = lyplg_ext_get_storage_p(ext, stmt, &s);
Michal Vasko193dacd2022-10-13 08:43:05 +0200658
Michal Vasko250ffba2022-11-08 11:31:05 +0100659 /* assign */
660 rc2 = lyplg_ext_set_storage(ext->module->ctx, s, storage_size, storage);
661 return rc1 ? rc1 : rc2;
Michal Vasko193dacd2022-10-13 08:43:05 +0200662}
663
664LIBYANG_API_DEF LY_ERR
Michal Vaskofbd037c2022-11-08 10:34:20 +0100665lyplg_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 +0200666{
667 LY_ARRAY_COUNT_TYPE u;
668 const struct lysp_ext_instance *extp = NULL;
669 enum ly_stmt match = 0;
Michal Vaskofbd037c2022-11-08 10:34:20 +0100670 const void **s = NULL;
Michal Vasko193dacd2022-10-13 08:43:05 +0200671
Michal Vasko193dacd2022-10-13 08:43:05 +0200672 /* find the parsed ext instance */
673 LY_ARRAY_FOR(ext->module->parsed->exts, u) {
674 extp = &ext->module->parsed->exts[u];
675
676 if (ext->def == extp->def->compiled) {
677 break;
678 }
679 extp = NULL;
680 }
681 assert(extp);
682
683 if (!(stmt & LY_STMT_NODE_MASK)) {
684 /* matching a non-node statement */
685 match = stmt;
686 }
687
688 /* get the substatement */
689 LY_ARRAY_FOR(extp->substmts, u) {
690 if ((match && (extp->substmts[u].stmt == match)) || (!match && (extp->substmts[u].stmt & stmt))) {
Michal Vaskofbd037c2022-11-08 10:34:20 +0100691 s = extp->substmts[u].storage;
692 break;
Michal Vasko193dacd2022-10-13 08:43:05 +0200693 }
694 }
695
Michal Vasko250ffba2022-11-08 11:31:05 +0100696 /* assign */
697 return lyplg_ext_set_storage(ext->module->ctx, s, storage_size, storage);
Michal Vasko193dacd2022-10-13 08:43:05 +0200698}
699
Michal Vaskoddd76592022-01-17 13:34:48 +0100700LIBYANG_API_DEF LY_ERR
701lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data, ly_bool *ext_data_free)
702{
703 if (!ctx->ext_clb) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200704 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 +0100705 return LY_EINVAL;
706 }
707
708 return ctx->ext_clb(ext, ctx->ext_clb_data, ext_data, ext_data_free);
709}