blob: 5c9ae31faecdc816219b2409eb245b1fac76ce82 [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
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
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
Michal Vaskofc2cd072021-02-24 13:17:17 +010014#define _GNU_SOURCE
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020017#include <ctype.h>
18#include <errno.h>
19#include <stdarg.h>
20#include <stdbool.h>
Radek Krejci47fab892020-11-05 17:02:41 +010021#include <stdint.h>
David Sedlák3b4db242018-10-19 16:11:01 +020022#include <stdio.h>
23#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020024#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
Radek Krejci535ea9f2020-05-29 16:01:05 +020026#include "common.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010027#include "compat.h"
David Sedlákf824ad52018-10-14 23:58:15 +020028#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010030#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020031#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010032#include "log.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020033#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020034#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020035#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020036#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020037#include "tree.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010038#include "tree_data_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020039#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020040#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020041#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020042
David Sedlák2b214ac2019-06-06 16:11:03 +020043/**
44 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020045 *
David Sedlák2b214ac2019-06-06 16:11:03 +020046 * @param ns Namespace URI to check.
47 *
48 * @return true if ns equals YIN_NS_URI false otherwise.
49 */
50#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
51
Michal Vaskoafac7822020-10-20 14:22:26 +020052enum yin_argument {
53 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
54 YIN_ARG_NAME, /**< argument name */
55 YIN_ARG_TARGET_NODE, /**< argument target-node */
56 YIN_ARG_MODULE, /**< argument module */
57 YIN_ARG_VALUE, /**< argument value */
58 YIN_ARG_TEXT, /**< argument text */
59 YIN_ARG_CONDITION, /**< argument condition */
60 YIN_ARG_URI, /**< argument uri */
61 YIN_ARG_DATE, /**< argument data */
62 YIN_ARG_TAG, /**< argument tag */
63 YIN_ARG_NONE /**< empty (special value) */
64};
65
Michal Vasko22df3f02020-08-24 13:29:22 +020066const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020067 [YIN_ARG_NAME] = "name",
68 [YIN_ARG_TARGET_NODE] = "target-node",
69 [YIN_ARG_MODULE] = "module",
70 [YIN_ARG_VALUE] = "value",
71 [YIN_ARG_TEXT] = "text",
72 [YIN_ARG_CONDITION] = "condition",
73 [YIN_ARG_URI] = "uri",
74 [YIN_ARG_DATE] = "date",
75 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020076 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020077};
78
Michal Vaskoafac7822020-10-20 14:22:26 +020079#define yin_attr2str(STMT) yin_attr_list[STMT]
80
81#define VALID_VALS1 " Only valid value is \"%s\"."
82#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
83#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
84#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
85
86/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
87#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
88 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
89 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
90 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
91
92/* flags to set constraints of subelements */
93#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
94#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
95#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
96#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
97
98#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
99 time to simply check validity of given constraints */
100
101struct yin_subelement {
102 enum ly_stmt type; /**< type of keyword */
103 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
104 uint16_t flags; /**< describes constraints of subelement can be set to YIN_SUBELEM_MANDATORY, YIN_SUBELEM_UNIQUE, YIN_SUBELEM_FIRST, YIN_SUBELEM_VER2, and YIN_SUBELEM_DEFAULT_TEXT */
105};
106
107/* Meta information passed to yin_parse_argument function,
108 holds information about where content of argument element will be stored. */
109struct yin_argument_meta {
110 uint16_t *flags; /**< Argument flags */
111 const char **argument; /**< Argument value */
112};
113
114/**
115 * @brief Meta information passed to functions working with tree_schema,
116 * that require additional information about parent node.
117 */
118struct tree_node_meta {
119 struct lysp_node *parent; /**< parent node */
120 struct lysp_node **nodes; /**< linked list of siblings */
121};
122
123/**
124 * @brief Meta information passed to yin_parse_import function.
125 */
126struct import_meta {
127 const char *prefix; /**< module prefix. */
128 struct lysp_import **imports; /**< imports to add to. */
129};
130
131/**
132 * @brief Meta information passed to yin_parse_include function.
133 */
134struct include_meta {
135 const char *name; /**< Module/submodule name. */
136 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
137};
138
139/**
140 * @brief Meta information passed to yin_parse_inout function.
141 */
142struct inout_meta {
143 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100144 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200145};
146
147/**
148 * @brief Meta information passed to yin_parse_minmax function.
149 */
150struct minmax_dev_meta {
151 uint32_t *lim; /**< min/max value to write to. */
152 uint16_t *flags; /**< min/max flags to write to. */
153 struct lysp_ext_instance **exts; /**< extension instances to add to. */
154};
155
156LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
157 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
158
159/**
160 * @brief Match yang keyword from yin data.
161 *
162 * @param[in,out] ctx Yin parser context for logging and to store current state.
163 * @param[in] name Start of keyword name
164 * @param[in] name_len Lenght of keyword name.
165 * @param[in] prefix Start of keyword prefix.
166 * @param[in] prefix_len Lenght of prefix.
167 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
168 *
169 * @return yang_keyword values.
170 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200171enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100172yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200173 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200174{
David Sedlák8f7a1172019-06-20 14:42:18 +0200175 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200176 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200177 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200178 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200179
Michal Vasko69730152020-10-09 16:30:07 +0200180 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200181 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200182 }
183
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200184 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200185 if (ns) {
186 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200187 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200188 }
189 } else {
190 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200191 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200192 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200193
Michal Vasko63f3d842020-07-08 10:10:14 +0200194 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
195 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100196 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200197 name = in->current;
198 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200199
200 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200201 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
Michal Vasko69730152020-10-09 16:30:07 +0200202 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200203 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200204 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200205 return kw;
206 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200207 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200208 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200209 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200210 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200211 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200212 }
213}
214
Michal Vaskoafac7822020-10-20 14:22:26 +0200215/**
216 * @brief Match argument name.
217 *
218 * @param[in] name String representing name.
219 * @param[in] len Lenght of the name.
220 *
221 * @return yin_argument values.
222 */
David Sedlákc5b20842019-08-13 10:18:31 +0200223enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200224yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200225{
David Sedlákc5b20842019-08-13 10:18:31 +0200226 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200227 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200228
David Sedlák7ff55a92019-06-17 11:11:41 +0200229 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200230
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200231#define READ_INC(LEN) already_read += LEN
232#define ARG_SET(STMT) arg=STMT
233#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100234
David Sedlák1c8b2702019-02-22 11:03:02 +0100235 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100236 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200237 READ_INC(1);
238 if (ARG_CHECK("ondition", 8)) {
239 ARG_SET(YIN_ARG_CONDITION);
240 }
David Sedlák3b4db242018-10-19 16:11:01 +0200241 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200242
David Sedlák94de2aa2019-02-15 12:42:11 +0100243 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200244 READ_INC(1);
245 if (ARG_CHECK("ate", 3)) {
246 ARG_SET(YIN_ARG_DATE);
247 }
David Sedlák3b4db242018-10-19 16:11:01 +0200248 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200249
David Sedlák94de2aa2019-02-15 12:42:11 +0100250 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200251 READ_INC(1);
252 if (ARG_CHECK("odule", 5)) {
253 ARG_SET(YIN_ARG_MODULE);
254 }
David Sedlák872c7b42018-10-26 13:15:20 +0200255 break;
256
David Sedlák94de2aa2019-02-15 12:42:11 +0100257 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200258 READ_INC(1);
259 if (ARG_CHECK("ame", 3)) {
260 ARG_SET(YIN_ARG_NAME);
261 }
David Sedlák872c7b42018-10-26 13:15:20 +0200262 break;
263
David Sedlák94de2aa2019-02-15 12:42:11 +0100264 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200265 READ_INC(1);
266 if (ARG_CHECK("a", 1)) {
267 if (ARG_CHECK("g", 1)) {
268 ARG_SET(YIN_ARG_TAG);
269 } else if (ARG_CHECK("rget-node", 9)) {
270 ARG_SET(YIN_ARG_TARGET_NODE);
271 }
272 } else if (ARG_CHECK("ext", 3)) {
273 ARG_SET(YIN_ARG_TEXT);
274 }
David Sedlák3b4db242018-10-19 16:11:01 +0200275 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200276
David Sedlák94de2aa2019-02-15 12:42:11 +0100277 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200278 READ_INC(1);
279 if (ARG_CHECK("ri", 2)) {
280 ARG_SET(YIN_ARG_URI);
281 }
David Sedlák3b4db242018-10-19 16:11:01 +0200282 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200283
David Sedlák94de2aa2019-02-15 12:42:11 +0100284 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200285 READ_INC(1);
286 if (ARG_CHECK("alue", 4)) {
287 ARG_SET(YIN_ARG_VALUE);
288 }
David Sedlák3b4db242018-10-19 16:11:01 +0200289 break;
290 }
291
David Sedlákc10e7902018-12-17 02:17:59 +0100292 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200293 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200294 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200295 }
296
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200297#undef ARG_CHECK
298#undef ARG_SET
299#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100300
David Sedlák872c7b42018-10-26 13:15:20 +0200301 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200302}
303
Radek Krejcid6b76452019-09-03 17:03:03 +0200304#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
305 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
306 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
307 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200308
Radek Krejcid6b76452019-09-03 17:03:03 +0200309#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == LY_STMT_IMPORT || kw == LY_STMT_INCLUDE || kw == LY_STMT_INPUT || kw == LY_STMT_OUTPUT)
David Sedlák81497a32019-08-13 16:56:26 +0200310
David Sedlák26ea1432019-08-14 13:42:23 +0200311/**
312 * @brief Free subelems information allocated on heap.
313 *
314 * @param[in] count Size of subelems array.
315 * @param[in] subelems Subelems array to free.
316 */
David Sedlák81497a32019-08-13 16:56:26 +0200317static void
318subelems_deallocator(size_t count, struct yin_subelement *subelems)
319{
Michal Vaskod989ba02020-08-24 10:59:24 +0200320 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200321 if (HAS_META(subelems[i].type)) {
322 free(subelems[i].dest);
323 }
324 }
325
326 free(subelems);
327}
328
David Sedlák26ea1432019-08-14 13:42:23 +0200329/**
330 * @brief Allocate subelems information on heap.
331 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200332 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200333 * @param[in] count Number of subelements.
334 * @param[in] parent Parent node if any.
335 * @param[out] result Allocated subelems array.
336 *
337 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
338 */
David Sedlák81497a32019-08-13 16:56:26 +0200339static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100340subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200341 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200342{
343 va_list ap;
344
345 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200346 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200347
348 va_start(ap, result);
349 for (size_t i = 0; i < count; ++i) {
350 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200351 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200352 /* DEST */
353 if (IS_NODE_ELEM((*result)[i].type)) {
354 struct tree_node_meta *node_meta = NULL;
355 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200356 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200357 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200358 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200359 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200360 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200361 struct import_meta *imp_meta = NULL;
362 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200363 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200364 imp_meta->prefix = va_arg(ap, const char *);
365 imp_meta->imports = va_arg(ap, struct lysp_import **);
366 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200367 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200368 struct include_meta *inc_meta = NULL;
369 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200370 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200371 inc_meta->name = va_arg(ap, const char *);
372 inc_meta->includes = va_arg(ap, struct lysp_include **);
373 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200374 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200375 struct inout_meta *inout_meta = NULL;
376 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200377 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200378 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100379 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200380 (*result)[i].dest = inout_meta;
381 } else {
382 (*result)[i].dest = va_arg(ap, void *);
383 }
384 /* FLAGS */
385 (*result)[i].flags = va_arg(ap, int);
386 }
387 va_end(ap);
388
389 return LY_SUCCESS;
390
David Sedlákbf8a2b72019-08-14 16:48:10 +0200391mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200392 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100393 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200394 return LY_EMEM;
395}
396
Michal Vaskoafac7822020-10-20 14:22:26 +0200397/**
398 * @brief Check that val is valid UTF8 character sequence of val_type.
399 * Doesn't check empty string, only character validity.
400 *
401 * @param[in] ctx Yin parser context for logging.
402 * @param[in] val_type Type of the input string to select method of checking character validity.
403 *
404 * @return LY_ERR values.
405 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200406LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100407yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200408{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200409 uint8_t prefix = 0;
410 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100411 size_t utf8_char_len, already_read = 0;
412 const char *val;
413
414 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
415
416 val = ctx->xmlctx->value;
417 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200418 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200419 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200420 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100421 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200422
423 switch (val_type) {
424 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200425 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, NULL));
David Sedlák4a650532019-07-10 11:55:18 +0200426 break;
427 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200428 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, &prefix));
David Sedlák4a650532019-07-10 11:55:18 +0200429 break;
430 case Y_STR_ARG:
431 case Y_MAYBE_STR_ARG:
432 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
433 break;
434 }
435 }
436
437 return LY_SUCCESS;
438}
439
David Sedlákb4e44562019-07-04 15:42:12 +0200440/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100441 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200442 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200443 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200444 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
445 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200446 * @param[out] arg_val Where value of argument should be stored. Can be NULL iff arg_type is specified as YIN_ARG_NONE.
David Sedlák292763b2019-07-09 11:10:53 +0200447 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200448 * @param[in] current_element Identification of current element, used for logging.
449 *
450 * @return LY_ERR values.
451 */
452static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100453yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200454 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200455{
David Sedlákc5b20842019-08-13 10:18:31 +0200456 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200457 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200458
David Sedlák1bccdfa2019-06-17 15:55:27 +0200459 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100460 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200461 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100462 if (!ctx->xmlctx->prefix) {
463 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200464 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100465 /* skip it */
466 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200467 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200468 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200469 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200470 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100471
472 /* go to value */
473 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
474 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200475 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg_val);
David Sedlák169cc522019-08-15 13:23:45 +0200476 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200477 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100478 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200479 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200480 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200481 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100482 } else {
483 /* skip it */
484 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200485 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100486
487 /* next attribute */
488 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200489 }
490
David Sedlák292763b2019-07-09 11:10:53 +0200491 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200492 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100493 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200494 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200495 return LY_EVALID;
496 }
497
498 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200499}
500
David Sedlákd6e56892019-07-01 15:40:24 +0200501/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200502 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200503 *
504 * @param[in] type Type of wanted record.
505 * @param[in] array_size Size of array.
506 * @param[in] array Searched array.
507 *
508 * @return Pointer to desired record on success, NULL if element is not in the array.
509 */
David Sedlákb4e44562019-07-04 15:42:12 +0200510static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200511get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200512{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200513 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200514 if (array[u].type == type) {
515 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200516 }
517 }
David Sedlákd6e56892019-07-01 15:40:24 +0200518 return NULL;
519}
520
David Sedlákbba38e52019-07-09 15:20:01 +0200521/**
522 * @brief Helper function to check mandatory constraint of subelement.
523 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200524 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200525 * @param[in] subelem_info Array of information about subelements.
526 * @param[in] subelem_info_size Size of subelem_info array.
527 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
528 *
529 * @return LY_ERR values.
530 */
531static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100532yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200533 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200534{
David Sedlákb0faad82019-07-04 14:28:59 +0200535 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200536 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200537 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200538 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200539 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200540 return LY_EVALID;
541 }
542 }
543
544 return LY_SUCCESS;
545}
546
David Sedlákbba38e52019-07-09 15:20:01 +0200547/**
548 * @brief Helper function to check "first" constraint of subelement.
549 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200550 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200551 * @param[in] subelem_info Array of information about subelements.
552 * @param[in] subelem_info_size Size of subelem_info array.
553 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200554 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement, used for logging.
David Sedlákbba38e52019-07-09 15:20:01 +0200555 *
556 * @return LY_ERR values.
557 */
558static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100559yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200560 signed char subelem_info_size, enum ly_stmt current_element,
561 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200562{
David Sedlákb0faad82019-07-04 14:28:59 +0200563 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200564 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200565 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200566 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200567 return LY_EVALID;
568 }
569 }
570
571 return LY_SUCCESS;
572}
573
David Sedlákbba38e52019-07-09 15:20:01 +0200574/**
David Sedlákb4e44562019-07-04 15:42:12 +0200575 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
576 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200577 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200578 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200579 * @param[in] kw Type of current element.
580 * @param[out] value Where value of attribute should be stored.
581 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200582 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200583 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200584 * @return LY_ERR values.
585 */
David Sedlákb4e44562019-07-04 15:42:12 +0200586static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100587yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200588 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200589{
Michal Vaskob36053d2020-03-26 15:49:30 +0100590 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
591 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100592 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200593 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
594 };
David Sedlákb4e44562019-07-04 15:42:12 +0200595
Radek Krejcif13b87b2020-12-01 22:02:17 +0100596 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200597}
598
599/**
David Sedlák6542aed2019-08-14 10:47:43 +0200600 * @brief Parse path element.
601 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200602 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200603 * @param[in] kw Type of current element.
604 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200605 * @return LY_ERR values.
606 */
607static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100608yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200609{
Michal Vasko004d3152020-06-11 19:59:22 +0200610 LY_ERR ret;
611 const char *str_path;
612
613 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
Michal Vasko6b26e742020-07-17 15:02:10 +0200614 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +0200615 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200616 lydict_remove(ctx->xmlctx->ctx, str_path);
617 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200618 type->flags |= LYS_SET_PATH;
619
620 return LY_SUCCESS;
621}
622
623/**
David Sedlákd3983112019-07-12 11:20:56 +0200624 * @brief Parse pattern element.
625 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200626 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200627 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200628 * @return LY_ERR values.
629 */
630static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100631yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200632{
633 const char *real_value = NULL;
634 char *saved_value = NULL;
635 struct lysp_restr *restr;
636
Michal Vaskob36053d2020-03-26 15:49:30 +0100637 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
638 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
639 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &real_value, Y_STR_ARG, LY_STMT_PATTERN));
David Sedlákd3983112019-07-12 11:20:56 +0200640 size_t len = strlen(real_value);
641
642 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100643 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200644 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100645 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100646 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200647 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200648 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200649 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200650 type->flags |= LYS_SET_PATTERN;
651
Radek Krejcif13b87b2020-12-01 22:02:17 +0100652 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200653 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
654 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
655 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
656 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
657 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
658 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
659 };
Michal Vasko69730152020-10-09 16:30:07 +0200660
Radek Krejcif13b87b2020-12-01 22:02:17 +0100661 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200662}
663
David Sedlákc5b20842019-08-13 10:18:31 +0200664/**
665 * @brief Parse fraction-digits element.
666 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200667 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200668 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200669 * @return LY_ERR values.
670 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200671static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100672yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200673{
674 const char *temp_val = NULL;
675 char *ptr;
676 unsigned long int num;
677
Michal Vaskob36053d2020-03-26 15:49:30 +0100678 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
679 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_FRACTION_DIGITS));
David Sedlákf75d55e2019-07-12 16:52:50 +0200680
Michal Vasko69730152020-10-09 16:30:07 +0200681 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200682 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100683 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200684 return LY_EVALID;
685 }
686
687 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100688 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200689 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200690 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100691 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200692 return LY_EVALID;
693 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100694 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200695 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100696 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200697 return LY_EVALID;
698 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100699 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200700 type->fraction_digits = num;
701 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100702 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200703 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
704 };
Michal Vasko69730152020-10-09 16:30:07 +0200705
Radek Krejcif13b87b2020-12-01 22:02:17 +0100706 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200707}
708
David Sedlák07869a52019-07-12 14:28:19 +0200709/**
David Sedlák43801c92019-08-05 15:58:54 +0200710 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200711 *
712 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200713 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200714 * @return LY_ERR values.
715 */
David Sedlákca36c422019-07-12 12:47:55 +0200716static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100717yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200718{
David Sedlák07869a52019-07-12 14:28:19 +0200719 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200720
Michal Vaskob36053d2020-03-26 15:49:30 +0100721 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200722 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100723 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
724 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200725 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100726 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200727 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200728
Radek Krejcif13b87b2020-12-01 22:02:17 +0100729 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200730 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
731 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
732 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
733 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
734 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
735 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
736 };
Michal Vasko69730152020-10-09 16:30:07 +0200737
Radek Krejcif13b87b2020-12-01 22:02:17 +0100738 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200739}
740
741/**
742 * @brief Parse bit element.
743 *
744 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200745 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200746 * @return LY_ERR values.
747 */
748static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100749yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200750{
751 struct lysp_type_enum *en;
752
Michal Vaskob36053d2020-03-26 15:49:30 +0100753 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200754 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100755 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
756 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
David Sedlák43801c92019-08-05 15:58:54 +0200757 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
758
Radek Krejcif13b87b2020-12-01 22:02:17 +0100759 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200760 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
761 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
762 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
763 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
764 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
765 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
766 };
Michal Vasko69730152020-10-09 16:30:07 +0200767
Radek Krejcif13b87b2020-12-01 22:02:17 +0100768 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200769}
770
David Sedlákd3983112019-07-12 11:20:56 +0200771/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200772 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
773 * more instances, such as base or if-feature.
774 *
775 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200776 * @param[in] kw Type of current element.
777 * @param[out] values Parsed values to add to.
778 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200779 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200780 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200781 * @return LY_ERR values.
782 */
783static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100784yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200785 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200786{
787 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200788
Michal Vaskob36053d2020-03-26 15:49:30 +0100789 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200790 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100791 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200792 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
793 };
David Sedlák968ac342019-07-11 15:17:59 +0200794
Michal Vaskob36053d2020-03-26 15:49:30 +0100795 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
796 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200797
Radek Krejcif13b87b2020-12-01 22:02:17 +0100798 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200799}
800
801/**
David Sedlák6542aed2019-08-14 10:47:43 +0200802 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
803 *
804 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200805 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200806 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
David Sedlák6542aed2019-08-14 10:47:43 +0200807 * @param[in] arg_type Expected type of attribute.
808 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200809 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200810 * @return LY_ERR values.
811 */
812static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100813yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200814 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200815{
816 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100817 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200818 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200819 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100820 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200821 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200822 }
823
824 return LY_SUCCESS;
825}
826
827/**
828 * @brief Parse base element.
829 *
830 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200831 * @param[in] parent Identification of parent element.
832 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200833 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200834 * @return LY_ERR values.
835 */
836static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100837yin_parse_base(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, void *dest, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200838{
839 struct lysp_type *type = NULL;
840
Radek Krejcid6b76452019-09-03 17:03:03 +0200841 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200842 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100843 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200844 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200845 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200846 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100847 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200848 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200849 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100850 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200851 return LY_EINT;
852 }
853
854 return LY_SUCCESS;
855}
856
857/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200858 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200859 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200860 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100861 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200862 * @return LY_ERR values.
863 */
864static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100865yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200866{
867 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100868 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200869 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
870 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200871
872 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100873 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
874 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_REQUIRE_INSTANCE));
David Sedlákcf5569a2019-07-11 13:31:34 +0200875 if (strcmp(temp_val, "true") == 0) {
876 type->require_instance = 1;
877 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200878 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200879 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100880 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200881 return LY_EVALID;
882 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100883 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200884
Radek Krejcif13b87b2020-12-01 22:02:17 +0100885 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200886}
887
888/**
David Sedlákce77bf52019-07-11 16:59:31 +0200889 * @brief Parse modifier element.
890 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200891 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200892 * @param[in,out] pat Value to write to.
893 * @param[in,out] exts Extension instances to add to.
894 *
895 * @return LY_ERR values.
896 */
897static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100898yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200899{
David Sedlákd3983112019-07-12 11:20:56 +0200900 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200901 const char *temp_val;
902 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100903 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200904 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
905 };
David Sedlákce77bf52019-07-11 16:59:31 +0200906
Michal Vaskob36053d2020-03-26 15:49:30 +0100907 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
908 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MODIFIER));
David Sedlákce77bf52019-07-11 16:59:31 +0200909 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200910 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200911 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100912 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200913 return LY_EVALID;
914 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100915 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200916
917 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200918 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100919 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200920 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100921 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200922
923 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100924 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200925 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200926
Radek Krejcif13b87b2020-12-01 22:02:17 +0100927 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200928}
929
930/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200931 * @brief Parse a restriction element (length, range or one instance of must).
932 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200933 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200934 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to LY_STMT_MUST, LY_STMT_LENGTH or LY_STMT_RANGE.
David Sedlák6542aed2019-08-14 10:47:43 +0200935 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200936 */
937static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100938yin_parse_restriction(struct lys_yin_parser_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200939{
Radek Krejcid6b76452019-09-03 17:03:03 +0200940 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100941 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200942 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
943 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
944 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
945 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
946 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
947 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200948 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200949 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200950
Michal Vaskob36053d2020-03-26 15:49:30 +0100951 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200952 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200953 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100954
Radek Krejcif13b87b2020-12-01 22:02:17 +0100955 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200956}
957
958/**
David Sedlák6542aed2019-08-14 10:47:43 +0200959 * @brief Parse range element.
960 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200961 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200962 * @param[out] type Type structure to store parsed value and flags.
963 *
964 * @return LY_ERR values.
965 */
966static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100967yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200968{
969 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100970 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
971 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200972 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200973
974 return LY_SUCCESS;
975}
976
977/**
978 * @brief Parse length element.
979 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200980 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200981 * @param[out] type Type structure to store parsed value and flags.
982 *
983 * @return LY_ERR values.
984 */
985static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100986yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200987{
988 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100989 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
990 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200991 type->flags |= LYS_SET_LENGTH;
992
993 return LY_SUCCESS;
994}
995
996/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200997 * @brief Parse must element.
998 *
999 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001000 * @param[in,out] restrs Restrictions to add to.
1001 *
1002 * @return LY_ERR values.
1003 */
1004static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001005yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001006{
1007 struct lysp_restr *restr;
1008
Michal Vaskob36053d2020-03-26 15:49:30 +01001009 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1010 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001011}
1012
1013/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001014 * @brief Parse a node id into an array.
1015 *
1016 * @param[in,out] ctx YIN parser context for logging and to store current state.
1017 * @param[in] kw Type of current element.
1018 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1019 * @param[in,out] exts Extension instances to add to.
1020 *
1021 * @return LY_ERR values.
1022 */
1023static LY_ERR
1024yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1025 struct lysp_ext_instance **exts)
1026{
1027 struct lysp_qname *qname, **qnames;
1028
1029 switch (kw) {
1030 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001031 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1032 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001033 } else {
1034 qnames = (struct lysp_qname **)subinfo->dest;
1035 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001036 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001037 qname->mod = ctx->parsed_mod;
1038 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
1039 case LY_STMT_IF_FEATURE:
1040 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1041 qnames = (struct lysp_qname **)subinfo->dest;
1042 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1043 qname->mod = ctx->parsed_mod;
1044 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001045 default:
1046 break;
1047 }
1048
1049 LOGINT(ctx->xmlctx->ctx);
1050 return LY_EINT;
1051}
1052
1053/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001054 * @brief Parse position or value element.
1055 *
1056 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001057 * @param[in] kw Type of current element, can be set to LY_STMT_POSITION or LY_STMT_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001058 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001059 *
1060 * @return LY_ERR values.
1061 */
1062static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001063yin_parse_value_pos(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +02001064{
Radek Krejcid6b76452019-09-03 17:03:03 +02001065 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001066 const char *temp_val = NULL;
1067 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +02001068 long int num = 0;
1069 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001070
1071 /* set value flag */
1072 enm->flags |= LYS_SET_VALUE;
1073
1074 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001075 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1076 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001077 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001078 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001079 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001080 goto error;
1081 }
1082
1083 /* convert value */
1084 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001085 if (kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001086 num = strtol(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001087 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001088 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001089 goto error;
1090 }
1091 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001092 unum = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001093 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001094 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001095 goto error;
1096 }
1097 }
1098 /* check if whole argument value was converted */
1099 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001100 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +02001101 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001102 }
1103 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001104 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001105 goto error;
1106 }
1107 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001108 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001109 enm->value = num;
1110 } else {
1111 enm->value = unum;
1112 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001113 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001114
1115 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001116 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001117 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1118 };
Michal Vasko69730152020-10-09 16:30:07 +02001119
Radek Krejcif13b87b2020-12-01 22:02:17 +01001120 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001121
David Sedlákbf8a2b72019-08-14 16:48:10 +02001122error:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001123 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskob36053d2020-03-26 15:49:30 +01001124 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001125}
1126
David Sedlák05404f62019-07-24 14:11:53 +02001127/**
1128 * @brief Parse belongs-to element.
1129 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001130 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001131 * @param[out] submod Structure of submodule that is being parsed.
1132 * @param[in,out] exts Extension instances to add to.
1133 *
1134 * @return LY_ERR values
1135 */
1136static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001137yin_parse_belongs_to(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod, struct lysp_ext_instance **exts)
David Sedlák05404f62019-07-24 14:11:53 +02001138{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001139 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001140 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001141 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1142 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1143 };
David Sedlák05404f62019-07-24 14:11:53 +02001144
Michal Vaskob36053d2020-03-26 15:49:30 +01001145 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001146 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001147 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001148 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001149 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001150 lydict_remove(ctx->xmlctx->ctx, belongsto);
1151 return LY_EVALID;
1152 }
1153 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001154
Radek Krejcif13b87b2020-12-01 22:02:17 +01001155 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001156}
1157
David Sedlák5545f5d2019-07-11 11:55:16 +02001158/**
David Sedlákc1771b12019-07-10 15:55:46 +02001159 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001160 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001161 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001162 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001163 * @param[in] elem_type Type of element can be set to LY_STMT_ORGANIZATION or LY_STMT_CONTACT or LY_STMT_DESCRIPTION or LY_STMT_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +02001164 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001165 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001166 *
1167 * @return LY_ERR values.
1168 */
1169static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001170yin_parse_meta(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001171{
Radek Krejcid6b76452019-09-03 17:03:03 +02001172 assert(elem_type == LY_STMT_ORGANIZATION || elem_type == LY_STMT_CONTACT || elem_type == LY_STMT_DESCRIPTION || elem_type == LY_STMT_REFERENCE);
David Sedlákb4e44562019-07-04 15:42:12 +02001173
Radek Krejcif13b87b2020-12-01 22:02:17 +01001174 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001175 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1176 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1177 };
Michal Vasko69730152020-10-09 16:30:07 +02001178
David Sedlákdf2a9732019-08-07 13:23:16 +02001179 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001180 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1181 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, elem_type));
David Sedlákb4e44562019-07-04 15:42:12 +02001182
David Sedlákdf2a9732019-08-07 13:23:16 +02001183 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001184 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001185}
1186
1187/**
David Sedlákc1771b12019-07-10 15:55:46 +02001188 * @brief Parse error-message element.
1189 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001190 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001191 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001192 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001193 *
1194 * @return LY_ERR values.
1195 */
1196static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001197yin_parse_err_msg(struct lys_yin_parser_ctx *ctx, const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001198{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001199 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001200 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1201 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1202 };
David Sedlákc1771b12019-07-10 15:55:46 +02001203
David Sedlákdf2a9732019-08-07 13:23:16 +02001204 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001205 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1206 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
David Sedlákdf2a9732019-08-07 13:23:16 +02001207
Radek Krejcif13b87b2020-12-01 22:02:17 +01001208 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001209}
1210
1211/**
David Sedlák6542aed2019-08-14 10:47:43 +02001212 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001213 *
1214 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001215 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001216 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001217 *
1218 * @return LY_ERR values.
1219 */
1220static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001221yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001222{
David Sedlák6542aed2019-08-14 10:47:43 +02001223 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001224
Radek Krejcid6b76452019-09-03 17:03:03 +02001225 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001226 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001227 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001228 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001229 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001230 type = (struct lysp_type *)subinfo->dest;
1231 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001232
David Sedlák6542aed2019-08-14 10:47:43 +02001233 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001234 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001235 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001236 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001237 type->flags |= LYS_SET_TYPE;
1238 type = nested_type;
1239 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001240
Michal Vasko5bbcc242021-02-23 09:29:13 +01001241 type->pmod = ctx->parsed_mod;
1242
Radek Krejcif13b87b2020-12-01 22:02:17 +01001243 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001244 {LY_STMT_BASE, type, 0},
1245 {LY_STMT_BIT, type, 0},
1246 {LY_STMT_ENUM, type, 0},
1247 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1248 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1249 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1250 {LY_STMT_PATTERN, type, 0},
1251 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1252 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1253 {LY_STMT_TYPE, type},
1254 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1255 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001256
1257 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1258 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01001259 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001260}
1261
David Sedlák1af868e2019-07-17 17:03:14 +02001262/**
1263 * @brief Parse max-elements element.
1264 *
1265 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001266 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001267 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001268 * @param[in,out] exts Extension instances to add to.
1269 *
1270 * @return LY_ERR values.
1271 */
1272static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001273yin_parse_maxelements(struct lys_yin_parser_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák1af868e2019-07-17 17:03:14 +02001274{
1275 const char *temp_val = NULL;
1276 char *ptr;
1277 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001278 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001279 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1280 };
David Sedlák374d2b32019-07-17 15:06:55 +02001281
David Sedlák1af868e2019-07-17 17:03:14 +02001282 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001283 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1284 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
Michal Vasko69730152020-10-09 16:30:07 +02001285 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '0') || ((temp_val[0] != 'u') && !isdigit(temp_val[0]))) {
David Sedlák1538a842019-08-08 15:38:51 +02001286 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001287 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001288 return LY_EVALID;
1289 }
1290
1291 if (strcmp(temp_val, "unbounded")) {
1292 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001293 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001294 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001295 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001296 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001297 return LY_EVALID;
1298 }
1299 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001300 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001301 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001302 return LY_EVALID;
1303 }
1304 *max = num;
1305 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001306 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001307 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001308}
David Sedlák374d2b32019-07-17 15:06:55 +02001309
1310/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001311 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001312 *
1313 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001314 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001315 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001316 * @param[in,out] exts Extension instances to add to.
1317 *
1318 * @return LY_ERR values.
1319 */
1320static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001321yin_parse_minelements(struct lys_yin_parser_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák09e18c92019-07-18 11:17:11 +02001322{
1323 const char *temp_val = NULL;
1324 char *ptr;
1325 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001326 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001327 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1328 };
David Sedlák09e18c92019-07-18 11:17:11 +02001329
1330 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001331 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1332 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +02001333
Michal Vasko69730152020-10-09 16:30:07 +02001334 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001335 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001336 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001337 return LY_EVALID;
1338 }
1339
1340 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001341 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001342 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001343 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001344 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001345 return LY_EVALID;
1346 }
Michal Vasko69730152020-10-09 16:30:07 +02001347 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001348 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001349 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001350 return LY_EVALID;
1351 }
1352 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001353 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001354 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001355}
1356
David Sedláka2dad212019-07-18 12:45:19 +02001357/**
1358 * @brief Parse min-elements or max-elements element.
1359 *
1360 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001361 * @param[in] parent Identification of parent element.
1362 * @param[in] current Identification of current element.
1363 * @param[in] dest Where the parsed value and flags should be stored.
1364 *
1365 * @return LY_ERR values.
1366 */
David Sedlák09e18c92019-07-18 11:17:11 +02001367static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001368yin_parse_minmax(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001369{
Radek Krejcid6b76452019-09-03 17:03:03 +02001370 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1371 assert(parent == LY_STMT_LEAF_LIST || parent == LY_STMT_REFINE || parent == LY_STMT_LIST || parent == LY_STMT_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001372 uint32_t *lim;
1373 uint16_t *flags;
1374 struct lysp_ext_instance **exts;
1375
Radek Krejcid6b76452019-09-03 17:03:03 +02001376 if (parent == LY_STMT_LEAF_LIST) {
1377 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001378 flags = &((struct lysp_node_leaflist *)dest)->flags;
1379 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001380 } else if (parent == LY_STMT_REFINE) {
1381 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001382 flags = &((struct lysp_refine *)dest)->flags;
1383 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001384 } else if (parent == LY_STMT_LIST) {
1385 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001386 flags = &((struct lysp_node_list *)dest)->flags;
1387 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001388 } else {
1389 lim = ((struct minmax_dev_meta *)dest)->lim;
1390 flags = ((struct minmax_dev_meta *)dest)->flags;
1391 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001392 }
1393
Radek Krejcid6b76452019-09-03 17:03:03 +02001394 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001395 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001396 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001397 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001398 }
1399
1400 return LY_SUCCESS;
1401}
1402
1403/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001404 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001405 *
1406 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001407 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001408 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001409 *
1410 * @return LY_ERR values.
1411 */
1412static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001413yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001414{
1415 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001416 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001417 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1418 };
David Sedláka2dad212019-07-18 12:45:19 +02001419
Michal Vaskob36053d2020-03-26 15:49:30 +01001420 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1421 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
David Sedláka2dad212019-07-18 12:45:19 +02001422 if (strcmp(temp_val, "system") == 0) {
1423 *flags |= LYS_ORDBY_SYSTEM;
1424 } else if (strcmp(temp_val, "user") == 0) {
1425 *flags |= LYS_ORDBY_USER;
1426 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001427 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001428 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001429 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001430 return LY_EVALID;
1431 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001432 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001433
Radek Krejcif13b87b2020-12-01 22:02:17 +01001434 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001435}
1436
1437/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001438 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001439 *
1440 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001441 * @param[in] any_kw Identification of current element, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
David Sedlákad83cf92019-08-13 12:53:53 +02001442 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001443 *
1444 * @return LY_ERR values.
1445 */
1446static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001447yin_parse_any(struct lys_yin_parser_ctx *ctx, enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001448{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001449 struct lysp_node_anydata *any;
1450
David Sedlák8d552d62019-08-06 15:29:05 +02001451 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001452 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001453 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001454 any->parent = node_meta->parent;
1455
David Sedlákbf8a2b72019-08-14 16:48:10 +02001456 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001457 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1458 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &any->name, Y_IDENTIF_ARG, any_kw));
David Sedlák8a83bbb2019-07-18 14:46:00 +02001459
Radek Krejcif13b87b2020-12-01 22:02:17 +01001460 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001461 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1462 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1464 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_MUST, &any->musts, 0},
1466 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1467 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1468 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1469 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1470 };
Michal Vasko69730152020-10-09 16:30:07 +02001471
Radek Krejcif13b87b2020-12-01 22:02:17 +01001472 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001473}
1474
1475/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001476 * @brief parse leaf element.
1477 *
1478 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001479 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001480 *
1481 * @return LY_ERR values.
1482 */
1483static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001484yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001485{
David Sedlák203ca3a2019-07-18 15:26:25 +02001486 struct lysp_node_leaf *leaf;
1487
David Sedlák8d552d62019-08-06 15:29:05 +02001488 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001489 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001490 leaf->nodetype = LYS_LEAF;
1491 leaf->parent = node_meta->parent;
1492
David Sedlák203ca3a2019-07-18 15:26:25 +02001493 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001494 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1495 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, LY_STMT_LEAF));
David Sedlák203ca3a2019-07-18 15:26:25 +02001496
1497 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001498 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001499 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1500 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1501 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1502 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1503 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1504 {LY_STMT_MUST, &leaf->musts, 0},
1505 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1506 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1507 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1508 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1509 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1511 };
Michal Vasko69730152020-10-09 16:30:07 +02001512
Radek Krejcif13b87b2020-12-01 22:02:17 +01001513 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001514}
1515
1516/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001517 * @brief Parse leaf-list element.
1518 *
1519 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001520 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001521 *
1522 * @return LY_ERR values.
1523 */
1524static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001525yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001526{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001527 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001528
Michal Vaskob36053d2020-03-26 15:49:30 +01001529 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001530
David Sedlákc3da3ef2019-07-19 12:56:08 +02001531 llist->nodetype = LYS_LEAFLIST;
1532 llist->parent = node_meta->parent;
1533
David Sedlákc3da3ef2019-07-19 12:56:08 +02001534 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001535 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1536 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, LY_STMT_LEAF_LIST));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001537
1538 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001539 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001540 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1541 {LY_STMT_DEFAULT, &llist->dflts, 0},
1542 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1543 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1544 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1545 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1546 {LY_STMT_MUST, &llist->musts, 0},
1547 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1548 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1550 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1551 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1552 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1553 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1554 };
Michal Vasko69730152020-10-09 16:30:07 +02001555
Radek Krejcif13b87b2020-12-01 22:02:17 +01001556 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001557
David Sedlákbf8a2b72019-08-14 16:48:10 +02001558 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001559 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001560 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001561 return LY_EVALID;
1562 }
Michal Vasko69730152020-10-09 16:30:07 +02001563 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001564 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001565 return LY_EVALID;
1566 }
1567
1568 return LY_SUCCESS;
1569}
1570
1571/**
David Sedlák04e17b22019-07-19 15:29:48 +02001572 * @brief Parse typedef element.
1573 *
1574 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001575 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001576 *
1577 * @return LY_ERR values.
1578 */
1579static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001580yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001581{
1582 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001583 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001584
Michal Vaskob36053d2020-03-26 15:49:30 +01001585 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001586
1587 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001588 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1589 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
David Sedlák04e17b22019-07-19 15:29:48 +02001590
1591 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001592 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001593 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1594 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1596 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1597 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1598 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1599 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1600 };
Michal Vasko69730152020-10-09 16:30:07 +02001601
Radek Krejcif13b87b2020-12-01 22:02:17 +01001602 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001603
1604 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001605 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1606 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001607 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001608 }
1609
1610 return LY_SUCCESS;
1611}
1612
1613/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001614 * @brief Parse refine element.
1615 *
1616 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001617 * @param[in,out] refines Refines to add to.
1618 *
1619 * @return LY_ERR values.
1620 */
1621static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001622yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001623{
1624 struct lysp_refine *rf;
1625
1626 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001627 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001628
1629 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001630 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1631 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1632 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001633
1634 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001635 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001636 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001637 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001638 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001639 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001640 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1641 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1642 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1643 {LY_STMT_MUST, &rf->musts, 0},
1644 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1645 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1646 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1647 };
Michal Vasko69730152020-10-09 16:30:07 +02001648
Radek Krejcif13b87b2020-12-01 22:02:17 +01001649 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001650}
1651
1652/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001653 * @brief Parse uses element.
1654 *
1655 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001656 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001657 *
1658 * @return LY_ERR values.
1659 */
1660static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001661yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001662{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001663 struct lysp_node_uses *uses;
1664
David Sedlák8d552d62019-08-06 15:29:05 +02001665 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001666 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001667 uses->nodetype = LYS_USES;
1668 uses->parent = node_meta->parent;
1669
David Sedlák0d6de5a2019-07-22 13:25:44 +02001670 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001671 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1672 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, LY_STMT_USES));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001673
1674 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001675 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001676 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001677 {LY_STMT_AUGMENT, &augments, 0},
1678 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1679 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1680 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1681 {LY_STMT_REFINE, &uses->refines, 0},
1682 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1683 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1684 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1685 };
Michal Vasko69730152020-10-09 16:30:07 +02001686
Radek Krejcif13b87b2020-12-01 22:02:17 +01001687 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001688
1689 return LY_SUCCESS;
1690}
1691
1692/**
David Sedlákaa854b02019-07-22 14:17:10 +02001693 * @brief Parse revision element.
1694 *
1695 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001696 * @param[in,out] revs Parsed revisions to add to.
1697 *
1698 * @return LY_ERR values.
1699 */
1700static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001701yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001702{
1703 struct lysp_revision *rev;
1704 const char *temp_date = NULL;
1705
1706 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001707 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001708
1709 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001710 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1711 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_date, Y_STR_ARG, LY_STMT_REVISION));
David Sedlákaa854b02019-07-22 14:17:10 +02001712 /* check value */
1713 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001714 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001715 return LY_EVALID;
1716 }
Radek Krejci36642162021-01-12 16:49:22 +01001717 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001718 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001719
1720 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001721 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001722 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1723 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1724 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1725 };
Michal Vasko69730152020-10-09 16:30:07 +02001726
Radek Krejcif13b87b2020-12-01 22:02:17 +01001727 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001728}
1729
David Sedlák5e13dea2019-07-22 16:06:45 +02001730/**
1731 * @brief Parse include element.
1732 *
1733 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001734 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1735 *
1736 * @return LY_ERR values.
1737 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001738static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001739yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001740{
1741 struct lysp_include *inc;
1742
1743 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001744 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001745
1746 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001747 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1748 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, LY_STMT_INCLUDE));
David Sedlák0c2bab92019-07-22 15:33:19 +02001749
1750 /* submodules share the namespace with the module names, so there must not be
1751 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001752 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001753 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001754 return LY_EVALID;
1755 }
1756
1757 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001758 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001759 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1760 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1761 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1762 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1763 };
Michal Vasko69730152020-10-09 16:30:07 +02001764
Radek Krejcif13b87b2020-12-01 22:02:17 +01001765 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001766}
1767
David Sedlákaa854b02019-07-22 14:17:10 +02001768/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001769 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001770 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001771 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001772 * @param[in,out] rev Array to store the parsed value in.
1773 * @param[in,out] exts Extension instances to add to.
1774 *
1775 * @return LY_ERR values.
1776 */
1777static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001778yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001779{
1780 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001781 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001782 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1783 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001784
Michal Vaskob36053d2020-03-26 15:49:30 +01001785 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1786 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
David Sedlákdfbbb442019-08-06 16:33:21 +02001787 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskoe180ed02021-02-05 16:31:20 +01001788 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001789
1790 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001791 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001792
Radek Krejcif13b87b2020-12-01 22:02:17 +01001793 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001794}
1795
1796/**
1797 * @brief Parse config element.
1798 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001799 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001800 * @param[in,out] flags Flags to add to.
1801 * @param[in,out] exts Extension instances to add to.
1802 *
1803 * @return LY_ERR values.
1804 */
1805static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001806yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001807{
1808 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001809 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001810 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1811 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001812
Michal Vaskob36053d2020-03-26 15:49:30 +01001813 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1814 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
David Sedlákdfbbb442019-08-06 16:33:21 +02001815 if (strcmp(temp_val, "true") == 0) {
1816 *flags |= LYS_CONFIG_W;
1817 } else if (strcmp(temp_val, "false") == 0) {
1818 *flags |= LYS_CONFIG_R;
1819 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001820 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001821 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001822 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001823 return LY_EVALID;
1824 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001825 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001826
Radek Krejcif13b87b2020-12-01 22:02:17 +01001827 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001828}
1829
1830/**
1831 * @brief Parse yang-version element.
1832 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001833 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001834 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001835 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001836 *
1837 * @return LY_ERR values.
1838 */
1839static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001840yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001841{
1842 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001843 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001844 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1845 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001846
Michal Vaskob36053d2020-03-26 15:49:30 +01001847 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1848 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
Radek Krejci96e48da2020-09-04 13:18:06 +02001849 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001850 *version = LYS_VERSION_1_0;
1851 } else if (strcmp(temp_version, "1.1") == 0) {
1852 *version = LYS_VERSION_1_1;
1853 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001854 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001855 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001856 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001857 return LY_EVALID;
1858 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001859 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001860
Radek Krejcif13b87b2020-12-01 22:02:17 +01001861 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001862}
1863
1864/**
1865 * @brief Parse import element.
1866 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001867 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001868 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1869 *
1870 * @return LY_ERR values.
1871 */
1872static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001873yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001874{
1875 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001876
David Sedlákdfbbb442019-08-06 16:33:21 +02001877 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001878 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001879
Radek Krejcif13b87b2020-12-01 22:02:17 +01001880 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001881 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1882 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1883 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1884 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1885 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1886 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001887
1888 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001889 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1890 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
Radek Krejcif13b87b2020-12-01 22:02:17 +01001891 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001892 /* check prefix validity */
1893 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1894
1895 return LY_SUCCESS;
1896}
1897
1898/**
1899 * @brief Parse mandatory element.
1900 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001901 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001902 * @param[in,out] flags Flags to add to.
1903 * @param[in,out] exts Extension instances to add to.
1904 *
1905 * @return LY_ERR values.
1906 */
1907static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001908yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001909{
1910 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001911 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001912 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1913 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001914
Michal Vaskob36053d2020-03-26 15:49:30 +01001915 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1916 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MANDATORY));
David Sedlákdfbbb442019-08-06 16:33:21 +02001917 if (strcmp(temp_val, "true") == 0) {
1918 *flags |= LYS_MAND_TRUE;
1919 } else if (strcmp(temp_val, "false") == 0) {
1920 *flags |= LYS_MAND_FALSE;
1921 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001922 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001923 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001924 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001925 return LY_EVALID;
1926 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001927 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001928
Radek Krejcif13b87b2020-12-01 22:02:17 +01001929 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001930}
1931
1932/**
1933 * @brief Parse status element.
1934 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001935 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001936 * @param[in,out] flags Flags to add to.
1937 * @param[in,out] exts Extension instances to add to.
1938 *
1939 * @return LY_ERR values.
1940 */
1941static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001942yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001943{
1944 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001945 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001946 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1947 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001948
Michal Vaskob36053d2020-03-26 15:49:30 +01001949 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1950 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &value, Y_STR_ARG, LY_STMT_STATUS));
David Sedlákdfbbb442019-08-06 16:33:21 +02001951 if (strcmp(value, "current") == 0) {
1952 *flags |= LYS_STATUS_CURR;
1953 } else if (strcmp(value, "deprecated") == 0) {
1954 *flags |= LYS_STATUS_DEPRC;
1955 } else if (strcmp(value, "obsolete") == 0) {
1956 *flags |= LYS_STATUS_OBSLT;
1957 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001958 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001959 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001960 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001961 return LY_EVALID;
1962 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001963 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001964
Radek Krejcif13b87b2020-12-01 22:02:17 +01001965 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001966}
1967
1968/**
1969 * @brief Parse when element.
1970 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001971 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001972 * @param[out] when_p When pointer to parse to.
1973 */
1974static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001975yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001976{
1977 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001978 LY_ERR ret = LY_SUCCESS;
1979
David Sedlákdfbbb442019-08-06 16:33:21 +02001980 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001981 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001982
1983 ret = lyxml_ctx_next(ctx->xmlctx);
1984 LY_CHECK_ERR_RET(ret, free(when), ret);
1985
Michal Vaskob36053d2020-03-26 15:49:30 +01001986 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001987 LY_CHECK_ERR_RET(ret, free(when), ret);
1988
David Sedlákdfbbb442019-08-06 16:33:21 +02001989 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001990 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001991 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1992 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1993 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1994 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001995
Radek Krejcif13b87b2020-12-01 22:02:17 +01001996 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001997}
1998
1999/**
2000 * @brief Parse yin-elemenet element.
2001 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002002 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002003 * @param[in,out] data Data to read from, always moved to currently handled position.
2004 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002005 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002006 *
2007 * @return LY_ERR values.
2008 */
2009static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002010yin_parse_yin_element(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002011{
2012 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002013 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002014 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2015 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002016
Michal Vaskob36053d2020-03-26 15:49:30 +01002017 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2018 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_YIN_ELEMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02002019 if (strcmp(temp_val, "true") == 0) {
2020 *flags |= LYS_YINELEM_TRUE;
2021 } else if (strcmp(temp_val, "false") == 0) {
2022 *flags |= LYS_YINELEM_FALSE;
2023 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002024 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002025 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002026 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002027 return LY_EVALID;
2028 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002029 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002030
Radek Krejcif13b87b2020-12-01 22:02:17 +01002031 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002032}
2033
2034/**
2035 * @brief Parse argument element.
2036 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002037 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002038 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2039 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002040 *
2041 * @return LY_ERR values.
2042 */
2043static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002044yin_parse_argument(struct lys_yin_parser_ctx *ctx, struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002045{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002046 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002047 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2048 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2049 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002050
Michal Vaskob36053d2020-03-26 15:49:30 +01002051 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2052 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02002053
Radek Krejcif13b87b2020-12-01 22:02:17 +01002054 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002055}
2056
2057/**
2058 * @brief Parse the extension statement.
2059 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002060 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002061 * @param[in,out] extensions Extensions to add to.
2062 *
2063 * @return LY_ERR values.
2064 */
2065static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002066yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002067{
2068 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002069
Michal Vaskob36053d2020-03-26 15:49:30 +01002070 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2071 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2072 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, LY_STMT_EXTENSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02002073
2074 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002075 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002076 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2077 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2078 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2079 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2080 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2081 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002082
Radek Krejcif13b87b2020-12-01 22:02:17 +01002083 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002084}
2085
2086/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002087 * @brief Parse feature element.
2088 *
2089 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002090 * @param[in,out] features Features to add to.
2091 *
2092 * @return LY_ERR values.
2093 */
2094static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002095yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002096{
2097 struct lysp_feature *feat;
2098
2099 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002100 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002101
2102 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002103 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2104 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, LY_STMT_FEATURE));
David Sedlák5e13dea2019-07-22 16:06:45 +02002105
2106 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002107 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002108 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2109 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2110 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2111 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2112 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2113 };
Michal Vasko69730152020-10-09 16:30:07 +02002114
Radek Krejcif13b87b2020-12-01 22:02:17 +01002115 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002116}
2117
2118/**
David Sedlák28794f22019-07-22 16:45:00 +02002119 * @brief Parse identity element.
2120 *
2121 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002122 * @param[in,out] identities Identities to add to.
2123 *
2124 * @return LY_ERR values.
2125 */
2126static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002127yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002128{
2129 struct lysp_ident *ident;
2130
2131 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002132 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002133
2134 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002135 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2136 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, LY_STMT_IDENTITY));
David Sedlák28794f22019-07-22 16:45:00 +02002137
2138 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002139 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002140 {LY_STMT_BASE, &ident->bases, 0},
2141 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2142 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2143 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2144 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2145 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2146 };
Michal Vasko69730152020-10-09 16:30:07 +02002147
Radek Krejcif13b87b2020-12-01 22:02:17 +01002148 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002149}
2150
2151/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002152 * @brief Parse list element.
2153 *
2154 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002155 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002156 *
2157 * @return LY_ERR values.
2158 */
2159static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002160yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002161{
David Sedlákaf536aa2019-07-23 13:42:23 +02002162 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002163 LY_ERR ret = LY_SUCCESS;
2164 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002165 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002166
Michal Vaskob36053d2020-03-26 15:49:30 +01002167 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002168 list->nodetype = LYS_LIST;
2169 list->parent = node_meta->parent;
2170
David Sedlákaf536aa2019-07-23 13:42:23 +02002171 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002172 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2173 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, LY_STMT_LIST));
David Sedlákaf536aa2019-07-23 13:42:23 +02002174
2175 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002176 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002177 LY_STMT_ACTION, &list->actions, 0,
2178 LY_STMT_ANYDATA, &list->child, 0,
2179 LY_STMT_ANYXML, &list->child, 0,
2180 LY_STMT_CHOICE, &list->child, 0,
2181 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2182 LY_STMT_CONTAINER, &list->child, 0,
2183 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2184 LY_STMT_GROUPING, &list->groupings, 0,
2185 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2186 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2187 LY_STMT_LEAF, &list->child, 0,
2188 LY_STMT_LEAF_LIST, &list->child, 0,
2189 LY_STMT_LIST, &list->child, 0,
2190 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2191 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2192 LY_STMT_MUST, &list->musts, 0,
2193 LY_STMT_NOTIFICATION, &list->notifs, 0,
2194 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2195 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2196 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2197 LY_STMT_TYPEDEF, &list->typedefs, 0,
2198 LY_STMT_UNIQUE, &list->uniques, 0,
2199 LY_STMT_USES, &list->child, 0,
2200 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2201 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002202 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2203 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002204 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002205
Michal Vasko69730152020-10-09 16:30:07 +02002206 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002207 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002208 return LY_EVALID;
2209 }
2210
2211 return LY_SUCCESS;
2212}
2213
2214/**
David Sedlák031b9e72019-07-23 15:19:37 +02002215 * @brief Parse notification element.
2216 *
2217 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002218 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002219 *
2220 * @return LY_ERR values.
2221 */
2222static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002223yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002224{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002225 struct lysp_node_notif *notif;
2226 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002227 LY_ERR ret = LY_SUCCESS;
2228 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002229 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002230
2231 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002232 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002233 notif->nodetype = LYS_NOTIF;
2234 notif->parent = notif_meta->parent;
2235
2236 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002237 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2238 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
David Sedlák031b9e72019-07-23 15:19:37 +02002239
2240 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002241 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002242 LY_STMT_ANYDATA, &notif->child, 0,
2243 LY_STMT_ANYXML, &notif->child, 0,
2244 LY_STMT_CHOICE, &notif->child, 0,
2245 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002246 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2247 LY_STMT_GROUPING, &notif->groupings, 0,
2248 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002249 LY_STMT_LEAF, &notif->child, 0,
2250 LY_STMT_LEAF_LIST, &notif->child, 0,
2251 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002252 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2253 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2254 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2255 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002256 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002257 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002258
Radek Krejcif13b87b2020-12-01 22:02:17 +01002259 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2260 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002261 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002262
David Sedlák031b9e72019-07-23 15:19:37 +02002263 return LY_SUCCESS;
2264}
2265
2266/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002267 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002268 *
2269 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002270 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002271 *
2272 * @return LY_ERR values.
2273 */
2274static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002275yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002276{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002277 struct lysp_node_grp *grp;
2278 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002279 LY_ERR ret = LY_SUCCESS;
2280 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002281 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002282
2283 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002284 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002285 grp->nodetype = LYS_GROUPING;
2286 grp->parent = gr_meta->parent;
2287
2288 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002289 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2290 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, LY_STMT_GROUPING));
David Sedláke3ce9ef2019-07-23 16:34:30 +02002291
2292 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002293 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002294 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002295 LY_STMT_ANYDATA, &grp->child, 0,
2296 LY_STMT_ANYXML, &grp->child, 0,
2297 LY_STMT_CHOICE, &grp->child, 0,
2298 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002299 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2300 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002301 LY_STMT_LEAF, &grp->child, 0,
2302 LY_STMT_LEAF_LIST, &grp->child, 0,
2303 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002304 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2305 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2306 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2307 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002308 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002309 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002310 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2311 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002312
Radek Krejci2a9fc652021-01-22 17:44:34 +01002313 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002314}
2315
2316/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002317 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002318 *
2319 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002320 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002321 *
2322 * @return LY_ERR values.
2323 */
2324static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002325yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002326{
David Sedlákf111bcb2019-07-23 17:15:51 +02002327 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002328 LY_ERR ret = LY_SUCCESS;
2329 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002330 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002331
2332 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002333 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002334 cont->nodetype = LYS_CONTAINER;
2335 cont->parent = node_meta->parent;
2336
David Sedlákf111bcb2019-07-23 17:15:51 +02002337 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002338 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2339 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, LY_STMT_CONTAINER));
David Sedlákf111bcb2019-07-23 17:15:51 +02002340
2341 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002342 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002343 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2344 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2345 LY_STMT_ANYXML, &cont->child, 0,
2346 LY_STMT_CHOICE, &cont->child, 0,
2347 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2348 LY_STMT_CONTAINER, &cont->child, 0,
2349 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_GROUPING, &cont->groupings, 0,
2351 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2352 LY_STMT_LEAF, &cont->child, 0,
2353 LY_STMT_LEAF_LIST, &cont->child, 0,
2354 LY_STMT_LIST, &cont->child, 0,
2355 LY_STMT_MUST, &cont->musts, 0,
2356 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2357 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2358 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2360 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2361 LY_STMT_USES, &cont->child, 0,
2362 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2363 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002364 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2365 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002366
Radek Krejci2a9fc652021-01-22 17:44:34 +01002367 return ret;
David Sedlákf111bcb2019-07-23 17:15:51 +02002368}
2369
2370/**
David Sedlák5379d392019-07-24 10:42:03 +02002371 * @brief Parse case element.
2372 *
2373 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002374 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002375 *
2376 * @return LY_ERR values.
2377 */
2378static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002379yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002380{
David Sedlák5379d392019-07-24 10:42:03 +02002381 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002382 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002383 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002384 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002385
2386 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002387 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002388 cas->nodetype = LYS_CASE;
2389 cas->parent = node_meta->parent;
2390
David Sedlák5379d392019-07-24 10:42:03 +02002391 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002392 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2393 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, LY_STMT_CASE));
David Sedlák5379d392019-07-24 10:42:03 +02002394
2395 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002396 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002397 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2398 LY_STMT_ANYXML, &cas->child, 0,
2399 LY_STMT_CHOICE, &cas->child, 0,
2400 LY_STMT_CONTAINER, &cas->child, 0,
2401 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2402 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2403 LY_STMT_LEAF, &cas->child, 0,
2404 LY_STMT_LEAF_LIST, &cas->child, 0,
2405 LY_STMT_LIST, &cas->child, 0,
2406 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2407 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2408 LY_STMT_USES, &cas->child, 0,
2409 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2410 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002411 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2412 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002413
2414 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002415}
2416
2417/**
David Sedlák05404f62019-07-24 14:11:53 +02002418 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002419 *
2420 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002421 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002422 *
2423 * @return LY_ERR values.
2424 */
2425LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002426yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002427{
David Sedlák81497a32019-08-13 16:56:26 +02002428 LY_ERR ret = LY_SUCCESS;
2429 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002430 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002431 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002432
2433 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002434 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002435
David Sedlákb7abcfa2019-07-24 12:33:35 +02002436 choice->nodetype = LYS_CHOICE;
2437 choice->parent = node_meta->parent;
2438
David Sedlákb7abcfa2019-07-24 12:33:35 +02002439 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002440 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2441 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, LY_STMT_CHOICE));
David Sedlákb7abcfa2019-07-24 12:33:35 +02002442
2443 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002444 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002445 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2446 LY_STMT_ANYXML, &choice->child, 0,
2447 LY_STMT_CASE, &choice->child, 0,
2448 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2449 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2450 LY_STMT_CONTAINER, &choice->child, 0,
2451 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2452 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2453 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2454 LY_STMT_LEAF, &choice->child, 0,
2455 LY_STMT_LEAF_LIST, &choice->child, 0,
2456 LY_STMT_LIST, &choice->child, 0,
2457 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2458 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2459 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2460 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2461 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002462 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2463 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002464 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002465}
2466
2467/**
David Sedlák05404f62019-07-24 14:11:53 +02002468 * @brief Parse input or output element.
2469 *
2470 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002471 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002472 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2473 *
2474 * @return LY_ERR values.
2475 */
2476static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002477yin_parse_inout(struct lys_yin_parser_ctx *ctx, enum ly_stmt inout_kw, struct inout_meta *inout_meta)
David Sedlák05404f62019-07-24 14:11:53 +02002478{
David Sedlák81497a32019-08-13 16:56:26 +02002479 LY_ERR ret = LY_SUCCESS;
2480 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002481 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002482
David Sedlák05404f62019-07-24 14:11:53 +02002483 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002484 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name));
Radek Krejcid6b76452019-09-03 17:03:03 +02002485 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002486 inout_meta->inout_p->parent = inout_meta->parent;
2487
2488 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002489 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2490 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
David Sedlák05404f62019-07-24 14:11:53 +02002491
2492 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002493 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002494 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2495 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2496 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2497 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002498 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002499 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2500 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2501 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002502 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2503 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002504 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002505 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002506 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2507 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002508 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002509
Radek Krejci01180ac2021-01-27 08:48:22 +01002510 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002511 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2512 return LY_EVALID;
2513 }
2514
David Sedlák05404f62019-07-24 14:11:53 +02002515 return LY_SUCCESS;
2516}
2517
David Sedlák992fb7c2019-07-24 16:51:01 +02002518/**
2519 * @brief Parse action element.
2520 *
2521 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002522 * @param[in] act_meta Meta information about parent node and actions to add to.
2523 *
2524 * @return LY_ERR values.
2525 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002526static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002527yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002528{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002529 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002530 LY_ERR ret = LY_SUCCESS;
2531 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002532 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002533 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002534
2535 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002536 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002537 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002538 act->parent = act_meta->parent;
2539
2540 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002541 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002542 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002543
2544 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002545 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002546 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2547 LY_STMT_GROUPING, &act->groupings, 0,
2548 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2549 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2550 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2551 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2552 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2553 LY_STMT_TYPEDEF, &act->typedefs, 0,
2554 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002555 ret = (yin_parse_content(ctx, subelems, subelems_size, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002556 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002557 LY_CHECK_RET(ret);
2558
Michal Vasko7f45cf22020-10-01 12:49:44 +02002559 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2560 if (!act->input.nodetype) {
2561 act->input.nodetype = LYS_INPUT;
2562 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002563 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002564 }
2565 if (!act->output.nodetype) {
2566 act->output.nodetype = LYS_OUTPUT;
2567 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002568 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002569 }
2570
David Sedlák85d0eca2019-07-24 15:15:21 +02002571 return LY_SUCCESS;
2572}
2573
David Sedlák05404f62019-07-24 14:11:53 +02002574/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002575 * @brief Parse augment element.
2576 *
2577 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002578 * @param[in] aug_meta Meta information about parent node and augments to add to.
2579 *
2580 * @return LY_ERR values.
2581 */
2582static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002583yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002584{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002585 struct lysp_node_augment *aug;
2586 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002587 LY_ERR ret = LY_SUCCESS;
2588 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002589 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002590
2591 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002592 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002593 aug->nodetype = LYS_AUGMENT;
2594 aug->parent = aug_meta->parent;
2595
2596 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002597 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2598 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2599 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002600
2601 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002602 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002603 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2604 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2605 LY_STMT_ANYXML, &aug->child, 0,
2606 LY_STMT_CASE, &aug->child, 0,
2607 LY_STMT_CHOICE, &aug->child, 0,
2608 LY_STMT_CONTAINER, &aug->child, 0,
2609 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002610 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002611 LY_STMT_LEAF, &aug->child, 0,
2612 LY_STMT_LEAF_LIST, &aug->child, 0,
2613 LY_STMT_LIST, &aug->child, 0,
2614 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2615 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2616 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2617 LY_STMT_USES, &aug->child, 0,
2618 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2619 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002620 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2621 subelems_deallocator(subelems_size, subelems);
David Sedlák992fb7c2019-07-24 16:51:01 +02002622
Radek Krejci2a9fc652021-01-22 17:44:34 +01002623 return ret;
David Sedlák992fb7c2019-07-24 16:51:01 +02002624}
2625
David Sedlák8b754462019-07-25 16:22:13 +02002626/**
2627 * @brief Parse deviate element.
2628 *
2629 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002630 * @param[in] deviates Deviates to add to.
2631 *
2632 * @return LY_ERR values.
2633 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002634static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002635yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002636{
2637 LY_ERR ret = LY_SUCCESS;
2638 uint8_t dev_mod;
2639 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002640 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002641 struct lysp_deviate_add *d_add = NULL;
2642 struct lysp_deviate_rpl *d_rpl = NULL;
2643 struct lysp_deviate_del *d_del = NULL;
2644
2645 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002646 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2647 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_DEVIATE));
David Sedlák4ffcec82019-07-25 15:10:21 +02002648
2649 if (strcmp(temp_val, "not-supported") == 0) {
2650 dev_mod = LYS_DEV_NOT_SUPPORTED;
2651 } else if (strcmp(temp_val, "add") == 0) {
2652 dev_mod = LYS_DEV_ADD;
2653 } else if (strcmp(temp_val, "replace") == 0) {
2654 dev_mod = LYS_DEV_REPLACE;
2655 } else if (strcmp(temp_val, "delete") == 0) {
2656 dev_mod = LYS_DEV_DELETE;
2657 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002658 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002659 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002660 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002661 return LY_EVALID;
2662 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002663 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002664
2665 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2666 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002667 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002668 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002669 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2670 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002671 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002672
2673 } else if (dev_mod == LYS_DEV_ADD) {
2674 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002675 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002676 d = (struct lysp_deviate *)d_add;
2677 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2678 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002679 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002680 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002681 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002682 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2683 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2684 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2685 {LY_STMT_MUST, &d_add->musts, 0},
2686 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2687 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2688 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2689 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002690 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002691
2692 } else if (dev_mod == LYS_DEV_REPLACE) {
2693 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002694 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002695 d = (struct lysp_deviate *)d_rpl;
2696 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2697 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002698 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002699 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002700 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002701 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2702 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2703 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2704 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2705 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2706 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2707 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002708 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002709
2710 } else {
2711 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002712 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002713 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002714 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002715 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002716 {LY_STMT_MUST, &d_del->musts, 0},
2717 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2718 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2719 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2720 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002721 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002722 }
2723 LY_CHECK_GOTO(ret, cleanup);
2724
2725 d->mod = dev_mod;
2726 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002727 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002728
2729 return ret;
2730
2731cleanup:
2732 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002733 return ret;
2734}
2735
David Sedlák992fb7c2019-07-24 16:51:01 +02002736/**
David Sedlák8b754462019-07-25 16:22:13 +02002737 * @brief Parse deviation element.
2738 *
2739 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002740 * @param[in] deviations Deviations to add to.
2741 *
2742 * @return LY_ERR values.
2743 */
2744static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002745yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002746{
2747 struct lysp_deviation *dev;
2748
2749 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002750 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002751
2752 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002753 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2754 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2755 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002756 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002757 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2758 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2759 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2760 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2761 };
Michal Vasko69730152020-10-09 16:30:07 +02002762
Radek Krejcif13b87b2020-12-01 22:02:17 +01002763 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002764}
2765
2766/**
David Sedlákc5b20842019-08-13 10:18:31 +02002767 * @brief map keyword to keyword-group.
2768 *
2769 * @param[in] ctx YIN parser context used for logging.
2770 * @param[in] kw Keyword that is child of module or submodule.
2771 * @param[out] group Group of keyword.
2772 *
2773 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2774 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002775static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002776kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002777{
2778 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002779 /* module header */
2780 case LY_STMT_NONE:
2781 case LY_STMT_NAMESPACE:
2782 case LY_STMT_PREFIX:
2783 case LY_STMT_BELONGS_TO:
2784 case LY_STMT_YANG_VERSION:
2785 *group = Y_MOD_MODULE_HEADER;
2786 break;
2787 /* linkage */
2788 case LY_STMT_INCLUDE:
2789 case LY_STMT_IMPORT:
2790 *group = Y_MOD_LINKAGE;
2791 break;
2792 /* meta */
2793 case LY_STMT_ORGANIZATION:
2794 case LY_STMT_CONTACT:
2795 case LY_STMT_DESCRIPTION:
2796 case LY_STMT_REFERENCE:
2797 *group = Y_MOD_META;
2798 break;
2799 /* revision */
2800 case LY_STMT_REVISION:
2801 *group = Y_MOD_REVISION;
2802 break;
2803 /* body */
2804 case LY_STMT_ANYDATA:
2805 case LY_STMT_ANYXML:
2806 case LY_STMT_AUGMENT:
2807 case LY_STMT_CHOICE:
2808 case LY_STMT_CONTAINER:
2809 case LY_STMT_DEVIATION:
2810 case LY_STMT_EXTENSION:
2811 case LY_STMT_FEATURE:
2812 case LY_STMT_GROUPING:
2813 case LY_STMT_IDENTITY:
2814 case LY_STMT_LEAF:
2815 case LY_STMT_LEAF_LIST:
2816 case LY_STMT_LIST:
2817 case LY_STMT_NOTIFICATION:
2818 case LY_STMT_RPC:
2819 case LY_STMT_TYPEDEF:
2820 case LY_STMT_USES:
2821 case LY_STMT_EXTENSION_INSTANCE:
2822 *group = Y_MOD_BODY;
2823 break;
2824 default:
2825 LOGINT(ctx->xmlctx->ctx);
2826 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002827 }
2828
2829 return LY_SUCCESS;
2830}
2831
David Sedlákc5b20842019-08-13 10:18:31 +02002832/**
2833 * @brief Check if relative order of two keywords is valid.
2834 *
2835 * @param[in] ctx YIN parser context used for logging.
2836 * @param[in] kw Current keyword.
2837 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002838 * @param[in] parrent Identification of parrent element, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
David Sedlákc5b20842019-08-13 10:18:31 +02002839 * because relative order is required only in module and submodule sub-elements, used for logging.
2840 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002841 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002842 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002843static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002844yin_check_relative_order(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum ly_stmt next_kw, enum ly_stmt parrent)
David Sedláke6cd89e2019-08-07 12:46:02 +02002845{
Radek Krejcid6b76452019-09-03 17:03:03 +02002846 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002847 enum yang_module_stmt gr, next_gr;
2848
2849 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2850 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2851
2852 if (gr > next_gr) {
2853 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2854 return LY_EVALID;
2855 }
2856
2857 return LY_SUCCESS;
2858}
2859
David Sedlákc5dd0942019-09-13 10:23:59 +02002860/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002861 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2862 *
2863 * @param[in,out] ctx Yin parser context for logging and to store current state.
2864 * @param[in] elem_type Type of element that is currently being parsed.
2865 * @param[out] arg Value to write to.
2866 *
2867 * @return LY_ERR values.
2868 */
2869static LY_ERR
2870yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2871{
2872 enum ly_stmt child;
2873
2874 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2875
2876 switch (elem_type) {
2877 case LY_STMT_ACTION:
2878 case LY_STMT_ANYDATA:
2879 case LY_STMT_ANYXML:
2880 case LY_STMT_ARGUMENT:
2881 case LY_STMT_BASE:
2882 case LY_STMT_BIT:
2883 case LY_STMT_CASE:
2884 case LY_STMT_CHOICE:
2885 case LY_STMT_CONTAINER:
2886 case LY_STMT_ENUM:
2887 case LY_STMT_EXTENSION:
2888 case LY_STMT_FEATURE:
2889 case LY_STMT_GROUPING:
2890 case LY_STMT_IDENTITY:
2891 case LY_STMT_IF_FEATURE:
2892 case LY_STMT_LEAF:
2893 case LY_STMT_LEAF_LIST:
2894 case LY_STMT_LIST:
2895 case LY_STMT_MODULE:
2896 case LY_STMT_NOTIFICATION:
2897 case LY_STMT_RPC:
2898 case LY_STMT_SUBMODULE:
2899 case LY_STMT_TYPE:
2900 case LY_STMT_TYPEDEF:
2901 case LY_STMT_UNITS:
2902 case LY_STMT_USES:
2903 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
2904 break;
2905 case LY_STMT_AUGMENT:
2906 case LY_STMT_DEVIATION:
2907 case LY_STMT_REFINE:
2908 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
2909 break;
2910 case LY_STMT_CONFIG:
2911 case LY_STMT_DEFAULT:
2912 case LY_STMT_DEVIATE:
2913 case LY_STMT_ERROR_APP_TAG:
2914 case LY_STMT_FRACTION_DIGITS:
2915 case LY_STMT_KEY:
2916 case LY_STMT_LENGTH:
2917 case LY_STMT_MANDATORY:
2918 case LY_STMT_MAX_ELEMENTS:
2919 case LY_STMT_MIN_ELEMENTS:
2920 case LY_STMT_MODIFIER:
2921 case LY_STMT_ORDERED_BY:
2922 case LY_STMT_PATH:
2923 case LY_STMT_PATTERN:
2924 case LY_STMT_POSITION:
2925 case LY_STMT_PREFIX:
2926 case LY_STMT_PRESENCE:
2927 case LY_STMT_RANGE:
2928 case LY_STMT_REQUIRE_INSTANCE:
2929 case LY_STMT_STATUS:
2930 case LY_STMT_VALUE:
2931 case LY_STMT_YANG_VERSION:
2932 case LY_STMT_YIN_ELEMENT:
2933 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
2934 break;
2935 case LY_STMT_IMPORT:
2936 case LY_STMT_INCLUDE:
2937 case LY_STMT_BELONGS_TO:
2938 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
2939 break;
2940 case LY_STMT_INPUT:
2941 case LY_STMT_OUTPUT:
2942 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2943 break;
2944 case LY_STMT_MUST:
2945 case LY_STMT_WHEN:
2946 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
2947 break;
2948 case LY_STMT_NAMESPACE:
2949 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
2950 break;
2951 case LY_STMT_REVISION:
2952 case LY_STMT_REVISION_DATE:
2953 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
2954 break;
2955 case LY_STMT_UNIQUE:
2956 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
2957 break;
2958 /* argument is mapped to yin element */
2959 case LY_STMT_CONTACT:
2960 case LY_STMT_DESCRIPTION:
2961 case LY_STMT_ORGANIZATION:
2962 case LY_STMT_REFERENCE:
2963 case LY_STMT_ERROR_MESSAGE:
2964 /* there shouldn't be any attribute, argument is supposed to be first subelement */
2965 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2966
2967 /* no content */
2968 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
2969 if (ctx->xmlctx->ws_only) {
2970 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2971 }
2972 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
2973 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
2974 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
2975 return LY_EVALID;
2976 }
2977
2978 /* parse child element */
2979 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
2980 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
2981 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
2982 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
2983 ly_stmt2str(elem_type));
2984 return LY_EVALID;
2985 }
2986 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2987
2988 /* no attributes expected? TODO */
2989 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
2990 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2991 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2992 }
2993
2994 /* load and save content */
2995 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
2996 LY_CHECK_RET(!*arg, LY_EMEM);
2997
2998 /* load closing tag of subelement */
2999 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3000
3001 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3002 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3003 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3004 }*/
3005 break;
3006 default:
3007 LOGINT(ctx->xmlctx->ctx);
3008 return LY_EINT;
3009 }
3010
3011 return LY_SUCCESS;
3012}
3013
3014/**
3015 * @brief Parse yin element into generic structure.
3016 *
3017 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3018 * @param[in] parent Identification of parent element.
3019 * @param[out] element Where the element structure should be stored.
3020 *
3021 * @return LY_ERR values.
3022 */
3023LY_ERR
3024yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3025{
3026 LY_ERR ret = LY_SUCCESS;
3027 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003028 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003029
3030 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3031
3032 /* allocate new structure for element */
3033 *element = calloc(1, sizeof(**element));
3034 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003035
3036 /* store identifier */
3037 if (ctx->xmlctx->prefix_len) {
3038 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3039 ctx->xmlctx->name) == -1) {
3040 LOGMEM(ctx->xmlctx->ctx);
3041 ret = LY_EMEM;
3042 goto cleanup;
3043 }
3044 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3045
3046 /* store prefix data for the statement */
3047 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->stmt, strlen((*element)->stmt), LY_PREF_XML,
3048 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3049 } else {
3050 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3051 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003052
3053 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3054 ctx->xmlctx->prefix_len, parent);
3055
3056 last = (*element)->child;
3057 if ((*element)->kw == LY_STMT_NONE) {
3058 /* unrecognized element */
3059 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3060 ly_stmt2str(parent));
3061 ret = LY_EVALID;
3062 goto cleanup;
3063 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3064 /* element is known yang keyword, which means argument can be parsed correctly. */
3065 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3066 LY_CHECK_GOTO(ret, cleanup);
3067 } else {
3068 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3069
3070 /* load attributes in generic way, save all attributes in linked list */
3071 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3072 new = calloc(1, sizeof(*last));
3073 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3074 if (!(*element)->child) {
3075 /* save first */
3076 (*element)->child = new;
3077 } else {
3078 last->next = new;
3079 }
3080 last = new;
3081
3082 last->flags |= LYS_YIN_ATTR;
3083 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3084 last->kw = LY_STMT_NONE;
3085 /* attributes with prefix are ignored */
3086 if (!ctx->xmlctx->prefix) {
3087 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3088
3089 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3090 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3091 } else {
3092 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3093 }
3094 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3095 }
3096 }
3097
3098 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3099 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3100 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3101 /* parse subelements */
3102 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3103 LY_CHECK_GOTO(ret, cleanup);
3104 if (!(*element)->child) {
3105 /* save first */
3106 (*element)->child = new;
3107 } else {
3108 last->next = new;
3109 }
3110 last = new;
3111
3112 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3113 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3114 }
3115 } else {
3116 /* save element content */
3117 if (ctx->xmlctx->value_len) {
3118 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3119 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003120
3121 /* store prefix data for the argument as well */
3122 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->arg, strlen((*element)->arg), LY_PREF_XML,
3123 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003124 }
3125
3126 /* read closing tag */
3127 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3128 }
3129
3130cleanup:
3131 return ret;
3132}
3133
3134/**
3135 * @brief Parse instance of extension.
3136 *
3137 * @param[in,out] ctx Yin parser context for logging and to store current state.
Radek Krejcifc596f92021-02-26 22:40:26 +01003138 * @param[in] subelem The statement this extension instance is a subelement of.
Michal Vaskoafac7822020-10-20 14:22:26 +02003139 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3140 * @param[in,out] exts Extension instance to add to.
3141 *
3142 * @return LY_ERR values.
3143 */
3144LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01003145yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, enum ly_stmt subelem, LY_ARRAY_COUNT_TYPE subelem_index,
Michal Vaskoafac7822020-10-20 14:22:26 +02003146 struct lysp_ext_instance **exts)
3147{
3148 struct lysp_ext_instance *e;
3149 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003150 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003151
3152 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003153 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003154
3155 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3156
Michal Vaskofc2cd072021-02-24 13:17:17 +01003157 if (!ctx->xmlctx->prefix_len) {
3158 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3159 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3160 return LY_EVALID;
3161 }
3162
3163 /* store prefixed name */
3164 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3165 ctx->xmlctx->name) == -1) {
3166 LOGMEM(ctx->xmlctx->ctx);
3167 return LY_EMEM;
3168 }
3169 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3170
3171 /* store prefix data for the name */
3172 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->name, strlen(e->name), LY_PREF_XML, &ctx->xmlctx->ns,
3173 &e->format, &e->prefix_data));
3174
Radek Krejciab430862021-03-02 20:13:40 +01003175 e->parent_stmt = subelem;
3176 e->parent_stmt_index = subelem_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003177
Michal Vaskoafac7822020-10-20 14:22:26 +02003178 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3179
3180 /* store attributes as subelements */
3181 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3182 if (!ctx->xmlctx->prefix) {
3183 new_subelem = calloc(1, sizeof(*new_subelem));
3184 if (!e->child) {
3185 e->child = new_subelem;
3186 } else {
3187 last_subelem->next = new_subelem;
3188 }
3189 last_subelem = new_subelem;
3190
3191 last_subelem->flags |= LYS_YIN_ATTR;
3192 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3193 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3194 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3195
Michal Vaskofc2cd072021-02-24 13:17:17 +01003196 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3197 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003198 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3199 } else {
3200 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3201 }
3202
3203 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3204 }
3205
3206 /* parse subelements */
3207 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3208 if (ctx->xmlctx->ws_only) {
3209 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3210 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3211 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3212 if (!e->child) {
3213 e->child = new_subelem;
3214 } else {
3215 last_subelem->next = new_subelem;
3216 }
3217 last_subelem = new_subelem;
3218
3219 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3220 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3221 }
3222 } else if (ctx->xmlctx->value_len) {
3223 /* save text content */
3224 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3225 LY_CHECK_RET(!e->argument, LY_EMEM);
3226
Michal Vaskofc2cd072021-02-24 13:17:17 +01003227 /* store prefix data for the argument as well */
3228 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->argument, strlen(e->argument), LY_PREF_XML,
Radek Krejci07a55962021-03-02 20:16:43 +01003229 &ctx->xmlctx->ns, &e->format, &e->prefix_data));
Michal Vaskofc2cd072021-02-24 13:17:17 +01003230
Michal Vaskoafac7822020-10-20 14:22:26 +02003231 /* parser next */
3232 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3233 }
3234
3235 return LY_SUCCESS;
3236}
3237
3238/**
3239 * @brief Generic function for content parsing
3240 *
3241 * @param[in,out] ctx Yin parser context for logging and to store current state.
3242 * @param[in] subelem_info array of valid subelement types and meta information
3243 * @param[in] subelem_info_size Size of subelem_info array.
3244 * @param[in] current_element Type of current element.
3245 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3246 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3247 *
3248 * @return LY_ERR values.
3249 */
David Sedlákd6e56892019-07-01 15:40:24 +02003250LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003251yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Radek Krejci0f969882020-08-21 16:56:47 +02003252 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003253{
3254 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003255 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003256 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003257 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003258
Michal Vaskob36053d2020-03-26 15:49:30 +01003259 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003260
Michal Vaskob36053d2020-03-26 15:49:30 +01003261 if (ctx->xmlctx->ws_only) {
3262 /* check whether there are any children */
3263 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3264 } else {
3265 /* we want to parse the value */
3266 next_status = LYXML_ELEM_CLOSE;
3267 }
3268
3269 if (next_status == LYXML_ELEMENT) {
3270 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3271
3272 /* current element has subelements as content */
3273 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3274 /* match keyword */
3275 last_kw = kw;
3276 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003277 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003278
3279 /* check if this element can be child of current element */
3280 subelem = get_record(kw, subelem_info_size, subelem_info);
3281 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003282 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003283 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3284 } else {
3285 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003286 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003287 }
3288 ret = LY_EVALID;
3289 goto cleanup;
3290 }
3291
3292 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003293 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003294 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3295 LY_CHECK_GOTO(ret, cleanup);
3296 }
3297
3298 /* flag check */
3299 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3300 /* subelement uniquenes */
3301 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3302 return LY_EVALID;
3303 }
3304 if (subelem->flags & YIN_SUBELEM_FIRST) {
3305 /* subelement is supposed to be defined as first subelement */
3306 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3307 LY_CHECK_GOTO(ret, cleanup);
3308 }
3309 if (subelem->flags & YIN_SUBELEM_VER2) {
3310 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003311 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003312 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003313 ret = LY_EVALID;
3314 goto cleanup;
3315 }
David Sedlákd6e56892019-07-01 15:40:24 +02003316 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003317 /* note that element was parsed for easy uniqueness check in next iterations */
3318 subelem->flags |= YIN_SUBELEM_PARSED;
3319
3320 switch (kw) {
3321 /* call responsible function */
3322 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003323 ret = yin_parse_extension_instance(ctx, current_element,
Michal Vasko69730152020-10-09 16:30:07 +02003324 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003325 break;
3326 case LY_STMT_ACTION:
3327 case LY_STMT_RPC:
3328 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3329 break;
3330 case LY_STMT_ANYDATA:
3331 case LY_STMT_ANYXML:
3332 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3333 break;
3334 case LY_STMT_ARGUMENT:
3335 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3336 break;
3337 case LY_STMT_AUGMENT:
3338 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3339 break;
3340 case LY_STMT_BASE:
3341 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3342 break;
3343 case LY_STMT_BELONGS_TO:
3344 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3345 break;
3346 case LY_STMT_BIT:
3347 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3348 break;
3349 case LY_STMT_CASE:
3350 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3351 break;
3352 case LY_STMT_CHOICE:
3353 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3354 break;
3355 case LY_STMT_CONFIG:
3356 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3357 break;
3358 case LY_STMT_CONTACT:
3359 case LY_STMT_DESCRIPTION:
3360 case LY_STMT_ORGANIZATION:
3361 case LY_STMT_REFERENCE:
3362 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3363 break;
3364 case LY_STMT_CONTAINER:
3365 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3366 break;
3367 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003368 ret = yin_parse_qname(ctx, kw, subelem, exts);
3369 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003370 case LY_STMT_ERROR_APP_TAG:
3371 case LY_STMT_KEY:
3372 case LY_STMT_PRESENCE:
3373 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3374 break;
3375 case LY_STMT_DEVIATE:
3376 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3377 break;
3378 case LY_STMT_DEVIATION:
3379 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3380 break;
3381 case LY_STMT_ENUM:
3382 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3383 break;
3384 case LY_STMT_ERROR_MESSAGE:
3385 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3386 break;
3387 case LY_STMT_EXTENSION:
3388 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3389 break;
3390 case LY_STMT_FEATURE:
3391 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3392 break;
3393 case LY_STMT_FRACTION_DIGITS:
3394 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3395 break;
3396 case LY_STMT_GROUPING:
3397 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3398 break;
3399 case LY_STMT_IDENTITY:
3400 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3401 break;
3402 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003403 ret = yin_parse_qname(ctx, kw, subelem, exts);
3404 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003405 case LY_STMT_UNITS:
3406 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3407 break;
3408 case LY_STMT_IMPORT:
3409 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3410 break;
3411 case LY_STMT_INCLUDE:
Radek Krejcieeee95c2021-01-19 10:57:22 +01003412 if ((current_element == LY_STMT_SUBMODULE) && (ctx->parsed_mod->version == LYS_VERSION_1_1)) {
3413 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
3414 ((struct lysp_submodule *)(ctx->parsed_mod))->name);
3415 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003416 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3417 break;
3418 case LY_STMT_INPUT:
3419 case LY_STMT_OUTPUT:
3420 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3421 break;
3422 case LY_STMT_LEAF:
3423 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3424 break;
3425 case LY_STMT_LEAF_LIST:
3426 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3427 break;
3428 case LY_STMT_LENGTH:
3429 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3430 break;
3431 case LY_STMT_LIST:
3432 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3433 break;
3434 case LY_STMT_MANDATORY:
3435 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3436 break;
3437 case LY_STMT_MAX_ELEMENTS:
3438 case LY_STMT_MIN_ELEMENTS:
3439 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3440 break;
3441 case LY_STMT_MODIFIER:
3442 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3443 break;
3444 case LY_STMT_MUST:
3445 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3446 break;
3447 case LY_STMT_NAMESPACE:
3448 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3449 break;
3450 case LY_STMT_NOTIFICATION:
3451 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3452 break;
3453 case LY_STMT_ORDERED_BY:
3454 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3455 break;
3456 case LY_STMT_PATH:
3457 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3458 break;
3459 case LY_STMT_PATTERN:
3460 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3461 break;
3462 case LY_STMT_VALUE:
3463 case LY_STMT_POSITION:
3464 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3465 break;
3466 case LY_STMT_PREFIX:
3467 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3468 break;
3469 case LY_STMT_RANGE:
3470 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3471 break;
3472 case LY_STMT_REFINE:
3473 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3474 break;
3475 case LY_STMT_REQUIRE_INSTANCE:
3476 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3477 break;
3478 case LY_STMT_REVISION:
3479 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3480 break;
3481 case LY_STMT_REVISION_DATE:
3482 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3483 break;
3484 case LY_STMT_STATUS:
3485 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3486 break;
3487 case LY_STMT_TYPE:
3488 ret = yin_parse_type(ctx, current_element, subelem);
3489 break;
3490 case LY_STMT_TYPEDEF:
3491 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3492 break;
3493 case LY_STMT_UNIQUE:
3494 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3495 break;
3496 case LY_STMT_USES:
3497 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3498 break;
3499 case LY_STMT_WHEN:
3500 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3501 break;
3502 case LY_STMT_YANG_VERSION:
3503 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3504 break;
3505 case LY_STMT_YIN_ELEMENT:
3506 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3507 break;
3508 case LY_STMT_ARG_TEXT:
3509 case LY_STMT_ARG_VALUE:
3510 /* TODO what to do with content/attributes? */
3511 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3512 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3513 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3514 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3515 }
3516 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3517 break;
3518 default:
3519 LOGINT(ctx->xmlctx->ctx);
3520 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003521 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003522 LY_CHECK_GOTO(ret, cleanup);
3523 subelem = NULL;
3524
3525 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003526 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003527 } else {
3528 LY_CHECK_RET(ret);
3529 /* elements with text or none content */
3530 /* save text content, if text_content isn't set, it's just ignored */
3531 /* no resources are allocated in this branch, no need to use cleanup label */
3532 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3533 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003534 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *text_content);
Michal Vaskob36053d2020-03-26 15:49:30 +01003535 LY_CHECK_RET(!*text_content, LY_EMEM);
3536 }
3537
3538 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003539 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003540
David Sedlák8b754462019-07-25 16:22:13 +02003541 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3542 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003543
3544cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003545 return ret;
3546}
3547
David Sedlákaa98bba2019-09-12 11:52:14 +02003548/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003549 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003550 *
3551 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003552 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003553 *
3554 * @return LY_ERR values.
3555 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003556LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003557yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003558{
David Sedlák81497a32019-08-13 16:56:26 +02003559 LY_ERR ret = LY_SUCCESS;
3560 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003561 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003562 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003563
Michal Vaskoc3781c32020-10-06 14:04:08 +02003564 mod->is_submod = 0;
3565
Michal Vaskob36053d2020-03-26 15:49:30 +01003566 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3567 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01003568 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003569 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3570 LY_STMT_ANYXML, &mod->data, 0,
3571 LY_STMT_AUGMENT, &mod->augments, 0,
3572 LY_STMT_CHOICE, &mod->data, 0,
3573 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3574 LY_STMT_CONTAINER, &mod->data, 0,
3575 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3576 LY_STMT_DEVIATION, &mod->deviations, 0,
3577 LY_STMT_EXTENSION, &mod->extensions, 0,
3578 LY_STMT_FEATURE, &mod->features, 0,
3579 LY_STMT_GROUPING, &mod->groupings, 0,
3580 LY_STMT_IDENTITY, &mod->identities, 0,
3581 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3582 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3583 LY_STMT_LEAF, &mod->data, 0,
3584 LY_STMT_LEAF_LIST, &mod->data, 0,
3585 LY_STMT_LIST, &mod->data, 0,
3586 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3587 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3588 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3589 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3590 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3591 LY_STMT_REVISION, &mod->revs, 0,
3592 LY_STMT_RPC, &mod->rpcs, 0,
3593 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3594 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003595 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003596 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003597
Radek Krejcif13b87b2020-12-01 22:02:17 +01003598 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3599 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003600 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003601
David Sedláked809f12019-09-13 10:15:11 +02003602 /* submodules share the namespace with the module names, so there must not be
3603 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003604 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003605 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003606 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003607 return LY_EVALID;
3608 }
3609
3610 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003611}
3612
Michal Vaskoafac7822020-10-20 14:22:26 +02003613/**
3614 * @brief Parse submodule element.
3615 *
3616 * @param[in,out] ctx Yin parser context for logging and to store current state.
3617 * @param[in] mod_attrs Attributes of submodule element.
3618 * @param[out] submod Parsed submodule structure.
3619 *
3620 * @return LY_ERR values.
3621 */
David Sedlák3b4db242018-10-19 16:11:01 +02003622LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003623yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003624{
David Sedlák81497a32019-08-13 16:56:26 +02003625 LY_ERR ret = LY_SUCCESS;
3626 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003627 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003628 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003629
Michal Vaskoc3781c32020-10-06 14:04:08 +02003630 submod->is_submod = 1;
3631
Michal Vaskob36053d2020-03-26 15:49:30 +01003632 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3633 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01003634 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003635 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3636 LY_STMT_ANYXML, &submod->data, 0,
3637 LY_STMT_AUGMENT, &submod->augments, 0,
3638 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3639 LY_STMT_CHOICE, &submod->data, 0,
3640 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3641 LY_STMT_CONTAINER, &submod->data, 0,
3642 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3643 LY_STMT_DEVIATION, &submod->deviations, 0,
3644 LY_STMT_EXTENSION, &submod->extensions, 0,
3645 LY_STMT_FEATURE, &submod->features, 0,
3646 LY_STMT_GROUPING, &submod->groupings, 0,
3647 LY_STMT_IDENTITY, &submod->identities, 0,
3648 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3649 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3650 LY_STMT_LEAF, &submod->data, 0,
3651 LY_STMT_LEAF_LIST, &submod->data, 0,
3652 LY_STMT_LIST, &submod->data, 0,
3653 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3654 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3655 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3656 LY_STMT_REVISION, &submod->revs, 0,
3657 LY_STMT_RPC, &submod->rpcs, 0,
3658 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3659 LY_STMT_USES, &submod->data, 0,
3660 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3661 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003662
Radek Krejcif13b87b2020-12-01 22:02:17 +01003663 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3664 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003665 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003666
David Sedláked809f12019-09-13 10:15:11 +02003667 /* submodules share the namespace with the module names, so there must not be
3668 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003669 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003670 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003671 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003672 return LY_EVALID;
3673 }
3674
3675 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003676}
3677
3678LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003679yin_parse_submodule(struct lys_yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx,
Radek Krejci0f969882020-08-21 16:56:47 +02003680 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003681{
Radek Krejcid6b76452019-09-03 17:03:03 +02003682 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003683 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003684 struct lysp_submodule *mod_p = NULL;
3685
3686 /* create context */
3687 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003688 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003689 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003690 (*yin_ctx)->unres = main_ctx->unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003691 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003692
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003693 mod_p = calloc(1, sizeof *mod_p);
3694 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3695 mod_p->mod = main_ctx->parsed_mod->mod;
3696 mod_p->parsing = 1;
3697 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3698
David Sedlák1b623122019-08-05 15:27:49 +02003699 /* map the typedefs and groupings list from main context to the submodule's context */
3700 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3701 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3702
David Sedlák8985a142019-07-31 16:43:06 +02003703 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003704 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003705 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003706 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003707 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3708 ret = LY_EINVAL;
3709 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003710 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003711 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003712 ret = LY_EVALID;
3713 goto cleanup;
3714 }
3715
Michal Vaskob36053d2020-03-26 15:49:30 +01003716 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003717 LY_CHECK_GOTO(ret, cleanup);
3718
David Sedlákbf8a2b72019-08-14 16:48:10 +02003719 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003720 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003721 if (in->current[0] == '\n') {
3722 LY_IN_NEW_LINE(in);
3723 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003724 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003725 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003726 if (in->current[0]) {
3727 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003728 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003729 ret = LY_EVALID;
3730 goto cleanup;
3731 }
3732
David Sedlák8985a142019-07-31 16:43:06 +02003733 mod_p->parsing = 0;
3734 *submod = mod_p;
3735
3736cleanup:
3737 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003738 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003739 yin_parser_ctx_free(*yin_ctx);
3740 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003741 }
David Sedlák8985a142019-07-31 16:43:06 +02003742 return ret;
3743}
3744
3745LY_ERR
Michal Vasko405cc9e2020-12-01 12:01:27 +01003746yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
David Sedlák3b4db242018-10-19 16:11:01 +02003747{
David Sedláke4889912018-11-02 09:52:40 +01003748 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003749 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003750 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003751
David Sedlák8985a142019-07-31 16:43:06 +02003752 /* create context */
3753 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003754 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003755 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003756 (*yin_ctx)->unres = unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003757 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003758
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003759 mod_p = calloc(1, sizeof *mod_p);
3760 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3761 mod_p->mod = mod;
3762 mod_p->parsing = 1;
3763 (*yin_ctx)->parsed_mod = mod_p;
3764
David Sedlák8985a142019-07-31 16:43:06 +02003765 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003766 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003767 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003768 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003769 LOGERR(mod->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
David Sedlák3017da42019-02-15 09:48:04 +01003770 ret = LY_EINVAL;
3771 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003772 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003773 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003774 ret = LY_EVALID;
3775 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003776 }
3777
David Sedlák00250342019-06-21 14:19:39 +02003778 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003779 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003780 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003781
David Sedlákbf8a2b72019-08-14 16:48:10 +02003782 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003783 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003784 if (in->current[0] == '\n') {
3785 LY_IN_NEW_LINE(in);
3786 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003787 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003788 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003789 if (in->current[0]) {
3790 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003791 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003792 ret = LY_EVALID;
3793 goto cleanup;
3794 }
3795
David Sedlák3017da42019-02-15 09:48:04 +01003796 mod_p->parsing = 0;
3797 mod->parsed = mod_p;
3798
3799cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003800 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003801 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003802 yin_parser_ctx_free(*yin_ctx);
3803 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003804 }
David Sedlák2e411422018-12-17 02:35:39 +01003805 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003806}