blob: f0053914c0286d590675ca6f5f75915662848dbf [file] [log] [blame]
Radek Krejcid7e8a622018-10-29 15:54:55 +01001/**
Radek Krejci0935f412019-08-20 16:15:18 +02002 * @file plugins_exts.h
Radek Krejcid7e8a622018-10-29 15:54:55 +01003 * @author Radek Krejci <rkrejci@cesnet.cz>
Michal Vaskofbbea932022-06-07 11:00:55 +02004 * @author Michal Vasko <mvasko@cesnet.cz>
Radek Krejcid7e8a622018-10-29 15:54:55 +01005 * @brief libyang support for YANG extensions implementation.
6 *
Michal Vaskofbbea932022-06-07 11:00:55 +02007 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
Radek Krejcid7e8a622018-10-29 15:54:55 +01008 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
14 */
15
Radek Krejci0935f412019-08-20 16:15:18 +020016#ifndef LY_PLUGINS_EXTS_H_
17#define LY_PLUGINS_EXTS_H_
Radek Krejcid7e8a622018-10-29 15:54:55 +010018
Radek Krejci535ea9f2020-05-29 16:01:05 +020019#include "log.h"
Michal Vaskofbbea932022-06-07 11:00:55 +020020#include "parser_data.h"
Radek Krejci3e6632f2021-03-22 22:08:21 +010021#include "plugins.h"
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +010022#include "tree_data.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010023#include "tree_edit.h"
Radek Krejci0e59c312019-08-15 15:34:15 +020024#include "tree_schema.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020025
26struct ly_ctx;
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +010027struct ly_in;
Radek Krejci535ea9f2020-05-29 16:01:05 +020028struct lyd_node;
Michal Vasko193dacd2022-10-13 08:43:05 +020029struct lysc_ctx;
Radek Krejci0aa1f702021-04-01 16:16:19 +020030struct lysc_ext_substmt;
Michal Vaskob4750962022-10-06 15:33:35 +020031struct lysp_ctx;
Michal Vasko193dacd2022-10-13 08:43:05 +020032struct lyspr_ctx;
aPiecek03cb4872022-10-24 10:31:51 +020033struct lyspr_tree_ctx;
Radek Krejci0e59c312019-08-15 15:34:15 +020034
Radek Krejcid7e8a622018-10-29 15:54:55 +010035#ifdef __cplusplus
36extern "C" {
37#endif
38
39/**
Radek Krejci75104122021-04-01 15:37:45 +020040 * @page howtoPluginsExtensions Extension Plugins
41 *
42 * Note that the part of the libyang API here is available only by including a separated `<libyang/plugins_exts.h>` header
43 * file. Also note that the extension plugins API is versioned separately from libyang itself, so backward incompatible
44 * changes can come even without changing libyang major version.
45 *
46 * YANG extensions are very complex. Usually only its description specifies how it is supposed to behave, what are the
47 * allowed substatements, their cardinality or if the standard YANG statements placed inside the extension differs somehow
aPiecekb0445f22021-06-24 11:34:07 +020048 * in their meaning or behavior. libyang provides the Extension plugins API to implement such extensions and add its support
Radek Krejci75104122021-04-01 15:37:45 +020049 * into libyang itself. However we tried our best, the API is not (and it cannot be) so universal and complete to cover all
50 * possibilities. There are definitely use cases which cannot be simply implemented only with this API.
51 *
52 * libyang implements 3 important extensions: [NACM](https://tools.ietf.org/html/rfc8341), [Metadata](@ref howtoDataMetadata)
53 * and [yang-data](@ref howtoDataYangdata). Despite the core implementation in all three cases is done via extension plugin
54 * API, also other parts of the libyang code had to be extended to cover complete scope of the extensions.
55 *
56 * We believe, that the API is capable to allow implementation of very wide range of YANG extensions. However, if you see
57 * limitations for the particular YANG extension, don't hesitate to contact the project developers to discuss all the
58 * options, including updating the API.
59 *
60 * The plugin's functionality is provided to libyang via a set of callbacks specified as an array of ::lyplg_ext_record
61 * structures using the ::LYPLG_EXTENSIONS macro.
62 *
Michal Vaskoc7262cb2022-11-09 09:41:56 +010063 * The most important callbacks are ::lyplg_ext.parse and ::lyplg_ext.compile. They are responsible for parsing and
64 * compiling extension instance. This should include validating all the substatements, their values, or placement of
65 * the extension instance itself. If needed, the processed data can be stored in some form into the compiled schema
66 * representation of the extension instance. To make this task as easy as possible, libyang provides several
67 * [parsing](@ref pluginsExtensionsParse) and [compilation](@ref pluginsExtensionsCompile) helper functions to process
68 * known YANG statements exactly as if they were standard YANG statements.
Radek Krejci75104122021-04-01 15:37:45 +020069 *
70 * The data validation callback ::lyplg_ext.validate is used for additional validation of a data nodes that contains the
71 * connected extension instance directly (as a substatement) or indirectly in case of terminal nodes via their type (no
72 * matter if the extension instance is placed directly in the leaf's/leaf-list's type or in the type of the referenced
73 * typedef).
74 *
aPiecek03cb4872022-10-24 10:31:51 +020075 * The ::lyplg_ext.printer_info callback implement printing the compiled extension instance data when the schema (module) is
Radek Krejci75104122021-04-01 15:37:45 +020076 * being printed in the ::LYS_OUT_YANG_COMPILED (info) format. As for compile callback, there are also
Michal Vaskoc7262cb2022-11-09 09:41:56 +010077 * [helper functions](@ref pluginsExtensionsSprinterInfo) to access printer's context and to print standard YANG statements
Radek Krejci75104122021-04-01 15:37:45 +020078 * placed in the extension instance by libyang itself.
79 *
aPiecek03cb4872022-10-24 10:31:51 +020080 * The ::lyplg_ext.printer_ctree and ::lyplg_ext.printer_ptree callbacks implement printing of YANG tree diagrams
81 * (RFC 8340) for extension instance data. These callbacks are called for extension instances that have
Michal Vaskoc7262cb2022-11-09 09:41:56 +010082 * parents of type ::LY_STMT_MODULE, ::LY_STMT_SUBMODULE. Or these callbacks are called if the printer_tree finds
aPiecek03cb4872022-10-24 10:31:51 +020083 * a compiled/parsed data-node containing an extension instance. The callbacks should then decide which nodes
84 * should be printed within the extension instance. In addition, it is possible to register additional callbacks
85 * to the printer_tree context to override the form of the each node in the extension instance.
86 *
Michal Vaskoc7262cb2022-11-09 09:41:56 +010087 * The last callback, ::lyplg_ext.cfree, is supposed to free all the data allocated by the ::lyplg_ext.compile callback.
88 * To free the data created by helper function ::lyplg_ext_compile_extension_instance(), the plugin can used
89 * ::lyplg_ext_cfree_instance_substatements().
Radek Krejci75104122021-04-01 15:37:45 +020090 *
91 * The plugin information contains also the plugin identifier (::lyplg_type.id). This string can serve to identify the
92 * specific plugin responsible to storing data value. In case the user can recognize the id string, it can access the
93 * plugin specific data with the appropriate knowledge of its structure.
94 *
Michal Vaskoc7262cb2022-11-09 09:41:56 +010095 * Logging information from an extension plugin is possible via ::lyplg_ext_parse_log() and ::lyplg_ext_compile_log() functions.
Radek Krejci75104122021-04-01 15:37:45 +020096 */
97
98/**
99 * @defgroup pluginsExtensions Plugins: Extensions
100 *
101 * Structures and functions to for libyang plugins implementing specific YANG extensions defined in YANG modules. For more
102 * information, see @ref howtoPluginsTypes.
103 *
104 * This part of libyang API is available by including `<libyang/plugins_ext.h>` header file.
Radek Krejcid7e8a622018-10-29 15:54:55 +0100105 *
106 * @{
107 */
108
109/**
Radek Krejci0935f412019-08-20 16:15:18 +0200110 * @brief Extensions API version
111 */
Michal Vasko0b50f6b2022-10-05 15:07:55 +0200112#define LYPLG_EXT_API_VERSION 6
Radek Krejci0935f412019-08-20 16:15:18 +0200113
114/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200115 * @brief Mask for an operation statement.
Michal Vaskob4750962022-10-06 15:33:35 +0200116 *
Michal Vasko193dacd2022-10-13 08:43:05 +0200117 * This mask matches action and RPC.
Michal Vaskob4750962022-10-06 15:33:35 +0200118 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200119#define LY_STMT_OP_MASK (LY_STMT_ACTION | LY_STMT_RPC)
Michal Vaskob4750962022-10-06 15:33:35 +0200120
121/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200122 * @brief Mask for a data node statement.
Michal Vaskob4750962022-10-06 15:33:35 +0200123 *
Michal Vasko193dacd2022-10-13 08:43:05 +0200124 * This mask matches anydata, anyxml, case, choice, container, leaf, leaf-list, and list.
Michal Vaskob4750962022-10-06 15:33:35 +0200125 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200126#define LY_STMT_DATA_NODE_MASK (LY_STMT_ANYDATA | LY_STMT_ANYXML | LY_STMT_CASE | LY_STMT_CHOICE | LY_STMT_CONTAINER |\
127 LY_STMT_LEAF | LY_STMT_LEAF_LIST | LY_STMT_LIST)
Michal Vaskob4750962022-10-06 15:33:35 +0200128
129/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200130 * @brief Mask for a node statement.
Michal Vaskob4750962022-10-06 15:33:35 +0200131 *
Michal Vasko193dacd2022-10-13 08:43:05 +0200132 * This mask matches notification, input, output, action, RPC, anydata, anyxml, augment, case, choice, container,
133 * grouping, leaf, leaf-list, list, and uses.
Michal Vaskob4750962022-10-06 15:33:35 +0200134 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200135#define LY_STMT_NODE_MASK 0xFFFF
Michal Vaskob4750962022-10-06 15:33:35 +0200136
137/**
138 * @brief List of YANG statements
Michal Vasko193dacd2022-10-13 08:43:05 +0200139 *
140 * Their description mentions what types are stored for each statement. Note that extension instance storage
141 * always stores a pointer to the type, not the type itself.
Michal Vaskob4750962022-10-06 15:33:35 +0200142 */
143enum ly_stmt {
144 LY_STMT_NONE = 0,
145
Michal Vasko193dacd2022-10-13 08:43:05 +0200146 LY_STMT_NOTIFICATION = 0x0001, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_notif *`
147 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_notif *` */
148 LY_STMT_INPUT = 0x0002, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_action_inout *`
149 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_action_inout *` */
150 LY_STMT_OUTPUT = 0x0004, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_action_inout *`
151 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_action_inout *` */
152 LY_STMT_ACTION = 0x0008, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_action *`
153 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_action *` */
154 LY_STMT_RPC = 0x0010, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_action *`
155 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_action *` */
156 LY_STMT_ANYDATA = 0x0020, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_anydata *`
157 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_anydata *` */
158 LY_STMT_ANYXML = 0x0040, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_anydata *`
159 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_anydata *` */
160 LY_STMT_AUGMENT = 0x0080, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_augment *`
161 ::lysc_ext_substmt.storage - not compiled
162 ::lysc_ext_instance.parent - `struct lysc_node *` */
163 LY_STMT_CASE = 0x0100, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_case *`
164 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_case *` */
165 LY_STMT_CHOICE = 0x0200, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_choice *`
166 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_choice *` */
167 LY_STMT_CONTAINER = 0x0400, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_container *`
168 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_container *` */
169 LY_STMT_GROUPING = 0x0800, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_grp *`
170 ::lysc_ext_substmt.storage - not compiled
171 ::lysc_ext_instance.parent - `struct lysc_node *` */
172 LY_STMT_LEAF = 0x1000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_leaf *`
173 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_leaf *` */
174 LY_STMT_LEAF_LIST = 0x2000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_leaflist *`
175 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_leaflist *` */
176 LY_STMT_LIST = 0x4000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_list *`
177 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node_list *` */
178 LY_STMT_USES = 0x8000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_node_uses *`
179 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_node *` */
Michal Vaskob4750962022-10-06 15:33:35 +0200180
Michal Vasko193dacd2022-10-13 08:43:05 +0200181 LY_STMT_ARGUMENT = 0x10000, /**< ::lysp_ext_substmt.storage - `const char *`
182 ::lysp_ext_instance.parent - `struct lysp_ext *`
183 ::lysc_ext_substmt.storage - `const char *`
184 ::lysc_ext_instance.parent - `struct lysc_ext *` */
185 LY_STMT_BASE = 0x20000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char **`[]
186 ::lysc_ext_substmt.storage - not compiled
187 ::lysc_ext_instance.parent - `struct lysc_ident *` */
188 LY_STMT_BELONGS_TO = 0x30000, /**< ::lysp_ext_substmt.storage - `const char *`
189 ::lysp_ext_instance.parent - `struct lysp_submodule *`
190 ::lysc_ext_substmt.storage - not compiled
191 ::lysc_ext_instance.parent - `struct lysc_module *` */
192 LY_STMT_BIT = 0x40000, /**< ::lysp_ext_substmt.storage - `struct lysp_type_enum *`[]
193 ::lysp_ext_instance.parent - `struct lysp_type_enum *`
194 ::lysc_ext_substmt.storage - `struct lysc_type_bitenum_item *`[]
195 ::lysc_ext_instance.parent - `struct lysc_type_bitenum_item *` */
196 LY_STMT_CONFIG = 0x50000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `uint16_t *`
197 ::lysc_ext_substmt.storage - `uint16_t *`
198 ::lysc_ext_instance.parent - `struct lysc_node *` */
199 LY_STMT_CONTACT = 0x60000, /**< ::lysp_ext_substmt.storage - `const char *`
200 ::lysp_ext_instance.parent - `struct lysp_(sub)module *`
201 ::lysc_ext_substmt.storage - `const char *`
202 ::lysc_ext_instance.parent - `struct lysc_module *` */
203 LY_STMT_DEFAULT = 0x70000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_qname *`
204 ::lysc_ext_substmt.storage - not compiled
205 ::lysc_ext_instance.parent - `struct lysc_node *`, `struct lysc_type *` (typedef) */
206 LY_STMT_DESCRIPTION = 0x80000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
207 ::lysc_ext_substmt.storage - `const char *`
208 ::lysc_ext_instance.parent - compiled parent statement */
209 LY_STMT_DEVIATE = 0x90000, /**< ::lysp_ext_substmt.storage - `struct lysp_deviate *`[]
210 ::lysp_ext_instance.parent - `struct lysp_deviate *`
211 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
212 LY_STMT_DEVIATION = 0xA0000, /**< ::lysp_ext_substmt.storage - `struct lysp_deviation *`[]
213 ::lysp_ext_instance.parent - `struct lysp_deviation *`
214 ::lysc_ext_substmt.storage - not compiled
215 ::lysc_ext_instance.parent - `struct lysc_node *` */
216 LY_STMT_ENUM = 0xB0000, /**< ::lysp_ext_substmt.storage - `struct lysp_type_enum *`[]
217 ::lysp_ext_instance.parent - `struct lysp_type_enum *`
218 ::lysc_ext_substmt.storage - `struct lysc_type_bitenum_item *`[]
219 ::lysc_ext_instance.parent - `struct lysc_type_bitenum_item *` */
220 LY_STMT_ERROR_APP_TAG = 0xC0000, /**< ::lysp_ext_substmt.storage - `const char *`
221 ::lysp_ext_instance.parent - `struct lysp_restr *`
222 ::lysc_ext_substmt.storage - `const char *`
223 ::lysc_ext_instance.parent - compiled restriction structure */
224 LY_STMT_ERROR_MESSAGE = 0xD0000, /**< ::lysp_ext_substmt.storage - `const char *`
225 ::lysp_ext_instance.parent - `struct lysp_restr *`
226 ::lysc_ext_substmt.storage - `const char *`
227 ::lysc_ext_instance.parent - compiled restriction structure */
228 LY_STMT_EXTENSION = 0xE0000, /**< ::lysp_ext_substmt.storage - `struct lysp_ext *`[]
229 ::lysp_ext_instance.parent - `struct lysp_ext *`
230 ::lysc_ext_substmt.storage - not compiled explicitly
231 ::lysc_ext_instance.parent - `struct lysc_ext *` */
232 LY_STMT_EXTENSION_INSTANCE = 0xF0000, /**< ::lysp_ext_substmt.storage - `struct lysp_ext_instance *`[]
233 ::lysc_ext_substmt.storage - `struct lysc_ext_instance *`[] */
234 LY_STMT_FEATURE = 0x100000, /**< ::lysp_ext_substmt.storage - `struct lysp_feature *`[]
235 ::lysp_ext_instance.parent - `struct lysp_feature *`
236 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
237 LY_STMT_FRACTION_DIGITS = 0x110000, /**< ::lysp_ext_substmt.storage - `uint8_t *`
238 ::lysp_ext_instance.parent - `struct lysp_type *`
239 ::lysc_ext_substmt.storage - `uint8_t *`
240 ::lysc_ext_instance.parent - `struct lysc_type *` */
241 LY_STMT_IDENTITY = 0x120000, /**< ::lysp_ext_substmt.storage - `struct lysp_ident *`[]
242 ::lysp_ext_instance.parent - `struct lysp_ident *`
243 ::lysc_ext_substmt.storage - `struct lysc_ident *`[]
244 ::lysc_ext_instance.parent - `struct lysc_ident *` */
245 LY_STMT_IF_FEATURE = 0x130000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_qname *`[]
246 ::lysc_ext_substmt.storage - no storage, evaluated when compiled
247 ::lysc_ext_instance.parent - compiled parent statement */
248 LY_STMT_IMPORT = 0x140000, /**< ::lysp_ext_substmt.storage - `struct lysp_import *`[]
249 ::lysp_ext_instance.parent - `struct lysp_import *`
250 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
251 LY_STMT_INCLUDE = 0x150000, /**< ::lysp_ext_substmt.storage - `struct lysp_include *`[]
252 ::lysp_ext_instance.parent - `struct lysp_include *`
253 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
254 LY_STMT_KEY = 0x160000, /**< ::lysp_ext_substmt.storage - `const char *`
255 ::lysp_ext_instance.parent - `struct lysp_node_list *`
256 ::lysc_ext_substmt.storage - `const char *`
257 ::lysc_ext_instance.parent - `struct lysc_node_list *` */
258 LY_STMT_LENGTH = 0x170000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_restr *`
259 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_range *` */
260 LY_STMT_MANDATORY = 0x180000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `uint16_t *`
261 ::lysc_ext_substmt.storage - `uint16_t *`
262 ::lysc_ext_instance.parent - `struct lysc_node *` */
263 LY_STMT_MAX_ELEMENTS = 0x190000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `uint32_t *`
264 ::lysc_ext_substmt.storage - `uint32_t *`
265 ::lysc_ext_instance.parent - `struct lysc_node_list *` */
266 LY_STMT_MIN_ELEMENTS = 0x1A0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `uint32_t *`
267 ::lysc_ext_substmt.storage - `uint32_t *`
268 ::lysc_ext_instance.parent - `struct lysc_node_list *` */
269 LY_STMT_MODIFIER = 0x1B0000, /**< ::lysp_ext_substmt.storage - `const char *`
270 ::lysp_ext_instance.parent - `struct lysp_restr *`
271 ::lysc_ext_substmt.storage - `const char *`
272 ::lysc_ext_instance.parent - `struct lysc_pattern *` */
273 LY_STMT_MODULE = 0x1C0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_module *`
274 ::lysc_ext_substmt.storage - not compiled
275 ::lysc_ext_instance.parent - `struct lysc_module *` */
276 LY_STMT_MUST = 0x1D0000, /**< ::lysp_ext_substmt.storage - `struct lysp_restr *`[]
277 ::lysp_ext_instance.parent - `struct lysp_restr *`
278 ::lysc_ext_substmt.storage - `struct lysc_must *`[]
279 ::lysc_ext_instance.parent - `struct lysc_must *` */
280 LY_STMT_NAMESPACE = 0x1E0000, /**< ::lysp_ext_substmt.storage - `const char *`
281 ::lysp_ext_instance.parent - `struct lysp_module *`
282 ::lysc_ext_substmt.storage - `const char *`
283 ::lysc_ext_instance.parent - `struct lysc_module *` */
284 LY_STMT_ORDERED_BY = 0x1F0000, /**< ::lysp_ext_substmt.storage - `uint16_t *`
285 ::lysp_ext_instance.parent - `struct lysp_node *`
286 ::lysc_ext_substmt.storage - `uint16_t *`
287 ::lysc_ext_instance.parent - `struct lysc_node *` */
288 LY_STMT_ORGANIZATION = 0x200000, /**< ::lysp_ext_substmt.storage - `const char *`
289 ::lysp_ext_instance.parent - `struct lysp_(sub)module *`
290 ::lysc_ext_substmt.storage - `const char *`
291 ::lysc_ext_instance.parent - `struct lysc_module *` */
292 LY_STMT_PATH = 0x210000, /**< ::lysp_ext_substmt.storage - `struct lyxp_expr *`
293 ::lysp_ext_instance.parent - `struct lysp_type *`
294 ::lysc_ext_substmt.storage - not compiled
295 ::lysc_ext_instance.parent - `struct lysc_type *` */
296 LY_STMT_PATTERN = 0x220000, /**< ::lysp_ext_substmt.storage - `struct lysp_restr *`[]
297 ::lysp_ext_instance.parent - `struct lysp_restr *`
298 ::lysc_ext_substmt.storage - `struct lysc_pattern **`[]
299 ::lysc_ext_instance.parent - `struct lysc_pattern *` */
300 LY_STMT_POSITION = 0x230000, /**< ::lysp_ext_substmt.storage - `int64_t *`
301 ::lysp_ext_instance.parent - `struct lysp_type_enum *`
302 ::lysc_ext_substmt.storage - `int64_t *`
303 ::lysc_ext_instance.parent - `struct lysc_type_bitenum_item *` */
304 LY_STMT_PREFIX = 0x240000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
305 ::lysc_ext_substmt.storage - not compiled
306 ::lysc_ext_instance.parent - `struct lysc_module *` */
307 LY_STMT_PRESENCE = 0x250000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
308 ::lysc_ext_substmt.storage - `const char *`
309 ::lysc_ext_instance.parent - `struct lysc_node_container *` */
310 LY_STMT_RANGE = 0x260000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_restr *`
311 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_range *` */
312 LY_STMT_REFERENCE = 0x270000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
313 ::lysc_ext_substmt.storage - `const char *`
314 ::lysc_ext_instance.parent - compiled parent statement */
315 LY_STMT_REFINE = 0x280000, /**< ::lysp_ext_substmt.storage - `struct lysp_refine *`[]
316 ::lysp_ext_instance.parent - `struct lysp_refine *`
317 ::lysc_ext_substmt.storage - not compiled
318 ::lysc_ext_instance.parent - `struct lysc_node *` */
319 LY_STMT_REQUIRE_INSTANCE = 0x290000, /**< ::lysp_ext_substmt.storage - `uint8_t *`
320 ::lysp_ext_instance.parent - `struct lysp_type *`
321 ::lysc_ext_substmt.storage - `uint8_t *`
322 ::lysc_ext_instance.parent - `struct lysc_type *` */
323 LY_STMT_REVISION = 0x2A0000, /**< ::lysp_ext_substmt.storage - `struct lysp_revision *`[]
324 ::lysp_ext_instance.parent - `struct lysp_revision *`
325 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
326 LY_STMT_REVISION_DATE = 0x2B0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
327 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - not compiled */
328 LY_STMT_STATUS = 0x2C0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `uint16_t *`
329 ::lysc_ext_substmt.storage - `uint16_t *`
330 ::lysc_ext_instance.parent - compiled parent statement */
331 LY_STMT_SUBMODULE = 0x2D0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_submodule *`
332 ::lysc_ext_substmt.storage - not compiled
333 ::lysc_ext_instance.parent - `struct lysc_module *` */
334 LY_STMT_TYPE = 0x2E0000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_type *`
335 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_type *` */
336 LY_STMT_TYPEDEF = 0x2F0000, /**< ::lysp_ext_substmt.storage - `struct lysp_tpdf *`[]
337 ::lysp_ext_instance.parent - `struct lysp_tpdf *`
338 ::lysc_ext_substmt.storage - not compiled
339 ::lysc_ext_instance.parent - `struct lysc_type *` */
340 LY_STMT_UNIQUE = 0x300000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_qname *`[]
341 ::lysc_ext_substmt.storage - not compiled
342 ::lysc_ext_instance.parent - `struct lysc_node_list *` */
343 LY_STMT_UNITS = 0x310000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `const char *`
344 ::lysc_ext_substmt.storage - `const char *`
345 ::lysc_ext_instance.parent - `struct lysc_node *`, `struct lysc_type *` (typedef) */
346 LY_STMT_VALUE = 0x320000, /**< ::lysp_ext_substmt.storage - `int64_t *`
347 ::lysp_ext_instance.parent - `struct lysp_type_enum *`
348 ::lysc_ext_substmt.storage - `int64_t *`
349 ::lysc_ext_instance.parent - `struct lysc_type_bitenum_item *` */
350 LY_STMT_WHEN = 0x330000, /**< ::lysp_ext_substmt.storage and ::lysp_ext_instance.parent - `struct lysp_when *`
351 ::lysc_ext_substmt.storage and ::lysc_ext_instance.parent - `struct lysc_when *` */
352 LY_STMT_YANG_VERSION = 0x340000, /**< ::lysp_ext_substmt.storage - `uint8_t *`
353 ::lysp_ext_instance.parent - `struct lysp_(sub)module *`
354 ::lysc_ext_substmt.storage - not compiled
355 ::lysc_ext_instance.parent - `struct lysc_module *` */
356 LY_STMT_YIN_ELEMENT = 0x350000, /**< ::lysp_ext_substmt.storage - `uint16_t *`
357 ::lysp_ext_instance.parent - `struct lysp_ext *`
358 ::lysc_ext_substmt.storage - not compiled
359 ::lysc_ext_instance.parent - `struct lysc_ext *` */
Michal Vaskob4750962022-10-06 15:33:35 +0200360
361 /* separated from the list of statements
362 * the following tokens are part of the syntax and parsers have to work
363 * with them, but they are not a standard YANG statements
364 */
365 LY_STMT_SYNTAX_SEMICOLON,
366 LY_STMT_SYNTAX_LEFT_BRACE,
367 LY_STMT_SYNTAX_RIGHT_BRACE,
368
369 /*
370 * YIN-specific tokens, still they are part of the syntax, but not the standard statements
371 */
372 LY_STMT_ARG_TEXT,
373 LY_STMT_ARG_VALUE
374};
375
376/**
Michal Vasko9c3556a2022-10-06 16:08:47 +0200377 * @brief Structure representing a generic parsed YANG substatement in an extension instance.
Michal Vaskob4750962022-10-06 15:33:35 +0200378 */
379struct lysp_stmt {
380 const char *stmt; /**< identifier of the statement */
381 const char *arg; /**< statement's argument */
382 LY_VALUE_FORMAT format; /**< prefix format of the identifier/argument (::LY_VALUE_XML is YIN format) */
383 void *prefix_data; /**< Format-specific data for prefix resolution (see ly_resolve_prefix()) */
384
385 struct lysp_stmt *next; /**< link to the next statement */
386 struct lysp_stmt *child; /**< list of the statement's substatements (linked list) */
387 uint16_t flags; /**< statement flags, can be set to LYS_YIN_ATTR */
388 enum ly_stmt kw; /**< numeric respresentation of the stmt value */
389};
390
391/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200392 * @brief Structure representing a parsed known YANG substatement in an extension instance.
393 */
394struct lysp_ext_substmt {
395 enum ly_stmt stmt; /**< parsed substatement */
396 void *storage; /**< pointer to the parsed storage of the statement according to the specific
397 lys_ext_substmt::stmt */
398};
399
400/**
401 * @brief YANG extension parsed instance.
Michal Vaskob4750962022-10-06 15:33:35 +0200402 */
403struct lysp_ext_instance {
404 const char *name; /**< extension identifier, including possible prefix */
405 const char *argument; /**< optional value of the extension's argument */
406 LY_VALUE_FORMAT format; /**< prefix format of the extension name/argument (::LY_VALUE_XML is YIN format) */
Michal Vasko193dacd2022-10-13 08:43:05 +0200407 void *prefix_data; /**< format-specific data for prefix resolution (see ly_resolve_prefix()) */
408 struct lysp_ext *def; /**< pointer to the extension definition */
Michal Vaskob4750962022-10-06 15:33:35 +0200409
Michal Vasko193dacd2022-10-13 08:43:05 +0200410 void *parent; /**< pointer to the parent statement holding the extension instance(s), use
411 ::lysp_ext_instance#parent_stmt to access the value/structure */
412 enum ly_stmt parent_stmt; /**< type of the parent statement */
413 LY_ARRAY_COUNT_TYPE parent_stmt_index; /**< index of the stamenet in case the parent does not point to the parent
414 statement directly and it is an array */
415 uint16_t flags; /**< ::LYS_INTERNAL value (@ref snodeflags) */
Michal Vaskob4750962022-10-06 15:33:35 +0200416
Michal Vasko193dacd2022-10-13 08:43:05 +0200417 const struct lyplg_ext_record *record; /**< extension definition plugin record, if any */
418 struct lysp_ext_substmt *substmts; /**< list of supported known YANG statements with the pointer to their
419 parsed data ([sized array](@ref sizedarrays)) */
420 void *parsed; /**< private plugin parsed data */
421 struct lysp_stmt *child; /**< list of generic (unknown) YANG statements */
Michal Vaskob4750962022-10-06 15:33:35 +0200422};
423
424/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200425 * @brief Structure representing a compiled known YANG substatement in an extension instance.
Michal Vaskob4750962022-10-06 15:33:35 +0200426 */
427struct lysc_ext_substmt {
Michal Vasko193dacd2022-10-13 08:43:05 +0200428 enum ly_stmt stmt; /**< compiled substatement */
429 void *storage; /**< pointer to the compiled storage of the statement according to the specific
430 lys_ext_substmt::stmt */
Michal Vaskob4750962022-10-06 15:33:35 +0200431};
432
433/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200434 * @brief YANG extension compiled instance.
Michal Vaskob4750962022-10-06 15:33:35 +0200435 */
436struct lysc_ext_instance {
Michal Vasko193dacd2022-10-13 08:43:05 +0200437 struct lysc_ext *def; /**< pointer to the extension definition */
438 const char *argument; /**< optional value of the extension's argument */
439 struct lys_module *module; /**< module where the extension instantiated is defined */
440 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vaskob4750962022-10-06 15:33:35 +0200441
Michal Vasko193dacd2022-10-13 08:43:05 +0200442 void *parent; /**< pointer to the parent element holding the extension instance(s), use
443 ::lysc_ext_instance#parent_stmt to access the value/structure */
444 enum ly_stmt parent_stmt; /**< type of the parent statement */
445 LY_ARRAY_COUNT_TYPE parent_stmt_index; /**< index of the stamenet in case the parent does not point to the parent
446 statement directly and it is an array */
447
448 struct lysc_ext_substmt *substmts; /**< list of supported known YANG statements with the pointer to their
449 compiled data ([sized array](@ref sizedarrays)) */
450 void *compiled; /**< private plugin compiled data */
Michal Vaskob4750962022-10-06 15:33:35 +0200451};
452
453/**
Radek Krejcia6f61e72021-03-24 21:00:19 +0100454 * @brief Macro to define plugin information in external plugins
455 *
456 * Use as follows:
457 * LYPLG_EXTENSIONS = {{<filled information of ::lyplg_ext_record>}, ..., {0}};
Radek Krejci0935f412019-08-20 16:15:18 +0200458 */
Radek Krejcia6f61e72021-03-24 21:00:19 +0100459#define LYPLG_EXTENSIONS \
460 uint32_t plugins_extensions_apiver__ = LYPLG_EXT_API_VERSION; \
461 const struct lyplg_ext_record plugins_extensions__[]
Radek Krejci0935f412019-08-20 16:15:18 +0200462
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100463/**
464 * @defgroup pluginsExtensionsParse Plugins: Extensions parsing support
465 * @ingroup pluginsExtensions
466 *
467 * Implementing extension plugin parse callback.
468 *
469 * @{
Michal Vasko193dacd2022-10-13 08:43:05 +0200470 */
471
472/**
473 * @brief Callback for parsing extension instance substatements.
474 *
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100475 * All known YANG substatements can easily be parsed using ::lyplg_ext_parse_extension_instance.
Michal Vasko193dacd2022-10-13 08:43:05 +0200476 *
477 * @param[in] pctx Parse context.
478 * @param[in,out] ext Parsed extension instance data.
479 * @return LY_SUCCESS on success.
480 * @return LY_ENOT if the extension instance is not supported and should be removed.
481 * @return LY_ERR error on error.
482 */
483typedef LY_ERR (*lyplg_ext_parse_clb)(struct lysp_ctx *pctx, struct lysp_ext_instance *ext);
484
485/**
486 * @brief Log a message from an extension plugin using the parsed extension instance.
487 *
488 * @param[in] pctx Parse context to use.
489 * @param[in] ext Parsed extensiopn instance.
490 * @param[in] level Log message level (error, warning, etc.)
491 * @param[in] err_no Error type code.
492 * @param[in] format Format string to print.
493 * @param[in] ... Format variable parameters.
494 */
495LIBYANG_API_DECL void lyplg_ext_parse_log(const struct lysp_ctx *pctx, const struct lysp_ext_instance *ext,
496 LY_LOG_LEVEL level, LY_ERR err_no, const char *format, ...);
497
498/**
499 * @brief Get current parsed module from a parse context.
500 *
501 * @param[in] pctx Parse context.
502 * @return Current (local) parse mod.
503 */
504LIBYANG_API_DECL const struct lysp_module *lyplg_ext_parse_get_cur_pmod(const struct lysp_ctx *pctx);
505
506/**
507 * @brief Parse substatements of an extension instance.
508 *
509 * Uses standard libyang schema compiler to transform YANG statements into the parsed schema structures. The plugins are
510 * supposed to use this function when the extension instance's substatements can be parsed in a standard way.
511 *
512 * @param[in] pctx Parse context.
513 * @param[in,out] ext Parsed extension instance with the prepared ::lysp_ext_instance.substmts array, which will be
514 * updated by storing the parsed data.
515 * @return LY_SUCCESS on success.
516 * @return LY_ERR error on error.
517 */
518LIBYANG_API_DECL LY_ERR lyplg_ext_parse_extension_instance(struct lysp_ctx *pctx, struct lysp_ext_instance *ext);
519
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100520/** @} pluginsExtensionsParse */
521
522/**
523 * @defgroup pluginsExtensionsCompile Plugins: Extensions compilation support
524 * @ingroup pluginsExtensions
525 *
526 * Implementing extension plugin compile callback.
527 *
528 * @{
Michal Vasko193dacd2022-10-13 08:43:05 +0200529 */
530
531/**
532 * @defgroup scflags Schema compile flags
533 *
534 * Flags to modify schema compilation process and change the way how the particular statements are being compiled. *
535 * @{
536 */
537#define LYS_COMPILE_GROUPING 0x01 /**< Compiling (validation) of a non-instantiated grouping.
538 In this case not all the restrictions are checked since they can
539 be valid only in the real placement of the grouping. This is
540 the case of any restriction that needs to look out of the statements
541 themselves, since the context is not known. */
542#define LYS_COMPILE_DISABLED 0x02 /**< Compiling a disabled subtree (by its if-features). Meaning
543 it will be removed at the end of compilation and should not be
544 added to any unres sets. */
545#define LYS_COMPILE_NO_CONFIG 0x04 /**< ignore config statements, neither inherit config value */
546#define LYS_COMPILE_NO_DISABLED 0x08 /**< ignore if-feature statements */
547
548#define LYS_COMPILE_RPC_INPUT (LYS_IS_INPUT | LYS_COMPILE_NO_CONFIG) /**< Internal option when compiling schema tree of RPC/action input */
549#define LYS_COMPILE_RPC_OUTPUT (LYS_IS_OUTPUT | LYS_COMPILE_NO_CONFIG) /**< Internal option when compiling schema tree of RPC/action output */
550#define LYS_COMPILE_NOTIFICATION (LYS_IS_NOTIF | LYS_COMPILE_NO_CONFIG) /**< Internal option when compiling schema tree of Notification */
551
552/** @} scflags */
Radek Krejci38d85362019-09-05 16:26:38 +0200553
554/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200555 * @brief Callback to compile extension from the lysp_ext_instance to the lysc_ext_instance. The later structure is generally prepared
556 * and only the extension specific data are supposed to be added (if any).
557 *
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100558 * The parsed generic statements can be processed by the callback on its own or the ::lyplg_ext_compile_extension_instance()
Radek Krejciadcf63d2021-02-09 10:21:18 +0100559 * function can be used to let the compilation to libyang following the standard rules for processing the YANG statements.
560 *
Radek Krejci0e59c312019-08-15 15:34:15 +0200561 * @param[in] cctx Current compile context.
Michal Vasko193dacd2022-10-13 08:43:05 +0200562 * @param[in] extp Parsed extension instance data.
563 * @param[in,out] ext Prepared compiled extension instance structure where an addition, extension-specific, data are
Michal Vaskoddd76592022-01-17 13:34:48 +0100564 * supposed to be placed for later use (data validation or use of external tool).
Radek Krejci0e59c312019-08-15 15:34:15 +0200565 * @return LY_SUCCESS in case of success.
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100566 * @return LY_ENOT in case the extension instance is not supported and should be removed.
Michal Vasko193dacd2022-10-13 08:43:05 +0200567 * @return LY_ERR error on error.
Radek Krejci0e59c312019-08-15 15:34:15 +0200568 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200569typedef LY_ERR (*lyplg_ext_compile_clb)(struct lysc_ctx *cctx, const struct lysp_ext_instance *extp,
570 struct lysc_ext_instance *ext);
571
572/**
573 * @brief Log a message from an extension plugin using the compiled extension instance.
574 *
575 * @param[in] cctx Optional compile context to generate the path from.
576 * @param[in] ext Compiled extension instance.
577 * @param[in] level Log message level (error, warning, etc.)
578 * @param[in] err_no Error type code.
579 * @param[in] format Format string to print.
580 */
581LIBYANG_API_DECL void lyplg_ext_compile_log(const struct lysc_ctx *cctx, const struct lysc_ext_instance *ext,
582 LY_LOG_LEVEL level, LY_ERR err_no, const char *format, ...);
583
584/**
585 * @brief Log a message from an extension plugin using the compiled extension instance with an explicit error path.
586 *
587 * @param[in] path Log error path to use.
588 * @param[in] ext Compiled extension instance.
589 * @param[in] level Log message level (error, warning, etc.)
590 * @param[in] err_no Error type code.
591 * @param[in] format Format string to print.
592 */
593LIBYANG_API_DECL void lyplg_ext_compile_log_path(const char *path, const struct lysc_ext_instance *ext,
594 LY_LOG_LEVEL level, LY_ERR err_no, const char *format, ...);
595
596/**
597 * @brief YANG schema compilation context getter for libyang context.
598 *
599 * @param[in] ctx YANG schema compilation context.
600 * @return libyang context connected with the compilation context.
601 */
602LIBYANG_API_DECL struct ly_ctx *lyplg_ext_compile_get_ctx(const struct lysc_ctx *ctx);
603
604/**
605 * @brief YANG schema compilation context getter for compilation options.
606 *
607 * @param[in] ctx YANG schema compilation context.
608 * @return pointer to the compilation options to allow modifying them with @ref scflags values.
609 */
610LIBYANG_API_DECL uint32_t *lyplg_ext_compile_get_options(const struct lysc_ctx *ctx);
611
612/**
613 * @brief YANG schema compilation context getter for current module.
614 *
615 * @param[in] ctx YANG schema compilation context.
616 * @return current module.
617 */
618LIBYANG_API_DECL const struct lys_module *lyplg_ext_compile_get_cur_mod(const struct lysc_ctx *ctx);
619
620/**
621 * @brief YANG schema compilation context getter for currently processed module.
622 *
623 * @param[in] ctx YANG schema compilation context.
624 * @return Currently processed module.
625 */
626LIBYANG_API_DECL struct lysp_module *lyplg_ext_compile_get_pmod(const struct lysc_ctx *ctx);
627
628/**
629 * @brief Compile substatements of an extension instance.
630 *
631 * Uses standard libyang schema compiler to transform YANG statements into the compiled schema structures. The plugins are
632 * supposed to use this function when the extension instance's substatements are supposed to be compiled in a standard way
633 * (or if just the @ref scflags are enough to modify the compilation process).
634 *
635 * @param[in] ctx Compile context.
636 * @param[in] extp Parsed representation of the extension instance being processed.
637 * @param[in,out] ext Compiled extension instance with the prepared ::lysc_ext_instance.substmts array, which will be updated
638 * by storing the compiled data.
639 * @return LY_SUCCESS on success.
640 * @return LY_EVALID if compilation of the substatements fails.
641 * @return LY_ENOT if the extension is disabled (by if-feature) and should be ignored.
642 */
643LIBYANG_API_DECL LY_ERR lyplg_ext_compile_extension_instance(struct lysc_ctx *ctx, const struct lysp_ext_instance *extp,
644 struct lysc_ext_instance *ext);
645
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100646/** @} pluginsExtensionsCompile */
647
648/**
649 * @defgroup pluginsExtensionsSprinterInfo Plugins: Extensions schema info printer support
650 * @ingroup pluginsExtensions
651 *
652 * Implementing extension plugin schema info printer callback.
653 *
654 * @{
Michal Vasko193dacd2022-10-13 08:43:05 +0200655 */
Radek Krejci0e59c312019-08-15 15:34:15 +0200656
657/**
Michal Vaskoddd76592022-01-17 13:34:48 +0100658 * @brief Callback to print the compiled extension instance's private data in the INFO format.
659 *
660 * @param[in] ctx YANG printer context to provide output handler and other information for printing.
661 * @param[in] ext The compiled extension instance, mainly to access the extensions.
662 * @param[in,out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
663 * 1 otherwise.
664 * @return LY_SUCCESS when everything was fine, other LY_ERR values in case of failure
665 */
Michal Vasko941e0562022-10-18 10:35:00 +0200666typedef LY_ERR (*lyplg_ext_sprinter_info_clb)(struct lyspr_ctx *ctx, struct lysc_ext_instance *ext, ly_bool *flag);
Michal Vaskoddd76592022-01-17 13:34:48 +0100667
668/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200669 * @brief YANG printer context getter for output handler.
Radek Krejci0e59c312019-08-15 15:34:15 +0200670 *
Michal Vasko193dacd2022-10-13 08:43:05 +0200671 * @param[in] ctx YANG printer context.
672 * @return Output handler where the data are being printed. Note that the address of the handler pointer in the context is
673 * returned to allow to modify the handler.
Radek Krejci0e59c312019-08-15 15:34:15 +0200674 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200675LIBYANG_API_DECL struct ly_out **lyplg_ext_print_get_out(const struct lyspr_ctx *ctx);
676
677/**
678 * @brief YANG printer context getter for printer options.
679 *
680 * @param[in] ctx YANG printer context.
681 * @return pointer to the printer options to allow modifying them with @ref schemaprinterflags values.
682 */
683LIBYANG_API_DECL uint32_t *lyplg_ext_print_get_options(const struct lyspr_ctx *ctx);
684
685/**
686 * @brief YANG printer context getter for printer indentation level.
687 *
688 * @param[in] ctx YANG printer context.
689 * @return pointer to the printer's indentation level to allow modifying its value.
690 */
691LIBYANG_API_DECL uint16_t *lyplg_ext_print_get_level(const struct lyspr_ctx *ctx);
692
693/**
Michal Vasko941e0562022-10-18 10:35:00 +0200694 * @brief Print substatements of an extension instance in info format (compiled YANG).
Michal Vasko193dacd2022-10-13 08:43:05 +0200695 *
Michal Vasko941e0562022-10-18 10:35:00 +0200696 * Generic function to access YANG printer functions from the extension plugins (::lyplg_ext_sprinter_info_clb).
Michal Vasko193dacd2022-10-13 08:43:05 +0200697 *
698 * @param[in] ctx YANG printer context to provide output handler and other information for printing.
699 * @param[in] ext The compiled extension instance to access the extensions and substatements data.
700 * @param[in,out] flag Flag to be shared with the caller regarding the opening brackets - 0 if the '{' not yet printed,
701 * 1 otherwise.
702 */
Michal Vasko941e0562022-10-18 10:35:00 +0200703LIBYANG_API_DECL void lyplg_ext_print_info_extension_instance(struct lyspr_ctx *ctx, const struct lysc_ext_instance *ext,
Michal Vasko193dacd2022-10-13 08:43:05 +0200704 ly_bool *flag);
705
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100706/** @} pluginsExtensionsSprinterInfo */
707
708/**
709 * @defgroup pluginsExtensionsSprinterTree Plugins: Extensions schema parsed and compiled tree printer support
710 * @ingroup pluginsExtensions
711 *
712 * Implementing extension plugin schema parsed and compiled tree printer callback.
713 *
714 * @{
aPiecek03cb4872022-10-24 10:31:51 +0200715 */
716
717/**
718 * @brief Callback to print parent node of @p ext or to print the contents of the extension.
719 *
720 * Function is called in two different cases. If the printer_tree needs the tree-diagram form of a parent node,
721 * then @p ctx is set to NULL. In the second case, if printer_tree needs to print the contents of the extension,
722 * then @p ctx is set and function must prepare the nodes that should be printed using the
723 * lyplg_ext_sprinter_tree* functions.
724 *
725 * @param[in] ext Extension instance.
726 * @param[in,out] ctx Context for the tree printer. Extension contents can be inserted into it by functions
727 * lyplg_ext_sprinter_ctree_add_ext_nodes(), lyplg_ext_sprinter_ctree_add_nodes() or by their ptree alternatives.
728 * It parameter is set to NULL, then @p flags and @p add_opts are used by printer_tree.
729 * @param[out] flags Optional override tree-diagram \<flags\> in a parent node. If @p ctx is set, ignore this parameter.
730 * @param[out] add_opts Additional tree-diagram \<opts\> string in a parent node which is printed before \<opts\>. If @p ctx
731 * is set, ignore this parameter.
732 * @return LY_ERR value.
733 */
734typedef LY_ERR (*lyplg_ext_sprinter_ctree_clb)(struct lysc_ext_instance *ext, const struct lyspr_tree_ctx *ctx,
735 const char **flags, const char **add_opts);
736
737/**
738 * @brief Callback for rewriting the tree-diagram form of a specific node.
739 *
740 * If this callback is set, then it is called for each node that belongs to the extension instance.
741 *
742 * @param[in] node Node whose tree-diagram form can be modified by the function.
743 * @param[in,out] plugin_priv Private context set by plugin.
744 * @param[out] skip Flag set to 1 removes the node from printed diagram.
745 * @param[out] flags Override tree-diagram \<flags\> string in the @p node.
746 * @param[out] add_opts Additional tree-diagram \<opts\> string in the @p node which is printed before \<opts\>.
747 * @return LY_ERR value.
748 */
749typedef LY_ERR (*lyplg_ext_sprinter_ctree_override_clb)(const struct lysc_node *node, const void *plugin_priv,
750 ly_bool *skip, const char **flags, const char **add_opts);
751
752/**
753 * @brief Registration of printing a group of nodes, which is already in the extension.
754 *
755 * @param[in] ctx Context of printer_tree in which the group of nodes is saved and later printed.
756 * @param[in] ext Extension in which the group of nodes will be searched.
757 * @param[in] clb Override function that will be applied to each delivered node.
758 * @return LY_ERR value.
759 */
760LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_ctree_add_ext_nodes(const struct lyspr_tree_ctx *ctx,
761 struct lysc_ext_instance *ext, lyplg_ext_sprinter_ctree_override_clb clb);
762
763/**
764 * @brief Registration of printing the group of nodes which were defined in the plugin.
765 *
766 * @param[in] ctx Context of printer_tree in which the group of nodes is saved and later printed.
767 * @param[in] nodes Points to the first node in group.
768 * @param[in] clb Override function that will be applied to each delivered node.
769 * @return LY_ERR value.
770 */
771LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_ctree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysc_node *nodes,
772 lyplg_ext_sprinter_ctree_override_clb clb);
773
774/**
775 * @brief Registration of plugin-private data defined by the plugin that is shared between override_clb calls.
776 *
777 * @param[in] ctx Context of printer_tree in which plugin-private data will be saved.
778 * @param[in] plugin_priv Plugin-private data shared between oberride_clb calls.
779 * @param[in] free_clb Release function for @p plugin_priv.
780 * @return LY_ERR value.
781 */
782LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_tree_set_priv(const struct lyspr_tree_ctx *ctx, void *plugin_priv,
783 void (*free_clb)(void *plugin_priv));
784
785/**
786 * @copydoc lyplg_ext_sprinter_ctree_clb
787 */
788typedef LY_ERR (*lyplg_ext_sprinter_ptree_clb)(struct lysp_ext_instance *ext, const struct lyspr_tree_ctx *ctx,
789 const char **flags, const char **add_opts);
790
791/**
792 * @copydoc lyplg_ext_sprinter_ctree_override_clb
793 */
794typedef LY_ERR (*lyplg_ext_sprinter_ptree_override_clb)(const struct lysp_node *node, const void *plugin_priv,
795 ly_bool *skip, const char **flags, const char **add_opts);
796
797/**
798 * @copydoc lyplg_ext_sprinter_ctree_add_ext_nodes
799 */
800LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_ptree_add_ext_nodes(const struct lyspr_tree_ctx *ctx,
801 struct lysp_ext_instance *ext, lyplg_ext_sprinter_ptree_override_clb clb);
802
803/**
804 * @copydoc lyplg_ext_sprinter_ctree_add_nodes
805 */
806LIBYANG_API_DECL LY_ERR lyplg_ext_sprinter_ptree_add_nodes(const struct lyspr_tree_ctx *ctx, struct lysp_node *nodes,
807 lyplg_ext_sprinter_ptree_override_clb clb);
808
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100809/** @} pluginsExtensionsSprinterTree */
810
aPiecek03cb4872022-10-24 10:31:51 +0200811/*
Michal Vasko193dacd2022-10-13 08:43:05 +0200812 * data node
813 */
Radek Krejci0e59c312019-08-15 15:34:15 +0200814
815/**
Michal Vasko135719f2022-08-25 12:18:17 +0200816 * @brief Callback called for all data nodes connected to the extension instance.
817 *
818 * Can be used for additional data node validation. Is called only after the whole data tree is created and standard
Michal Vaskoeba23112022-08-26 08:35:41 +0200819 * validation succeeds. Not called when parsing data and ::LYD_PARSE_ONLY is used.
Michal Vasko135719f2022-08-25 12:18:17 +0200820 *
821 * @param[in] ext Compiled extension instance.
822 * @param[in] node Data node to process.
Michal Vaskoeba23112022-08-26 08:35:41 +0200823 * @param[in] validate_options Options used for the validation phase, see @ref datavalidationoptions.
Michal Vasko135719f2022-08-25 12:18:17 +0200824 * @return LY_SUCCESS on success.
825 * @return LY_ERR on error.
826 */
Michal Vaskoeba23112022-08-26 08:35:41 +0200827typedef LY_ERR (*lyplg_ext_data_node_clb)(struct lysc_ext_instance *ext, struct lyd_node *node, uint32_t validate_options);
Michal Vasko135719f2022-08-25 12:18:17 +0200828
Michal Vasko193dacd2022-10-13 08:43:05 +0200829/*
830 * snode
831 */
832
Michal Vasko135719f2022-08-25 12:18:17 +0200833/**
Michal Vasko8cc3f662022-03-29 11:25:51 +0200834 * @brief Callback for getting a schema node for a new YANG instance data described by an extension instance.
835 * Needed only if the extension instance supports some nested standard YANG data.
Radek Krejci0e59c312019-08-15 15:34:15 +0200836 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100837 * @param[in] ext Compiled extension instance.
Michal Vasko8cc3f662022-03-29 11:25:51 +0200838 * @param[in] parent Parsed parent data node. Set if @p sparent is NULL.
839 * @param[in] sparent Schema parent node. Set if @p parent is NULL.
840 * @param[in] prefix Element prefix, if any.
841 * @param[in] prefix_len Length of @p prefix.
842 * @param[in] format Format of @p prefix.
843 * @param[in] prefix_data Format-specific prefix data.
844 * @param[in] name Element name.
845 * @param[in] name_len Length of @p name.
846 * @param[out] snode Schema node to use for parsing the node.
Michal Vaskoddd76592022-01-17 13:34:48 +0100847 * @return LY_SUCCESS on success.
848 * @return LY_ENOT if the data are not described by @p ext.
849 * @return LY_ERR on error.
Radek Krejci0e59c312019-08-15 15:34:15 +0200850 */
Michal Vasko8cc3f662022-03-29 11:25:51 +0200851typedef LY_ERR (*lyplg_ext_data_snode_clb)(struct lysc_ext_instance *ext, const struct lyd_node *parent,
852 const struct lysc_node *sparent, const char *prefix, size_t prefix_len, LY_VALUE_FORMAT format, void *prefix_data,
853 const char *name, size_t name_len, const struct lysc_node **snode);
Radek Krejci0e59c312019-08-15 15:34:15 +0200854
Michal Vasko193dacd2022-10-13 08:43:05 +0200855/*
856 * validate
857 */
858
Radek Krejci0e59c312019-08-15 15:34:15 +0200859/**
Michal Vaskoddd76592022-01-17 13:34:48 +0100860 * @brief Callback for validating parsed YANG instance data described by an extension instance.
Radek Krejciadcf63d2021-02-09 10:21:18 +0100861 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100862 * This callback is used only for nested data definition (with a standard YANG schema parent).
Radek Krejciadcf63d2021-02-09 10:21:18 +0100863 *
Michal Vaskoddd76592022-01-17 13:34:48 +0100864 * @param[in] ext Compiled extension instance.
Michal Vasko9af7cd42022-04-05 12:26:09 +0200865 * @param[in] sibling First sibling with schema node returned by ::lyplg_ext_data_snode_clb.
Michal Vaskofbbea932022-06-07 11:00:55 +0200866 * @param[in] dep_tree Tree to be used for validating references from the operation subtree, if operation.
867 * @param[in] data_type Validated data type, can be ::LYD_TYPE_DATA_YANG, ::LYD_TYPE_RPC_YANG, ::LYD_TYPE_NOTIF_YANG,
868 * or ::LYD_TYPE_REPLY_YANG.
Michal Vaskoddd76592022-01-17 13:34:48 +0100869 * @param[in] val_opts Validation options, see @ref datavalidationoptions.
Michal Vaskof4c6f002022-04-01 09:12:22 +0200870 * @param[out] diff Optional diff with any changes made by the validation.
Michal Vaskoddd76592022-01-17 13:34:48 +0100871 * @return LY_SUCCESS on success.
872 * @return LY_ERR on error.
Radek Krejciadcf63d2021-02-09 10:21:18 +0100873 */
Michal Vaskofbbea932022-06-07 11:00:55 +0200874typedef LY_ERR (*lyplg_ext_data_validate_clb)(struct lysc_ext_instance *ext, struct lyd_node *sibling,
875 const struct lyd_node *dep_tree, enum lyd_type data_type, uint32_t val_opts, struct lyd_node **diff);
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100876
Michal Vasko193dacd2022-10-13 08:43:05 +0200877/*
878 * parse free
879 */
880
881/**
882 * @brief Callback to free the extension-specific data created by its parsing.
883 *
884 * @param[in] ctx libyang context.
885 * @param[in,out] ext Parsed extension structure to free.
886 */
887typedef void (*lyplg_ext_parse_free_clb)(const struct ly_ctx *ctx, struct lysp_ext_instance *ext);
888
889/**
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100890 * @brief Free the extension instance's data parsed with ::lyplg_ext_parse_extension_instance().
Michal Vasko193dacd2022-10-13 08:43:05 +0200891 *
892 * @param[in] ctx libyang context
893 * @param[in] substmts Extension instance substatements to free.
894 */
895LIBYANG_API_DECL void lyplg_ext_pfree_instance_substatements(const struct ly_ctx *ctx, struct lysp_ext_substmt *substmts);
896
897/*
898 * compile free
899 */
900
901/**
902 * @brief Callback to free the extension-specific data created by its compilation.
903 *
904 * @param[in] ctx libyang context.
905 * @param[in,out] ext Compiled extension structure to free.
906 */
907typedef void (*lyplg_ext_compile_free_clb)(const struct ly_ctx *ctx, struct lysc_ext_instance *ext);
908
909/**
Michal Vaskoc7262cb2022-11-09 09:41:56 +0100910 * @brief Free the extension instance's data compiled with ::lyplg_ext_compile_extension_instance().
Michal Vasko193dacd2022-10-13 08:43:05 +0200911 *
912 * @param[in] ctx libyang context
913 * @param[in] substmts Extension instance substatements to free.
914 */
915LIBYANG_API_DECL void lyplg_ext_cfree_instance_substatements(const struct ly_ctx *ctx, struct lysc_ext_substmt *substmts);
916
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100917/**
Radek Krejci0e59c312019-08-15 15:34:15 +0200918 * @brief Extension plugin implementing various aspects of a YANG extension
919 */
Radek Krejcicc9e30f2021-03-29 12:45:08 +0200920struct lyplg_ext {
Michal Vaskoddd76592022-01-17 13:34:48 +0100921 const char *id; /**< plugin identification (mainly for distinguish incompatible versions
922 of the plugins for external tools) */
Michal Vasko9c3556a2022-10-06 16:08:47 +0200923 lyplg_ext_parse_clb parse; /**< callback to parse the extension instance substatements */
Michal Vaskoddd76592022-01-17 13:34:48 +0100924 lyplg_ext_compile_clb compile; /**< callback to compile extension instance from the parsed data */
Michal Vasko941e0562022-10-18 10:35:00 +0200925 lyplg_ext_sprinter_info_clb printer_info; /**< callback to print the compiled content (info format) of the extension
926 instance */
aPiecek03cb4872022-10-24 10:31:51 +0200927 lyplg_ext_sprinter_ctree_clb printer_ctree; /**< callback to print tree format of compiled node containing the
928 compiled content of the extension instance */
929 lyplg_ext_sprinter_ptree_clb printer_ptree; /**< callback to print tree format of parsed node containing the
930 parsed content of the extension instance */
Michal Vasko135719f2022-08-25 12:18:17 +0200931 lyplg_ext_data_node_clb node; /**< callback to validate most relevant data instance for the extension
932 instance */
Michal Vasko8cc3f662022-03-29 11:25:51 +0200933 lyplg_ext_data_snode_clb snode; /**< callback to get schema node for nested YANG data */
Michal Vaskoddd76592022-01-17 13:34:48 +0100934 lyplg_ext_data_validate_clb validate; /**< callback to validate parsed data instances according to the extension
935 definition */
Michal Vasko193dacd2022-10-13 08:43:05 +0200936
937 lyplg_ext_parse_free_clb pfree; /**< free the extension-specific data created by its parsing */
938 lyplg_ext_compile_free_clb cfree; /**< free the extension-specific data created by its compilation */
Radek Krejci0e59c312019-08-15 15:34:15 +0200939};
940
Radek Krejci3e6632f2021-03-22 22:08:21 +0100941struct lyplg_ext_record {
942 /* plugin identification */
943 const char *module; /**< name of the module where the extension is defined */
944 const char *revision; /**< optional module revision - if not specified, the plugin applies to any revision,
945 which is not an optimal approach due to a possible future revisions of the module.
946 Instead, there should be defined multiple items in the plugins list, each with the
947 different revision, but all with the same pointer to the plugin functions. The
948 only valid use case for the NULL revision is the case the module has no revision. */
tadeas-vintrlik2aa36b42021-11-03 13:07:34 +0100949 const char *name; /**< YANG name of the extension */
Radek Krejci3e6632f2021-03-22 22:08:21 +0100950
951 /* runtime data */
952 struct lyplg_ext plugin; /**< data to utilize plugin implementation */
953};
954
Michal Vasko61ad1ff2022-02-10 15:48:39 +0100955/**
Michal Vaskob4750962022-10-06 15:33:35 +0200956 * @brief Stringify statement identifier.
957 *
958 * @param[in] stmt The statement identifier to stringify.
959 * @return Constant string representation of the given @p stmt.
960 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200961LIBYANG_API_DECL const char *lyplg_ext_stmt2str(enum ly_stmt stmt);
Michal Vaskob4750962022-10-06 15:33:35 +0200962
963/**
Michal Vaskob4750962022-10-06 15:33:35 +0200964 * @brief Convert nodetype to statement identifier
965 *
966 * @param[in] nodetype Nodetype to convert.
967 * @return Statement identifier representing the given @p nodetype.
968 */
Michal Vasko193dacd2022-10-13 08:43:05 +0200969LIBYANG_API_DECL enum ly_stmt lyplg_ext_nodetype2stmt(uint16_t nodetype);
Michal Vaskob4750962022-10-06 15:33:35 +0200970
971/**
Michal Vasko193dacd2022-10-13 08:43:05 +0200972 * @brief Get compiled ext instance storage for a specific statement.
Michal Vaskob4750962022-10-06 15:33:35 +0200973 *
Michal Vasko193dacd2022-10-13 08:43:05 +0200974 * @param[in] ext Compiled ext instance.
975 * @param[in] stmt Compiled statement. Can be a mask when the first match is returned, it is expected the storage is
976 * the same for all the masked statements.
Michal Vaskofbd037c2022-11-08 10:34:20 +0100977 * @param[in] storage_size Size of the value at @p storage address (dereferenced).
Michal Vasko193dacd2022-10-13 08:43:05 +0200978 * @param[out] storage Compiled ext instance substatement storage, NULL if was not compiled.
979 * @return LY_SUCCESS on success.
980 * @return LY_ENOT if the substatement is not supported.
Michal Vaskob4750962022-10-06 15:33:35 +0200981 */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100982LIBYANG_API_DECL LY_ERR lyplg_ext_get_storage(const struct lysc_ext_instance *ext, int stmt, uint32_t storage_size,
983 const void **storage);
Michal Vasko193dacd2022-10-13 08:43:05 +0200984
985/**
986 * @brief Get parsed ext instance storage for a specific statement.
987 *
988 * @param[in] ext Compiled ext instance.
989 * @param[in] stmt Parsed statement. Can be a mask when the first match is returned, it is expected the storage is
990 * the same for all the masked statements.
Michal Vaskofbd037c2022-11-08 10:34:20 +0100991 * @param[in] storage_size Size of the value at @p storage address (dereferenced).
Michal Vasko193dacd2022-10-13 08:43:05 +0200992 * @param[out] storage Parsed ext instance substatement storage, NULL if was not parsed.
993 * @return LY_SUCCESS on success.
994 * @return LY_ENOT if the substatement is not supported.
995 */
Michal Vaskofbd037c2022-11-08 10:34:20 +0100996LIBYANG_API_DECL LY_ERR lyplg_ext_parsed_get_storage(const struct lysc_ext_instance *ext, int stmt,
997 uint32_t storage_size, const void **storage);
Michal Vaskob4750962022-10-06 15:33:35 +0200998
999/**
Michal Vasko61ad1ff2022-02-10 15:48:39 +01001000 * @brief Get specific run-time extension instance data from a callback set by ::ly_ctx_set_ext_data_clb().
1001 *
1002 * @param[in] ctx Context with the callback.
1003 * @param[in] ext Compiled extension instance.
1004 * @param[out] ext_data Provided extension instance data.
1005 * @param[out] ext_data_free Whether the extension instance should free @p ext_data or not.
1006 * @return LY_SUCCESS on success.
1007 * @return LY_ERR on error.
1008 */
Michal Vaskoddd76592022-01-17 13:34:48 +01001009LIBYANG_API_DECL LY_ERR lyplg_ext_get_data(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, void **ext_data,
1010 ly_bool *ext_data_free);
1011
1012/**
1013 * @brief Insert extension instance data into a parent.
1014 *
1015 * @param[in] parent Parent node to insert into.
1016 * @param[in] first First top-level sibling node to insert.
1017 * @return LY_SUCCESS on success.
1018 * @return LY_ERR error on error.
1019 */
Michal Vasko193dacd2022-10-13 08:43:05 +02001020LIBYANG_API_DECL LY_ERR lyplg_ext_insert(struct lyd_node *parent, struct lyd_node *first);
Radek Krejci0935f412019-08-20 16:15:18 +02001021
ekinzie0ab8b302022-10-10 03:03:57 -04001022/**
1023 * @brief Expand parent-reference xpath expressions
1024 *
Michal Vasko193dacd2022-10-13 08:43:05 +02001025 * @param[in] ext Context allocated for extension.
1026 * @param[out] refs Set of schema node matching parent-reference XPaths.
ekinzie0ab8b302022-10-10 03:03:57 -04001027 * @return LY_ERR value.
1028 */
1029LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_get_parent_ref(const struct lysc_ext_instance *ext, struct ly_set **refs);
1030
1031/**
Michal Vasko193dacd2022-10-13 08:43:05 +02001032 * @brief Allocate a new context for a particular instance of the yangmnt:mount-point extension.
1033 * Caller is responsible for destroying the resulting context.
ekinzie0ab8b302022-10-10 03:03:57 -04001034 *
1035 * @param[in] ext Compiled extension instance.
1036 * @param[out] ctx A context with modules loaded from the list found in
1037 * the extension data.
1038 * @return LY_ERR value.
1039 */
1040LIBYANG_API_DECL LY_ERR lyplg_ext_schema_mount_create_context(const struct lysc_ext_instance *ext, struct ly_ctx **ctx);
1041
Radek Krejci75104122021-04-01 15:37:45 +02001042/** @} pluginsExtensions */
Radek Krejcid7e8a622018-10-29 15:54:55 +01001043
1044#ifdef __cplusplus
1045}
1046#endif
1047
Radek Krejci0935f412019-08-20 16:15:18 +02001048#endif /* LY_PLUGINS_EXTS_H_ */