diff --git a/src/parser_yang.c b/src/parser_yang.c index 8511d26a8..58449aed5 100644 --- a/src/parser_yang.c +++ b/src/parser_yang.c @@ -982,8 +982,16 @@ parse_ext(struct lysp_yang_ctx *ctx, const char *ext_name, size_t ext_name_len, e->parent_stmt_index = parent_stmt_index; YANG_READ_SUBSTMT_FOR_GOTO(ctx, kw, word, word_len, ret, cleanup) { - LY_CHECK_GOTO(ret = parse_ext_substmt(ctx, kw, word, word_len, &e->child), cleanup) - YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, NULL, ret, cleanup); + switch (kw) { + case LY_STMT_EXTENSION_INSTANCE: + LY_CHECK_GOTO(parse_ext(ctx, word, word_len, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts), cleanup); + break; + default: + /* just store all the statements */ + LY_CHECK_GOTO(ret = parse_ext_substmt(ctx, kw, word, word_len, &e->child), cleanup) + break; + } + YANG_READ_SUBSTMT_NEXT_ITER(ctx, kw, word, word_len, e->exts, ret, cleanup); } cleanup: diff --git a/src/parser_yin.c b/src/parser_yin.c index 3924d0e62..eab9c37b2 100644 --- a/src/parser_yin.c +++ b/src/parser_yin.c @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief YIN parser. * - * Copyright (c) 2015 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2015 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -3409,6 +3409,14 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum if (ctx->xmlctx->ws_only) { LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); while (ctx->xmlctx->status == LYXML_ELEMENT) { + /* BUG nested extensions will not be parsed because we are not able to dinsguish between them + * and the argument of this extension, in case there is one and its 'yin-element' is 'true' + stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, + ctx->xmlctx->prefix_len, LY_STMT_EXTENSION_INSTANCE); + if (stmt == LY_STMT_EXTENSION_INSTANCE) { + LY_CHECK_RET(yin_parse_extension_instance(ctx, e, LY_STMT_EXTENSION_INSTANCE, 0, &e->exts)); + } else { */ + LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem)); if (!e->child) { e->child = new_subelem; @@ -3420,6 +3428,9 @@ yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE); LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx)); } + + /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */ + LY_CHECK_RET(yin_unres_exts_add(ctx, e->exts)); } else if (ctx->xmlctx->value_len) { /* invalid text content */ LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name, diff --git a/src/plugins_exts.h b/src/plugins_exts.h index 74ce21591..d75efaee2 100644 --- a/src/plugins_exts.h +++ b/src/plugins_exts.h @@ -109,7 +109,7 @@ extern "C" { /** * @brief Extensions API version */ -#define LYPLG_EXT_API_VERSION 6 +#define LYPLG_EXT_API_VERSION 7 /** * @brief Mask for an operation statement. @@ -419,6 +419,7 @@ struct lysp_ext_instance { parsed data ([sized array](@ref sizedarrays)) */ void *parsed; /**< private plugin parsed data */ struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */ + struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */ }; /** diff --git a/src/schema_compile.c b/src/schema_compile.c index aa9a3d0a0..bda517cfc 100644 --- a/src/schema_compile.c +++ b/src/schema_compile.c @@ -4,7 +4,7 @@ * @author Michal Vasko * @brief Schema compilation. * - * Copyright (c) 2015 - 2022 CESNET, z.s.p.o. + * Copyright (c) 2015 - 2024 CESNET, z.s.p.o. * * This source code is licensed under BSD 3-Clause License (the "License"). * You may not use this file except in compliance with the License. @@ -172,7 +172,10 @@ lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *extp, struct lys /* compile extension if not already */ LY_CHECK_GOTO(ret = lys_compile_extension(ctx, extp, &ext->def), cleanup); - /* compile */ + /* compile nested extensions */ + COMPILE_EXTS_GOTO(ctx, extp->exts, ext->exts, ext, ret, cleanup); + + /* compile this extension */ if (ext->def->plugin && ext->def->plugin->compile) { if (ext->argument) { lysc_update_path(ctx, ext->module, ext->argument); diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c index 91ba72b07..ee05d3cf7 100644 --- a/src/tree_schema_free.c +++ b/src/tree_schema_free.c @@ -80,6 +80,8 @@ lysp_ext_instance_free(struct lysf_ctx *ctx, struct lysp_ext_instance *ext) LY_LIST_FOR_SAFE(ext->child, next, stmt) { lysp_stmt_free(ctx->ctx, stmt); } + + FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free); } /**