blob: dfa04ce58b715eb9899efc210c71616c805368f4 [file] [log] [blame]
Radek Krejci5aeea3a2018-09-05 13:29:36 +02001/**
2 * @file tree_schema.h
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief libyang representation of YANG schema trees.
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#ifndef LY_TREE_SCHEMA_H_
16#define LY_TREE_SCHEMA_H_
17
18#include <stdint.h>
19
Radek Krejcice8c1592018-10-29 15:35:51 +010020#include "extensions.h"
21
Radek Krejci70853c52018-10-15 14:46:16 +020022#ifdef __cplusplus
23extern "C" {
24#endif
25
Radek Krejci5aeea3a2018-09-05 13:29:36 +020026/**
Radek Krejcidd4e8d42018-10-16 14:55:43 +020027 * @brief XPath representation.
28 */
29struct lyxp_expr;
30
31/**
Radek Krejcie53a8dc2018-10-17 12:52:40 +020032 * @brief Macro selector for other LY_ARRAY_* macros, do not use directly!
33 */
34#define LY_ARRAY_SELECT(_1, _2, NAME, ...) NAME
35
36/**
Radek Krejcie53a8dc2018-10-17 12:52:40 +020037 * @brief Helper macro to go through sized-arrays with a pointer iterator.
38 *
39 * Use with opening curly bracket (`{`).
40 *
41 * @param[in] ARRAY Array to go through
42 * @param[in] TYPE Type of the records in the ARRAY
43 * @param[out] ITER Iterating pointer to the item being processed in each loop
44 */
45#define LY_ARRAY_FOR_ITER(ARRAY, TYPE, ITER) \
Radek Krejci2c4e7172018-10-19 15:56:26 +020046 for (ITER = ARRAY; \
47 (ARRAY) && ((void*)ITER - (void*)ARRAY)/(sizeof(TYPE)) < (*((uint32_t*)(ARRAY) - 1)); \
Radek Krejcie53a8dc2018-10-17 12:52:40 +020048 ITER = (void*)((TYPE*)ITER + 1))
49
50/**
51 * @brief Helper macro to go through sized-arrays with a numeric iterator.
52 *
53 * Use with opening curly bracket (`{`).
54 *
55 * To access an item with the INDEX value, use always LY_ARRAY_INDEX macro!
56 *
57 * @param[in] ARRAY Array to go through
58 * @param[out] INDEX Iterating index of the item being processed in each loop
59 */
60#define LY_ARRAY_FOR_INDEX(ARRAY, INDEX) \
61 for (INDEX = 0; \
Radek Krejci2c4e7172018-10-19 15:56:26 +020062 ARRAY && INDEX < (*((uint32_t*)(ARRAY) - 1)); \
Radek Krejcie53a8dc2018-10-17 12:52:40 +020063 ++INDEX)
64
65/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +020066 * @defgroup schematree Schema Tree
67 * @{
68 *
69 * Data structures and functions to manipulate and access schema tree.
70 */
71
Radek Krejci0af5f5d2018-09-07 15:00:30 +020072/**
Radek Krejcie53a8dc2018-10-17 12:52:40 +020073 * @brief Get a number of records in the ARRAY.
Radek Krejci86d106e2018-10-18 09:53:19 +020074 *
75 * Does not check if array exists!
Radek Krejcie53a8dc2018-10-17 12:52:40 +020076 */
Radek Krejci2c4e7172018-10-19 15:56:26 +020077#define LY_ARRAY_SIZE(ARRAY) (*((uint32_t*)(ARRAY) - 1))
Radek Krejcie53a8dc2018-10-17 12:52:40 +020078
79/**
80 * @brief Sized-array iterator (for-loop).
81 *
82 * Use with opening curly bracket (`{`).
83 *
84 * There are 2 variants:
85 *
86 * LY_ARRAY_FOR(ARRAY, TYPE, ITER)
87 *
88 * Where ARRAY is a sized-array to go through, TYPE is the type of the items in the ARRAY and ITER is a pointer variable
89 * providing the items of the ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_ITER macro
90 *
91 * LY_ARRAY_FOR(ARRAY, INDEX)
92 *
93 * The ARRAY is again a sized-array to go through, the INDEX is a variable (unsigned integer) for storing iterating ARRAY's index
Radek Krejci2c4e7172018-10-19 15:56:26 +020094 * to access the items of ARRAY in the loops. This functionality is provided by LY_ARRAY_FOR_INDEX macro.
Radek Krejcie53a8dc2018-10-17 12:52:40 +020095 */
96#define LY_ARRAY_FOR(ARRAY, ...) LY_ARRAY_SELECT(__VA_ARGS__, LY_ARRAY_FOR_ITER, LY_ARRAY_FOR_INDEX)(ARRAY, __VA_ARGS__)
Radek Krejci5fac3592018-10-12 15:23:45 +020097
98/**
99 * @brief Macro to iterate via all sibling elements without affecting the list itself
100 *
101 * Works for all types of nodes despite it is data or schema tree, but all the
102 * parameters must be pointers to the same type.
103 *
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200104 * Use with opening curly bracket (`{`). All parameters must be of the same type.
Radek Krejci5fac3592018-10-12 15:23:45 +0200105 *
106 * @param START Pointer to the starting element.
107 * @param ELEM Iterator.
108 */
109#define LY_LIST_FOR(START, ELEM) \
110 for ((ELEM) = (START); \
111 (ELEM); \
112 (ELEM) = (ELEM)->next)
113
114/**
Radek Krejci5fac3592018-10-12 15:23:45 +0200115 * @brief Macro to iterate via all sibling elements allowing to modify the list itself (e.g. removing elements)
116 *
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200117 * Use with opening curly bracket (`{`). All parameters must be of the same type.
Radek Krejci5fac3592018-10-12 15:23:45 +0200118 *
119 * @param START Pointer to the starting element.
120 * @param NEXT Temporary storage to allow removing of the current iterator content.
121 * @param ELEM Iterator.
122 */
123#define LY_LIST_FOR_SAFE(START, NEXT, ELEM) \
124 for ((ELEM) = (START); \
125 (ELEM) ? (NEXT = (ELEM)->next, 1) : 0; \
126 (ELEM) = (NEXT))
127
128/**
Radek Krejci0af5f5d2018-09-07 15:00:30 +0200129 * @brief Schema input formats accepted by libyang [parser functions](@ref howtoschemasparsers).
130 */
131typedef enum {
132 LYS_IN_UNKNOWN = 0, /**< unknown format, used as return value in case of error */
133 LYS_IN_YANG = 1, /**< YANG schema input format */
134 LYS_IN_YIN = 2 /**< YIN schema input format */
135} LYS_INFORMAT;
136
137/**
138 * @brief Schema output formats accepted by libyang [printer functions](@ref howtoschemasprinters).
139 */
140typedef enum {
141 LYS_OUT_UNKNOWN = 0, /**< unknown format, used as return value in case of error */
142 LYS_OUT_YANG = 1, /**< YANG schema output format */
143 LYS_OUT_YIN = 2, /**< YIN schema output format */
144 LYS_OUT_TREE, /**< Tree schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
145 LYS_OUT_INFO, /**< Info schema output format, for more information see the [printers](@ref howtoschemasprinters) page */
146 LYS_OUT_JSON, /**< JSON schema output format, reflecting YIN format with conversion of attributes to object's members */
147} LYS_OUTFORMAT;
148
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200149#define LY_REV_SIZE 11 /**< revision data string length (including terminating NULL byte) */
150
Michal Vaskob55f6c12018-09-12 11:13:15 +0200151#define LYS_UNKNOWN 0x0000 /**< uninitalized unknown statement node */
152#define LYS_CONTAINER 0x0001 /**< container statement node */
153#define LYS_CHOICE 0x0002 /**< choice statement node */
154#define LYS_LEAF 0x0004 /**< leaf statement node */
155#define LYS_LEAFLIST 0x0008 /**< leaf-list statement node */
156#define LYS_LIST 0x0010 /**< list statement node */
157#define LYS_ANYXML 0x0020 /**< anyxml statement node */
158#define LYS_CASE 0x0040 /**< case statement node */
159#define LYS_USES 0x0080 /**< uses statement node */
160#define LYS_ANYDATA 0x0120 /**< anydata statement node, in tests it can be used for both #LYS_ANYXML and #LYS_ANYDATA */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200161
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100162#define LYS_INOUT 0x200
163#define LYS_ACTION 0x400
164#define LYS_NOTIF 0x800
165#define LYS_GROUPING 0x1000
166#define LYS_AUGMENT 0x2000
167
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200168/**
169 * @brief YANG import-stmt
170 */
171struct lysp_import {
Radek Krejci086c7132018-10-26 15:29:04 +0200172 struct lys_module *module; /**< pointer to the imported module
173 (mandatory, but resolved when the referring module is completely parsed) */
174 const char *name; /**< name of the imported module (mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200175 const char *prefix; /**< prefix for the data from the imported schema (mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200176 const char *dsc; /**< description */
177 const char *ref; /**< reference */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200178 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200179 char rev[LY_REV_SIZE]; /**< revision-date of the imported module */
180};
181
182/**
183 * @brief YANG include-stmt
184 */
185struct lysp_include {
Radek Krejci086c7132018-10-26 15:29:04 +0200186 struct lysp_module *submodule; /**< pointer to the parsed submodule structure
187 (mandatory, but resolved when the referring module is completely parsed) */
188 const char *name; /**< name of the included submodule (mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200189 const char *dsc; /**< description */
190 const char *ref; /**< reference */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200191 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200192 char rev[LY_REV_SIZE]; /**< revision-date of the included submodule */
193};
194
195/**
196 * @brief YANG extension-stmt
197 */
198struct lysp_ext {
199 const char *name; /**< extension name */
200 const char *argument; /**< argument name, NULL if not specified */
201 const char *dsc; /**< description statement */
202 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200203 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200204 uint16_t flags; /**< LYS_STATUS_* and LYS_YINELEM values (@ref snodeflags) */
205};
206
207/**
208 * @brief Helper structure for generic storage of the extension instances content.
209 */
210struct lysp_stmt {
211 const char *stmt; /**< identifier of the statement */
212 const char *arg; /**< statement's argument */
213 struct lysp_stmt *next; /**< link to the next statement */
Michal Vaskobc2559f2018-09-07 10:17:50 +0200214 struct lysp_stmt *child; /**< list of the statement's substatements (linked list) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200215};
216
217/**
218 * @brief YANG extension instance
219 */
220struct lysp_ext_instance {
221 const char *name; /**< extension identifier, including possible prefix */
222 const char *argument; /**< optional value of the extension's argument */
Michal Vaskod92e42a2018-09-07 08:35:02 +0200223 LYEXT_SUBSTMT insubstmt; /**< value identifying placement of the extension instance */
224 uint32_t insubstmt_index; /**< in case the instance is in a substatement, this identifies
225 the index of that substatement */
Michal Vaskobc2559f2018-09-07 10:17:50 +0200226 struct lysp_stmt *child; /**< list of the extension's substatements (linked list) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200227};
228
229/**
230 * @brief YANG feature-stmt
231 */
232struct lysp_feature {
233 const char *name; /**< feature name (mandatory) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200234 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200235 const char *dsc; /**< description statement */
236 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200237 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200238 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values allowed */
239};
240
241/**
242 * @brief YANG identity-stmt
243 */
244struct lysp_ident {
245 const char *name; /**< identity name (mandatory), including possible prefix */
Radek Krejci151a5b72018-10-19 14:21:44 +0200246 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
247 const char **bases; /**< list of base identifiers ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200248 const char *dsc; /**< description statement */
249 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200250 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200251 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_ values are allowed */
252};
253
Michal Vasko71e64ca2018-09-07 16:30:29 +0200254/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200255 * @brief Covers restrictions: range, length, pattern, must
256 */
257struct lysp_restr {
258 const char *arg; /**< The restriction expression/value (mandatory);
259 in case of pattern restriction, the first byte has a special meaning:
260 0x06 (ACK) for regular match and 0x15 (NACK) for invert-match */
261 const char *emsg; /**< error-message */
262 const char *eapptag; /**< error-app-tag value */
263 const char *dsc; /**< description */
264 const char *ref; /**< reference */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200265 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200266};
267
268/**
Michal Vasko71e64ca2018-09-07 16:30:29 +0200269 * @brief YANG revision-stmt
270 */
271struct lysp_revision {
Radek Krejcib7db73a2018-10-24 14:18:40 +0200272 char date[LY_REV_SIZE]; /**< revision date (madatory) */
Michal Vasko71e64ca2018-09-07 16:30:29 +0200273 const char *dsc; /**< description statement */
274 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200275 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vasko71e64ca2018-09-07 16:30:29 +0200276};
277
278/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200279 * @brief Enumeration/Bit value definition
280 */
281struct lysp_type_enum {
282 const char *name; /**< name (mandatory) */
283 const char *dsc; /**< description statement */
284 const char *ref; /**< reference statement */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200285 int64_t value; /**< enum's value or bit's position */
Radek Krejci151a5b72018-10-19 14:21:44 +0200286 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200287 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200288 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_ and LYS_SET_VALUE
289 values are allowed */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200290};
291
292/**
293 * @brief YANG type-stmt
294 *
295 * Some of the items in the structure may be mandatory, but it is necessary to resolve the type's base type first
296 */
297struct lysp_type {
298 const char *name; /**< name of the type (mandatory) */
299 struct lysp_restr *range; /**< allowed values range - numerical, decimal64 */
300 struct lysp_restr *length; /**< allowed length of the value - string, binary */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200301 struct lysp_restr *patterns; /**< list of patterns ([sized array](@ref sizedarrays)) - string */
302 struct lysp_type_enum *enums; /**< list of enum-stmts ([sized array](@ref sizedarrays)) - enum */
303 struct lysp_type_enum *bits; /**< list of bit-stmts ([sized array](@ref sizedarrays)) - bits */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200304 const char *path; /**< path - leafref */
Radek Krejci151a5b72018-10-19 14:21:44 +0200305 const char **bases; /**< list of base identifiers ([sized array](@ref sizedarrays)) - identityref */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200306 struct lysp_type *types; /**< list of sub-types ([sized array](@ref sizedarrays)) - union */
307 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200308
309 uint8_t fraction_digits; /**< number of fraction digits - decimal64 */
310 uint8_t require_instance; /**< require-instance flag - leafref, instance */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200311 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_SET_REQINST allowed */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200312};
313
314/**
315 * @brief YANG typedef-stmt
316 */
317struct lysp_tpdf {
318 const char *name; /**< name of the newly defined type (mandatory) */
319 const char *units; /**< units of the newly defined type */
320 const char *dflt; /**< default value of the newly defined type */
321 const char *dsc; /**< description statement */
322 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200323 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200324 struct lysp_type type; /**< base type from which the typedef is derived (mandatory) */
325 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values allowed */
326};
327
328/**
329 * @brief YANG grouping-stmt
330 */
331struct lysp_grp {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100332 struct lysp_node *parent; /**< parent node (NULL if this is a top-level grouping) */
333 uint16_t nodetype; /**< LYS_GROUPING */
334 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200335 const char *name; /**< grouping name (mandatory) */
336 const char *dsc; /**< description statement */
337 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200338 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
339 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200340 struct lysp_node *data; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200341 struct lysp_action *actions; /**< list of actions ([sized array](@ref sizedarrays)) */
342 struct lysp_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
343 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200344};
345
346/**
347 * @brief YANG when-stmt
348 */
349struct lysp_when {
350 const char *cond; /**< specified condition (mandatory) */
351 const char *dsc; /**< description statement */
352 const char *ref; /**< reference statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200353 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200354};
355
356/**
357 * @brief YANG refine-stmt
358 */
359struct lysp_refine {
360 const char *nodeid; /**< target descendant schema nodeid (mandatory) */
361 const char *dsc; /**< description statement */
362 const char *ref; /**< reference statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200363 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200364 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200365 const char *presence; /**< presence description */
Radek Krejci151a5b72018-10-19 14:21:44 +0200366 const char **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200367 uint32_t min; /**< min-elements constraint */
368 uint32_t max; /**< max-elements constraint, 0 means unbounded */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200369 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200370 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
371};
372
373/**
374 * @brief YANG uses-augment-stmt and augment-stmt
375 */
376struct lysp_augment {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100377 struct lysp_node *parent; /**< parent node (NULL if this is a top-level augment) */
378 uint16_t nodetype; /**< LYS_AUGMENT */
379 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200380 const char *nodeid; /**< target schema nodeid (mandatory) - absolute for global augments, descendant for uses's augments */
381 const char *dsc; /**< description statement */
382 const char *ref; /**< reference statement */
383 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200384 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200385 struct lysp_node *child; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200386 struct lysp_action *actions; /**< list of actions ([sized array](@ref sizedarrays)) */
387 struct lysp_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
388 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200389};
390
391/**
392 * @defgroup deviatetypes Deviate types
393 * @{
394 */
395#define LYS_DEV_NOT_SUPPORTED 1 /**< deviate type not-supported */
396#define LYS_DEV_ADD 2 /**< deviate type add */
397#define LYS_DEV_DELETE 3 /**< deviate type delete */
398#define LYS_DEV_REPLACE 4 /**< deviate type replace */
399/** @} */
400
401/**
402 * @brief Generic deviate structure to get type and cast to lysp_deviate_* structure
403 */
404struct lysp_deviate {
405 uint8_t mod; /**< [type](@ref deviatetypes) of the deviate modification */
406 struct lysp_deviate *next; /**< next deviate structure in the list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200407 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200408};
409
410struct lysp_deviate_add {
411 uint8_t mod; /**< [type](@ref deviatetypes) of the deviate modification */
412 struct lysp_deviate *next; /**< next deviate structure in the list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200413 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200414 const char *units; /**< units of the values */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200415 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200416 const char **uniques; /**< list of uniques specifications ([sized array](@ref sizedarrays)) */
417 const char **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200418 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
419 uint32_t min; /**< min-elements constraint */
420 uint32_t max; /**< max-elements constraint, 0 means unbounded */
421};
422
423struct lysp_deviate_del {
424 uint8_t mod; /**< [type](@ref deviatetypes) of the deviate modification */
425 struct lysp_deviate *next; /**< next deviate structure in the list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200426 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200427 const char *units; /**< units of the values */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200428 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200429 const char **uniques; /**< list of uniques specifications ([sized array](@ref sizedarrays)) */
430 const char **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200431 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200432};
433
434struct lysp_deviate_rpl {
435 uint8_t mod; /**< [type](@ref deviatetypes) of the deviate modification */
436 struct lysp_deviate *next; /**< next deviate structure in the list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200437 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200438 struct lysp_type *type; /**< type of the node */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200439 const char *units; /**< units of the values */
440 const char *dflt; /**< default value */
441 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
442 uint32_t min; /**< min-elements constraint */
443 uint32_t max; /**< max-elements constraint, 0 means unbounded */
444};
445
446struct lysp_deviation {
Michal Vaskob55f6c12018-09-12 11:13:15 +0200447 const char *nodeid; /**< target absolute schema nodeid (mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200448 const char *dsc; /**< description statement */
449 const char *ref; /**< reference statement */
450 struct lysp_deviate* deviates; /**< list of deviate specifications (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200451 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200452};
453
Michal Vaskob55f6c12018-09-12 11:13:15 +0200454#define LYS_CONFIG_W 0x01 /**< config true; */
455#define LYS_CONFIG_R 0x02 /**< config false; */
456#define LYS_CONFIG_MASK 0x03 /**< mask for config value */
457#define LYS_STATUS_CURR 0x08 /**< status current; */
458#define LYS_STATUS_DEPRC 0x10 /**< status deprecated; */
459#define LYS_STATUS_OBSLT 0x20 /**< status obsolete; */
460#define LYS_STATUS_MASK 0x38 /**< mask for status value */
461#define LYS_MAND_TRUE 0x40 /**< mandatory true; applicable only to
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200462 ::lysp_node_choice/::lysc_node_choice, ::lysp_node_leaf/::lysc_node_leaf
463 and ::lysp_node_anydata/::lysc_node_anydata */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200464#define LYS_MAND_FALSE 0x80 /**< mandatory false; applicable only to
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200465 ::lysp_node_choice/::lysc_node_choice, ::lysp_node_leaf/::lysc_node_leaf
466 and ::lysp_node_anydata/::lysc_node_anydata */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200467#define LYS_MAND_MASK 0xc0 /**< mask for mandatory values */
468#define LYS_ORDBY_SYSTEM 0x100 /**< ordered-by system lists, applicable only to
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200469 ::lysp_node_list/lysc_node_list and ::lysp_node_leaflist/::lysc_node_list */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200470#define LYS_ORDBY_USER 0x200 /**< ordered-by user lists, applicable only to
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200471 ::lysp_node_list/lysc_node_list and ::lysp_node_leaflist/::lysc_node_list */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200472#define LYS_ORDBY_MASK 0x300 /**< mask for ordered-by flags */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200473#define LYS_FENABLED 0x100 /**< feature enabled flag, applicable only to ::lysp_feature/::lysc_feature */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200474#define LYS_AUTOASSIGNED 0x01 /**< value was auto-assigned, applicable only to
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200475 ::lysp_type/::lysc_type enum and bits flags */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200476#define LYS_YINELEM_TRUE 0x01 /**< yin-element true for extension's argument */
477#define LYS_YINELEM_FALSE 0x02 /**< yin-element false for extension's argument */
478#define LYS_YINELEM_MASK 0x03 /**< mask for yin-element value */
479#define LYS_SET_VALUE 0x01 /**< value attribute is set */
480#define LYS_SET_MAX 0x400 /**< max attribute is set */
481#define LYS_SET_MIN 0x800 /**< min attribute is set */
482#define LYS_SET_REQINST 0x01 /**< require_instance attribute is set */
483
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200484/**
485 * @brief Generic YANG data node
486 */
487struct lysp_node {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100488 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200489 uint16_t nodetype; /**< type of the node (mandatory) */
490 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100491 struct lysp_node *next; /**< next sibling node (NULL if there is no one) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200492 const char *name; /**< node name (mandatory) */
493 const char *dsc; /**< description statement */
494 const char *ref; /**< reference statement */
495 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200496 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200497 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200498};
499
500/**
501 * @brief Extension structure of the lysp_node for YANG container
502 */
503struct lysp_node_container {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100504 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200505 uint16_t nodetype; /**< LYS_CONTAINER */
506 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
507 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
508 const char *name; /**< node name (mandatory) */
509 const char *dsc; /**< description statement */
510 const char *ref; /**< reference statement */
511 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200512 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200513 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200514
515 /* container */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200516 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200517 const char *presence; /**< presence description */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200518 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
519 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200520 struct lysp_node *child; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200521 struct lysp_action *actions; /**< list of actions ([sized array](@ref sizedarrays)) */
522 struct lysp_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200523};
524
525struct lysp_node_leaf {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100526 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200527 uint16_t nodetype; /**< LYS_LEAF */
528 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
529 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
530 const char *name; /**< node name (mandatory) */
531 const char *dsc; /**< description statement */
532 const char *ref; /**< reference statement */
533 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200534 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200535 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200536
537 /* leaf */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200538 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200539 struct lysp_type type; /**< type of the leaf node (mandatory) */
540 const char *units; /**< units of the leaf's type */
541 const char *dflt; /**< default value */
542};
543
544struct lysp_node_leaflist {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100545 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200546 uint16_t nodetype; /**< LYS_LEAFLIST */
547 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
548 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
549 const char *name; /**< node name (mandatory) */
550 const char *dsc; /**< description statement */
551 const char *ref; /**< reference statement */
552 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200553 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200554 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200555
556 /* leaf-list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200557 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200558 struct lysp_type type; /**< type of the leaf node (mandatory) */
559 const char *units; /**< units of the leaf's type */
Radek Krejci151a5b72018-10-19 14:21:44 +0200560 const char **dflts; /**< list of default values ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200561 uint32_t min; /**< min-elements constraint */
562 uint32_t max; /**< max-elements constraint, 0 means unbounded */
563};
564
565struct lysp_node_list {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100566 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200567 uint16_t nodetype; /**< LYS_LIST */
568 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
569 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
570 const char *name; /**< node name (mandatory) */
571 const char *dsc; /**< description statement */
572 const char *ref; /**< reference statement */
573 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200574 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200575 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200576
577 /* list */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200578 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200579 const char *key; /**< keys specification */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200580 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
581 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200582 struct lysp_node *child; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200583 struct lysp_action *actions; /**< list of actions ([sized array](@ref sizedarrays)) */
584 struct lysp_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200585 const char **uniques; /**< list of unique specifications ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200586 uint32_t min; /**< min-elements constraint */
587 uint32_t max; /**< max-elements constraint, 0 means unbounded */
588};
589
590struct lysp_node_choice {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100591 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200592 uint16_t nodetype; /**< LYS_CHOICE */
593 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
594 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
595 const char *name; /**< node name (mandatory) */
596 const char *dsc; /**< description statement */
597 const char *ref; /**< reference statement */
598 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200599 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200600 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200601
602 /* choice */
603 struct lysp_node *child; /**< list of data nodes (linked list) */
604 const char* dflt; /**< default case */
605};
606
607struct lysp_node_case {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100608 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200609 uint16_t nodetype; /**< LYS_CASE */
610 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
611 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
612 const char *name; /**< node name (mandatory) */
613 const char *dsc; /**< description statement */
614 const char *ref; /**< reference statement */
615 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200616 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200617 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200618
619 /* case */
620 struct lysp_node *child; /**< list of data nodes (linked list) */
621};
622
623struct lysp_node_anydata {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100624 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200625 uint16_t nodetype; /**< LYS_ANYXML || LYS_ANYDATA */
626 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
627 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
628 const char *name; /**< node name (mandatory) */
629 const char *dsc; /**< description statement */
630 const char *ref; /**< reference statement */
631 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200632 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200633 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200634
635 /* anyxml/anydata */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200636 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200637};
638
639struct lysp_node_uses {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100640 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200641 uint16_t nodetype; /**< LYS_USES */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200642 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
643 struct lysp_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
644 const char *name; /**< grouping name reference (mandatory) */
645 const char *dsc; /**< description statement */
646 const char *ref; /**< reference statement */
647 struct lysp_when *when; /**< when statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200648 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200649 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200650
651 /* uses */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200652 struct lysp_refine *refines; /**< list of uses's refines ([sized array](@ref sizedarrays)) */
653 struct lysp_augment *augments; /**< list of uses's augment ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200654};
655
656/**
657 * @brief YANG input-stmt and output-stmt
658 */
659struct lysp_action_inout {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100660 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
661 uint16_t nodetype; /**< LYS_INOUT */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200662 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
663 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
664 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200665 struct lysp_node *data; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200666 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200667};
668
669/**
670 * @brief YANG rpc-stmt and action-stmt
671 */
672struct lysp_action {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100673 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
674 uint16_t nodetype; /**< LYS_ACTION */
675 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200676 const char *name; /**< grouping name reference (mandatory) */
677 const char *dsc; /**< description statement */
678 const char *ref; /**< reference statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200679 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200680 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
681 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Michal Vaskob55f6c12018-09-12 11:13:15 +0200682 struct lysp_action_inout *input; /**< RPC's/Action's input */
683 struct lysp_action_inout *output;/**< RPC's/Action's output */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200684 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200685};
686
687/**
688 * @brief YANG notification-stmt
689 */
690struct lysp_notif {
Radek Krejci6d9b9b52018-11-02 12:43:39 +0100691 struct lysp_node *parent; /**< parent node (NULL if this is a top-level node) */
692 uint16_t nodetype; /**< LYS_NOTIF */
693 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* values are allowed */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200694 const char *name; /**< grouping name reference (mandatory) */
695 const char *dsc; /**< description statement */
696 const char *ref; /**< reference statement */
Radek Krejci151a5b72018-10-19 14:21:44 +0200697 const char **iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200698 struct lysp_restr *musts; /**< list of must restrictions ([sized array](@ref sizedarrays)) */
699 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
700 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200701 struct lysp_node *data; /**< list of data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200702 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200703};
704
705/**
Radek Krejcif0fceb62018-09-05 14:58:45 +0200706 * @brief supported YANG schema version values
707 */
708typedef enum LYS_VERSION {
709 LYS_VERSION_UNDEF = 0, /**< no specific version, YANG 1.0 as default */
710 LYS_VERSION_1_0 = 1, /**< YANG 1.0 */
711 LYS_VERSION_1_1 = 2 /**< YANG 1.1 */
712} LYS_VERSION;
713
714/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200715 * @brief Printable YANG schema tree structure representing YANG module.
716 *
717 * Simple structure corresponding to the YANG format. The schema is only syntactically validated.
718 */
719struct lysp_module {
720 struct ly_ctx *ctx; /**< libyang context of the module (mandatory) */
721 const char *name; /**< name of the module (mandatory) */
Radek Krejci6d6e4e42018-10-29 13:28:19 +0100722 const char *filepath; /**< path, if the schema was read from a file, NULL in case of reading from memory */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200723 union {
724 /* module */
Michal Vaskod5927ca2018-09-07 15:05:32 +0200725 const char *ns; /**< namespace of the module (module - mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200726 /* submodule */
Michal Vaskod5927ca2018-09-07 15:05:32 +0200727 const char *belongsto; /**< belongs to parent module (submodule - mandatory) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200728 };
Michal Vaskod5927ca2018-09-07 15:05:32 +0200729 const char *prefix; /**< module prefix or submodule belongsto prefix of main module (mandatory) */
Radek Krejcib7db73a2018-10-24 14:18:40 +0200730 struct lysp_revision *revs; /**< list of the module revisions ([sized array](@ref sizedarrays)), the first revision
731 in the list is always the last (newest) revision of the module */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200732 struct lysp_import *imports; /**< list of imported modules ([sized array](@ref sizedarrays)) */
733 struct lysp_include *includes; /**< list of included submodules ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200734 const char *org; /**< party/company responsible for the module */
735 const char *contact; /**< contact information for the module */
736 const char *dsc; /**< description of the module */
737 const char *ref; /**< cross-reference for the module */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200738 struct lysp_ext *extensions; /**< list of extension statements ([sized array](@ref sizedarrays)) */
739 struct lysp_feature *features; /**< list of feature definitions ([sized array](@ref sizedarrays)) */
740 struct lysp_ident *identities; /**< list of identities ([sized array](@ref sizedarrays)) */
741 struct lysp_tpdf *typedefs; /**< list of typedefs ([sized array](@ref sizedarrays)) */
742 struct lysp_grp *groupings; /**< list of groupings ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200743 struct lysp_node *data; /**< list of module's top-level data nodes (linked list) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200744 struct lysp_augment *augments; /**< list of augments ([sized array](@ref sizedarrays)) */
745 struct lysp_action *rpcs; /**< list of RPCs ([sized array](@ref sizedarrays)) */
746 struct lysp_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
747 struct lysp_deviation *deviations; /**< list of deviations ([sized array](@ref sizedarrays)) */
748 struct lysp_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200749
Radek Krejcif0fceb62018-09-05 14:58:45 +0200750 uint8_t submodule:1; /**< flag to distinguish main modules and submodules */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200751 uint8_t implemented:1; /**< flag if the module is implemented, not just imported */
Radek Krejci086c7132018-10-26 15:29:04 +0200752 uint8_t latest_revision:2; /**< flag to mark the latest available revision:
753 1 - the latest revision in searchdirs was not searched yet and this is the
754 latest revision in the current context
755 2 - searchdirs were searched and this is the latest available revision */
756 uint8_t parsing:1; /**< flag for circular check */
757 uint8_t version; /**< yang-version (LYS_VERSION values) */
Radek Krejcid33273d2018-10-25 14:55:52 +0200758 uint16_t refcount; /**< 0 in modules, number of includes of a submodules */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200759};
760
761/**
Radek Krejci3f5e3db2018-10-11 15:57:47 +0200762 * @brief Free the printable YANG schema tree structure.
763 *
764 * @param[in] module Printable YANG schema tree structure to free.
765 */
766void lysp_module_free(struct lysp_module *module);
767
768/**
Radek Krejcice8c1592018-10-29 15:35:51 +0100769 * @brief YANG extension instance
770 */
771struct lysc_ext_instance {
772 struct lyext_plugin *plugin; /**< pointer to the plugin implementing the extension (if present) */
773 void *parent; /**< pointer to the parent element holding the extension instance(s), use
774 ::lysc_ext_instance#parent_type to access the schema element */
775 const char *argument; /**< optional value of the extension's argument */
776 LYEXT_SUBSTMT insubstmt; /**< value identifying placement of the extension instance */
777 uint32_t insubstmt_index; /**< in case the instance is in a substatement that can appear multiple times,
778 this identifies the index of the substatement for this extension instance */
Radek Krejci2a408df2018-10-29 16:32:26 +0100779 LYEXT_PARENT parent_type; /**< type of the parent structure */
Radek Krejcice8c1592018-10-29 15:35:51 +0100780#if 0
Radek Krejcice8c1592018-10-29 15:35:51 +0100781 uint8_t ext_type; /**< extension type (#LYEXT_TYPE) */
782 uint8_t padding; /**< 32b padding */
Radek Krejcice8c1592018-10-29 15:35:51 +0100783 struct lys_module *module; /**< pointer to the extension instance's module (mandatory) */
784 LYS_NODE nodetype; /**< LYS_EXT */
785#endif
Radek Krejci2a408df2018-10-29 16:32:26 +0100786 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
787 void *priv; /**< private caller's data, not used by libyang */
Radek Krejcice8c1592018-10-29 15:35:51 +0100788};
789
790/**
Radek Krejci151a5b72018-10-19 14:21:44 +0200791 * @brief YANG import-stmt
792 */
793struct lysc_import {
Radek Krejci6d6e4e42018-10-29 13:28:19 +0100794 struct lys_module *module; /**< link to the imported module */
Radek Krejci151a5b72018-10-19 14:21:44 +0200795 const char *prefix; /**< prefix for the data from the imported schema (mandatory) */
Radek Krejcice8c1592018-10-29 15:35:51 +0100796 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200797};
798
799/**
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200800 * @brief YANG when-stmt
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200801 */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200802struct lysc_when {
803 struct lyxp_expr *cond; /**< XPath when condition */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200804 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200805};
806
807/**
Radek Krejci2a408df2018-10-29 16:32:26 +0100808 * @brief YANG identity-stmt
809 */
810struct lysc_ident {
811 const char *name; /**< identity name (mandatory), including possible prefix */
812 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
813 struct lysc_ident **derived; /**< list of (pointers to the) derived identities ([sized array](@ref sizedarrays)) */
814 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
815 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_ values are allowed */
816};
817
818/**
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200819 * @brief YANG feature-stmt
820 */
821struct lysc_feature {
822 const char *name; /**< feature name (mandatory) */
Radek Krejci151a5b72018-10-19 14:21:44 +0200823 struct lysc_feature **depfeatures;/**< list of pointers to other features depending on this one ([sized array](@ref sizedarrays)) */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200824 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
Radek Krejcice8c1592018-10-29 15:35:51 +0100825 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200826 uint16_t flags; /**< [schema node flags](@ref snodeflags) - only LYS_STATUS_* and
827 #LYS_FENABLED values allowed */
828};
829
Radek Krejci151a5b72018-10-19 14:21:44 +0200830/**
831 * @defgroup ifftokens if-feature expression tokens
832 * Tokens of if-feature expression used in ::lysc_iffeature#expr
833 *
834 * @{
835 */
836#define LYS_IFF_NOT 0x00 /**< operand "not" */
837#define LYS_IFF_AND 0x01 /**< operand "and" */
838#define LYS_IFF_OR 0x02 /**< operand "or" */
839#define LYS_IFF_F 0x03 /**< feature */
840/**
841 * @}
842 */
843
844/**
Radek Krejcib7db73a2018-10-24 14:18:40 +0200845 * @brief Compiled YANG revision statement
846 */
847struct lysc_revision {
848 char date[LY_REV_SIZE]; /**< revision-date (mandatory) */
849 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
850};
851
852/**
Radek Krejci151a5b72018-10-19 14:21:44 +0200853 * @brief Compiled YANG if-feature-stmt
854 */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200855struct lysc_iffeature {
Radek Krejci151a5b72018-10-19 14:21:44 +0200856 uint8_t *expr; /**< 2bits array describing the if-feature expression in prefix format, see @ref ifftokens */
857 struct lysc_feature **features; /**< array of pointers to the features used in expression ([sized array](@ref sizedarrays)) */
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200858};
859
860/**
Radek Krejci0af5f5d2018-09-07 15:00:30 +0200861 * @brief Compiled YANG data node
862 */
863struct lysc_node {
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200864 uint16_t nodetype; /**< type of the node (mandatory) */
865 uint16_t flags; /**< [schema node flags](@ref snodeflags) */
866 struct lysp_node *sp; /**< link to the simply parsed (SP) original of the node, NULL if the SP schema was removed. */
867 struct lysc_node *next; /**< pointer to the next sibling node (NULL if there is no one) */
868 const char *name; /**< node name (mandatory) */
869 struct lysc_when *when; /**< when statement */
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200870 struct lysc_iffeature *iffeatures; /**< list of if-feature expressions ([sized array](@ref sizedarrays)) */
871 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200872};
873
874/**
875 * @brief Compiled YANG schema tree structure representing YANG module.
876 *
877 * Semantically validated YANG schema tree for data tree parsing.
878 * Contains only the necessary information for the data validation.
879 */
880struct lysc_module {
881 struct ly_ctx *ctx; /**< libyang context of the module (mandatory) */
882 const char *name; /**< name of the module (mandatory) */
Radek Krejci6d6e4e42018-10-29 13:28:19 +0100883 const char *filepath; /**< path, if the schema was read from a file, NULL in case of reading from memory */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200884 const char *ns; /**< namespace of the module (mandatory) */
885 const char *prefix; /**< module prefix (mandatory) */
Radek Krejcif8f882a2018-10-31 14:51:15 +0100886 const char *revision; /**< the revision of the module */
Radek Krejci151a5b72018-10-19 14:21:44 +0200887 struct lysc_import *imports; /**< list of imported modules ([sized array](@ref sizedarrays)) */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200888
Radek Krejcie53a8dc2018-10-17 12:52:40 +0200889 struct lysc_feature *features; /**< list of feature definitions ([sized array](@ref sizedarrays)) */
Radek Krejci2a408df2018-10-29 16:32:26 +0100890 struct lysc_ident *identities; /**< list of identities ([sized array](@ref sizedarrays)) */
891 struct lysc_node *data; /**< list of module's top-level data nodes (linked list) */
892 struct lysc_action *rpcs; /**< list of RPCs ([sized array](@ref sizedarrays)) */
893 struct lysc_notif *notifs; /**< list of notifications ([sized array](@ref sizedarrays)) */
Radek Krejcice8c1592018-10-29 15:35:51 +0100894 struct lysc_ext_instance *exts; /**< list of the extension instances ([sized array](@ref sizedarrays)) */
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200895
896 uint8_t implemented:1; /**< flag if the module is implemented, not just imported */
Radek Krejcifaa1eac2018-10-30 14:34:55 +0100897 uint8_t latest_revision:2; /**< flag to mark the latest available revision:
898 1 - the latest revision in searchdirs was not searched yet and this is the
899 latest revision in the current context
900 2 - searchdirs were searched and this is the latest available revision */
Radek Krejci086c7132018-10-26 15:29:04 +0200901 uint8_t version; /**< yang-version (LYS_VERSION values) */
Radek Krejci0af5f5d2018-09-07 15:00:30 +0200902};
903
904/**
Radek Krejci151a5b72018-10-19 14:21:44 +0200905 * @brief Get how the if-feature statement currently evaluates.
906 *
907 * @param[in] iff Compiled if-feature statement to evaluate.
908 * @return If the statement evaluates to true, 1 is returned. 0 is returned when the statement evaluates to false.
909 */
910int lysc_iffeature_value(const struct lysc_iffeature *iff);
911
912/**
913 * @brief Get the current status of the provided feature.
914 *
915 * @param[in] feature Compiled feature statement to examine.
916 * @return
917 * - 1 if feature is enabled,
918 * - 0 if feature is disabled,
919 * - -1 in case of error (invalid argument)
920 */
921int lysc_feature_value(const struct lysc_feature *feature);
922
923/**
Radek Krejci5aeea3a2018-09-05 13:29:36 +0200924 * @brief Available YANG schema tree structures representing YANG module.
925 */
926struct lys_module {
927 struct lysp_module *parsed; /**< Simply parsed (unresolved) YANG schema tree */
928 struct lysc_module *compiled; /**< Compiled and fully validated YANG schema tree for data parsing */
929};
930
Radek Krejci151a5b72018-10-19 14:21:44 +0200931/**
932 * @brief Enable specified feature in the module
933 *
934 * By default, when the module is loaded by libyang parser, all features are disabled.
935 *
Radek Krejcica3db002018-11-01 10:31:01 +0100936 * If all features are being enabled, it must be possible respecting their if-feature conditions. For example,
937 * enabling all features on the following feature set will fail since it is not possible to enable both features
938 * (and it is unclear which of them should be enabled then). In this case the LY_EDENIED is returned and the feature
939 * is untouched.
940 *
941 * feature f1;
942 * feature f2 { if-feature 'not f1';}
943 *
Radek Krejci151a5b72018-10-19 14:21:44 +0200944 * @param[in] module Module where the feature will be enabled.
945 * @param[in] feature Name of the feature to enable. To enable all features at once, use asterisk (`*`) character.
946 * @return LY_ERR value.
947 */
948LY_ERR lys_feature_enable(struct lys_module *module, const char *feature);
949
950/**
951 * @brief Disable specified feature in the module
952 *
953 * By default, when the module is loaded by libyang parser, all features are disabled.
954 *
955 * @param[in] module Module where the feature will be disabled.
956 * @param[in] feature Name of the feature to disable. To disable all features at once, use asterisk (`*`) character.
957 * @return LY_ERR value
958 */
959LY_ERR lys_feature_disable(struct lys_module *module, const char *feature);
960
961/**
962 * @brief Get the current status of the specified feature in the module.
963 *
964 * @param[in] module Module where the feature is defined.
965 * @param[in] feature Name of the feature to inspect.
966 * @return
967 * - 1 if feature is enabled,
968 * - 0 if feature is disabled,
969 * - -1 in case of error (e.g. feature is not defined or invalid arguments)
970 */
971int lys_feature_value(const struct lys_module *module, const char *feature);
Radek Krejcidd4e8d42018-10-16 14:55:43 +0200972
973/**
Radek Krejci86d106e2018-10-18 09:53:19 +0200974 * @brief Load a schema into the specified context.
975 *
976 * @param[in] ctx libyang context where to process the data model.
977 * @param[in] data The string containing the dumped data model in the specified
978 * format.
979 * @param[in] format Format of the input data (YANG or YIN).
980 * @return Pointer to the data model structure or NULL on error.
981 */
Radek Krejcid14e9692018-11-01 11:00:37 +0100982struct lys_module *lys_parse_mem(struct ly_ctx *ctx, const char *data, LYS_INFORMAT format);
Radek Krejci86d106e2018-10-18 09:53:19 +0200983
984/**
985 * @brief Read a schema from file descriptor into the specified context.
986 *
987 * \note Current implementation supports only reading data from standard (disk) file, not from sockets, pipes, etc.
988 *
989 * @param[in] ctx libyang context where to process the data model.
990 * @param[in] fd File descriptor of a regular file (e.g. sockets are not supported) containing the schema
991 * in the specified format.
992 * @param[in] format Format of the input data (YANG or YIN).
993 * @return Pointer to the data model structure or NULL on error.
994 */
Radek Krejcid14e9692018-11-01 11:00:37 +0100995struct lys_module *lys_parse_fd(struct ly_ctx *ctx, int fd, LYS_INFORMAT format);
Radek Krejci86d106e2018-10-18 09:53:19 +0200996
997/**
Radek Krejcid33273d2018-10-25 14:55:52 +0200998 * @brief Read a schema into the specified context from a file.
Radek Krejci86d106e2018-10-18 09:53:19 +0200999 *
1000 * @param[in] ctx libyang context where to process the data model.
1001 * @param[in] path Path to the file with the model in the specified format.
1002 * @param[in] format Format of the input data (YANG or YIN).
1003 * @return Pointer to the data model structure or NULL on error.
1004 */
Radek Krejcid14e9692018-11-01 11:00:37 +01001005struct lys_module *lys_parse_path(struct ly_ctx *ctx, const char *path, LYS_INFORMAT format);
Radek Krejci86d106e2018-10-18 09:53:19 +02001006
1007/**
Radek Krejcid33273d2018-10-25 14:55:52 +02001008 * @brief Search for the schema file in the specified searchpaths.
1009 *
1010 * @param[in] searchpaths NULL-terminated array of paths to be searched (recursively). Current working
1011 * directory is searched automatically (but non-recursively if not in the provided list). Caller can use
1012 * result of the ly_ctx_get_searchdirs().
1013 * @param[in] cwd Flag to implicitly search also in the current working directory (non-recursively).
1014 * @param[in] name Name of the schema to find.
1015 * @param[in] revision Revision of the schema to find. If NULL, the newest found schema filepath is returned.
1016 * @param[out] localfile Mandatory output variable containing absolute path of the found schema. If no schema
1017 * complying the provided restriction is found, NULL is set.
1018 * @param[out] format Optional output variable containing expected format of the schema document according to the
1019 * file suffix.
1020 * @return LY_ERR value (LY_SUCCESS is returned even if the file is not found, then the *localfile is NULL).
1021 */
1022LY_ERR lys_search_localfile(const char * const *searchpaths, int cwd, const char *name, const char *revision, char **localfile, LYS_INFORMAT *format);
1023
1024/**
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001025 * @defgroup scflags Schema compile flags
1026 * @ingroup schematree
1027 *
1028 * @{
1029 */
1030#define LYSC_OPT_FREE_SP 1 /**< Free the input printable schema */
1031
1032/**
1033 * @}
1034 */
1035
1036/**
1037 * @brief Compile printable schema into a validated schema linking all the references.
1038 *
Radek Krejcif8f882a2018-10-31 14:51:15 +01001039 * @param[in, out] mod Schema structure holding pointers to both schema structure types. The ::lys_module#parsed
1040 * member is used as input and ::lys_module#compiled is used to hold the result of the compilation.
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001041 * @param[in] options Various options to modify compiler behavior, see [compile flags](@ref scflags).
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001042 * @return LY_ERR value.
1043 */
Radek Krejcid14e9692018-11-01 11:00:37 +01001044LY_ERR lys_compile(struct lys_module *mod, int options);
Radek Krejcidd4e8d42018-10-16 14:55:43 +02001045
Radek Krejci5aeea3a2018-09-05 13:29:36 +02001046/** @} */
1047
Radek Krejci70853c52018-10-15 14:46:16 +02001048#ifdef __cplusplus
1049}
1050#endif
1051
Radek Krejci5aeea3a2018-09-05 13:29:36 +02001052#endif /* LY_TREE_SCHEMA_H_ */