blob: 6dd7d6e284796b49677d67a4f8470705edbd4a02 [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"
Radek Krejci859a15a2021-03-05 20:56:59 +010039#include "tree_edit.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020040#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020041#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020042#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020043
Radek Krejci77114102021-03-10 15:21:57 +010044struct lys_glob_unres;
45
David Sedlák2b214ac2019-06-06 16:11:03 +020046/**
47 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020048 *
David Sedlák2b214ac2019-06-06 16:11:03 +020049 * @param ns Namespace URI to check.
50 *
51 * @return true if ns equals YIN_NS_URI false otherwise.
52 */
53#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
54
Michal Vaskoafac7822020-10-20 14:22:26 +020055enum yin_argument {
56 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
57 YIN_ARG_NAME, /**< argument name */
58 YIN_ARG_TARGET_NODE, /**< argument target-node */
59 YIN_ARG_MODULE, /**< argument module */
60 YIN_ARG_VALUE, /**< argument value */
61 YIN_ARG_TEXT, /**< argument text */
62 YIN_ARG_CONDITION, /**< argument condition */
63 YIN_ARG_URI, /**< argument uri */
64 YIN_ARG_DATE, /**< argument data */
65 YIN_ARG_TAG, /**< argument tag */
66 YIN_ARG_NONE /**< empty (special value) */
67};
68
Michal Vasko22df3f02020-08-24 13:29:22 +020069const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020070 [YIN_ARG_NAME] = "name",
71 [YIN_ARG_TARGET_NODE] = "target-node",
72 [YIN_ARG_MODULE] = "module",
73 [YIN_ARG_VALUE] = "value",
74 [YIN_ARG_TEXT] = "text",
75 [YIN_ARG_CONDITION] = "condition",
76 [YIN_ARG_URI] = "uri",
77 [YIN_ARG_DATE] = "date",
78 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020079 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020080};
81
Michal Vaskoafac7822020-10-20 14:22:26 +020082#define yin_attr2str(STMT) yin_attr_list[STMT]
83
84#define VALID_VALS1 " Only valid value is \"%s\"."
85#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
86#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
87#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
88
89/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
90#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
91 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
92 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
93 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
94
95/* flags to set constraints of subelements */
96#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
97#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
98#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
99#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
100
101#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
102 time to simply check validity of given constraints */
103
104struct yin_subelement {
105 enum ly_stmt type; /**< type of keyword */
106 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
107 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 */
108};
109
110/* Meta information passed to yin_parse_argument function,
111 holds information about where content of argument element will be stored. */
112struct yin_argument_meta {
113 uint16_t *flags; /**< Argument flags */
114 const char **argument; /**< Argument value */
115};
116
117/**
118 * @brief Meta information passed to functions working with tree_schema,
119 * that require additional information about parent node.
120 */
121struct tree_node_meta {
122 struct lysp_node *parent; /**< parent node */
123 struct lysp_node **nodes; /**< linked list of siblings */
124};
125
126/**
127 * @brief Meta information passed to yin_parse_import function.
128 */
129struct import_meta {
130 const char *prefix; /**< module prefix. */
131 struct lysp_import **imports; /**< imports to add to. */
132};
133
134/**
135 * @brief Meta information passed to yin_parse_include function.
136 */
137struct include_meta {
138 const char *name; /**< Module/submodule name. */
139 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
140};
141
142/**
143 * @brief Meta information passed to yin_parse_inout function.
144 */
145struct inout_meta {
146 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100147 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200148};
149
150/**
151 * @brief Meta information passed to yin_parse_minmax function.
152 */
153struct minmax_dev_meta {
154 uint32_t *lim; /**< min/max value to write to. */
155 uint16_t *flags; /**< min/max flags to write to. */
156 struct lysp_ext_instance **exts; /**< extension instances to add to. */
157};
158
159LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
160 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
161
162/**
163 * @brief Match yang keyword from yin data.
164 *
165 * @param[in,out] ctx Yin parser context for logging and to store current state.
166 * @param[in] name Start of keyword name
167 * @param[in] name_len Lenght of keyword name.
168 * @param[in] prefix Start of keyword prefix.
169 * @param[in] prefix_len Lenght of prefix.
170 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
171 *
172 * @return yang_keyword values.
173 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200174enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100175yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200176 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200177{
David Sedlák8f7a1172019-06-20 14:42:18 +0200178 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200179 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200180 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200181 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200182
Michal Vasko69730152020-10-09 16:30:07 +0200183 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200184 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200185 }
186
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200187 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200188 if (ns) {
189 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200190 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200191 }
192 } else {
193 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200194 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200195 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200196
Michal Vasko63f3d842020-07-08 10:10:14 +0200197 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
198 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100199 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200200 name = in->current;
201 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200202
203 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200204 /* 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 +0200205 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200206 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200207 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200208 return kw;
209 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200210 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200211 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200212 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200213 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200214 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200215 }
216}
217
Michal Vaskoafac7822020-10-20 14:22:26 +0200218/**
219 * @brief Match argument name.
220 *
221 * @param[in] name String representing name.
222 * @param[in] len Lenght of the name.
223 *
224 * @return yin_argument values.
225 */
David Sedlákc5b20842019-08-13 10:18:31 +0200226enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200227yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200228{
David Sedlákc5b20842019-08-13 10:18:31 +0200229 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200230 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200231
David Sedlák7ff55a92019-06-17 11:11:41 +0200232 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200233
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200234#define READ_INC(LEN) already_read += LEN
235#define ARG_SET(STMT) arg=STMT
236#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100237
David Sedlák1c8b2702019-02-22 11:03:02 +0100238 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100239 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200240 READ_INC(1);
241 if (ARG_CHECK("ondition", 8)) {
242 ARG_SET(YIN_ARG_CONDITION);
243 }
David Sedlák3b4db242018-10-19 16:11:01 +0200244 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200245
David Sedlák94de2aa2019-02-15 12:42:11 +0100246 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200247 READ_INC(1);
248 if (ARG_CHECK("ate", 3)) {
249 ARG_SET(YIN_ARG_DATE);
250 }
David Sedlák3b4db242018-10-19 16:11:01 +0200251 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200252
David Sedlák94de2aa2019-02-15 12:42:11 +0100253 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200254 READ_INC(1);
255 if (ARG_CHECK("odule", 5)) {
256 ARG_SET(YIN_ARG_MODULE);
257 }
David Sedlák872c7b42018-10-26 13:15:20 +0200258 break;
259
David Sedlák94de2aa2019-02-15 12:42:11 +0100260 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200261 READ_INC(1);
262 if (ARG_CHECK("ame", 3)) {
263 ARG_SET(YIN_ARG_NAME);
264 }
David Sedlák872c7b42018-10-26 13:15:20 +0200265 break;
266
David Sedlák94de2aa2019-02-15 12:42:11 +0100267 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200268 READ_INC(1);
269 if (ARG_CHECK("a", 1)) {
270 if (ARG_CHECK("g", 1)) {
271 ARG_SET(YIN_ARG_TAG);
272 } else if (ARG_CHECK("rget-node", 9)) {
273 ARG_SET(YIN_ARG_TARGET_NODE);
274 }
275 } else if (ARG_CHECK("ext", 3)) {
276 ARG_SET(YIN_ARG_TEXT);
277 }
David Sedlák3b4db242018-10-19 16:11:01 +0200278 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200279
David Sedlák94de2aa2019-02-15 12:42:11 +0100280 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200281 READ_INC(1);
282 if (ARG_CHECK("ri", 2)) {
283 ARG_SET(YIN_ARG_URI);
284 }
David Sedlák3b4db242018-10-19 16:11:01 +0200285 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200286
David Sedlák94de2aa2019-02-15 12:42:11 +0100287 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200288 READ_INC(1);
289 if (ARG_CHECK("alue", 4)) {
290 ARG_SET(YIN_ARG_VALUE);
291 }
David Sedlák3b4db242018-10-19 16:11:01 +0200292 break;
293 }
294
David Sedlákc10e7902018-12-17 02:17:59 +0100295 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200296 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200297 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200298 }
299
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200300#undef ARG_CHECK
301#undef ARG_SET
302#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100303
David Sedlák872c7b42018-10-26 13:15:20 +0200304 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200305}
306
Radek Krejcid6b76452019-09-03 17:03:03 +0200307#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
308 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
309 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
310 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200311
Radek Krejcid6b76452019-09-03 17:03:03 +0200312#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 +0200313
David Sedlák26ea1432019-08-14 13:42:23 +0200314/**
315 * @brief Free subelems information allocated on heap.
316 *
317 * @param[in] count Size of subelems array.
318 * @param[in] subelems Subelems array to free.
319 */
David Sedlák81497a32019-08-13 16:56:26 +0200320static void
321subelems_deallocator(size_t count, struct yin_subelement *subelems)
322{
Michal Vaskod989ba02020-08-24 10:59:24 +0200323 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200324 if (HAS_META(subelems[i].type)) {
325 free(subelems[i].dest);
326 }
327 }
328
329 free(subelems);
330}
331
David Sedlák26ea1432019-08-14 13:42:23 +0200332/**
333 * @brief Allocate subelems information on heap.
334 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200335 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200336 * @param[in] count Number of subelements.
337 * @param[in] parent Parent node if any.
338 * @param[out] result Allocated subelems array.
339 *
340 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
341 */
David Sedlák81497a32019-08-13 16:56:26 +0200342static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100343subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200344 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200345{
346 va_list ap;
347
348 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200349 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200350
351 va_start(ap, result);
352 for (size_t i = 0; i < count; ++i) {
353 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200354 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200355 /* DEST */
356 if (IS_NODE_ELEM((*result)[i].type)) {
357 struct tree_node_meta *node_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200358
David Sedlák81497a32019-08-13 16:56:26 +0200359 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200360 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200361 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200362 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200363 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200364 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200365 struct import_meta *imp_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200366
David Sedlák81497a32019-08-13 16:56:26 +0200367 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200368 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200369 imp_meta->prefix = va_arg(ap, const char *);
370 imp_meta->imports = va_arg(ap, struct lysp_import **);
371 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200372 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200373 struct include_meta *inc_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200374
David Sedlák81497a32019-08-13 16:56:26 +0200375 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200376 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200377 inc_meta->name = va_arg(ap, const char *);
378 inc_meta->includes = va_arg(ap, struct lysp_include **);
379 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200380 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200381 struct inout_meta *inout_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200382
David Sedlák81497a32019-08-13 16:56:26 +0200383 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200384 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200385 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100386 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200387 (*result)[i].dest = inout_meta;
388 } else {
389 (*result)[i].dest = va_arg(ap, void *);
390 }
391 /* FLAGS */
392 (*result)[i].flags = va_arg(ap, int);
393 }
394 va_end(ap);
395
396 return LY_SUCCESS;
397
David Sedlákbf8a2b72019-08-14 16:48:10 +0200398mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200399 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100400 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200401 return LY_EMEM;
402}
403
Michal Vaskoafac7822020-10-20 14:22:26 +0200404/**
405 * @brief Check that val is valid UTF8 character sequence of val_type.
406 * Doesn't check empty string, only character validity.
407 *
408 * @param[in] ctx Yin parser context for logging.
409 * @param[in] val_type Type of the input string to select method of checking character validity.
410 *
411 * @return LY_ERR values.
412 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200413LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100414yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200415{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200416 uint8_t prefix = 0;
417 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100418 size_t utf8_char_len, already_read = 0;
419 const char *val;
420
421 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
422
423 val = ctx->xmlctx->value;
424 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200425 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200426 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200427
428 switch (val_type) {
429 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200430 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 +0200431 break;
432 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200433 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 +0200434 break;
435 case Y_STR_ARG:
436 case Y_MAYBE_STR_ARG:
437 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
438 break;
439 }
Radek Iša2eac74c2021-03-15 15:53:08 +0100440
441 already_read += utf8_char_len;
442 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200443 }
444
Radek Iša42cc0b72021-03-15 16:51:31 +0100445 if ((already_read == 0) &&
446 ((val_type == Y_PREF_IDENTIF_ARG) || (val_type == Y_IDENTIF_ARG))) {
447 /* Empty identifier or prefix*/
448 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Empty identifier is not allowed.");
449 return LY_EVALID;
450 }
451
David Sedlák4a650532019-07-10 11:55:18 +0200452 return LY_SUCCESS;
453}
454
David Sedlákb4e44562019-07-04 15:42:12 +0200455/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100456 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200457 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200458 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200459 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
460 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200461 * @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 +0200462 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200463 * @param[in] current_element Identification of current element, used for logging.
464 *
465 * @return LY_ERR values.
466 */
467static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100468yin_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 +0200469 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200470{
David Sedlákc5b20842019-08-13 10:18:31 +0200471 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200472 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200473
David Sedlák1bccdfa2019-06-17 15:55:27 +0200474 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100475 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200476 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100477 if (!ctx->xmlctx->prefix) {
478 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200479 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100480 /* skip it */
481 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200482 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200483 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200484 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200485 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100486
487 /* go to value */
488 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
489 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200490 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 +0200491 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200492 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100493 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200494 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200495 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200496 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100497 } else {
498 /* skip it */
499 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200500 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100501
502 /* next attribute */
503 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200504 }
505
David Sedlák292763b2019-07-09 11:10:53 +0200506 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200507 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100508 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200509 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200510 return LY_EVALID;
511 }
512
513 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200514}
515
David Sedlákd6e56892019-07-01 15:40:24 +0200516/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200517 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200518 *
519 * @param[in] type Type of wanted record.
520 * @param[in] array_size Size of array.
521 * @param[in] array Searched array.
522 *
523 * @return Pointer to desired record on success, NULL if element is not in the array.
524 */
David Sedlákb4e44562019-07-04 15:42:12 +0200525static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200526get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200527{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200528 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200529 if (array[u].type == type) {
530 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200531 }
532 }
David Sedlákd6e56892019-07-01 15:40:24 +0200533 return NULL;
534}
535
David Sedlákbba38e52019-07-09 15:20:01 +0200536/**
537 * @brief Helper function to check mandatory constraint of subelement.
538 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200539 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200540 * @param[in] subelem_info Array of information about subelements.
541 * @param[in] subelem_info_size Size of subelem_info array.
542 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
543 *
544 * @return LY_ERR values.
545 */
546static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100547yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200548 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200549{
David Sedlákb0faad82019-07-04 14:28:59 +0200550 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200551 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200552 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200553 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200554 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200555 return LY_EVALID;
556 }
557 }
558
559 return LY_SUCCESS;
560}
561
David Sedlákbba38e52019-07-09 15:20:01 +0200562/**
563 * @brief Helper function to check "first" constraint of subelement.
564 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200565 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200566 * @param[in] subelem_info Array of information about subelements.
567 * @param[in] subelem_info_size Size of subelem_info array.
568 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200569 * @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 +0200570 *
571 * @return LY_ERR values.
572 */
573static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100574yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200575 signed char subelem_info_size, enum ly_stmt current_element,
576 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200577{
David Sedlákb0faad82019-07-04 14:28:59 +0200578 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200579 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200580 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200581 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200582 return LY_EVALID;
583 }
584 }
585
586 return LY_SUCCESS;
587}
588
David Sedlákbba38e52019-07-09 15:20:01 +0200589/**
David Sedlákb4e44562019-07-04 15:42:12 +0200590 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
591 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200592 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200593 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200594 * @param[in] kw Type of current element.
595 * @param[out] value Where value of attribute should be stored.
596 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200597 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200598 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200599 * @return LY_ERR values.
600 */
David Sedlákb4e44562019-07-04 15:42:12 +0200601static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100602yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200603 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200604{
Michal Vaskob36053d2020-03-26 15:49:30 +0100605 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
606 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100607 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200608 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
609 };
David Sedlákb4e44562019-07-04 15:42:12 +0200610
Radek Krejcif13b87b2020-12-01 22:02:17 +0100611 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200612}
613
614/**
David Sedlák6542aed2019-08-14 10:47:43 +0200615 * @brief Parse path element.
616 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200617 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200618 * @param[in] kw Type of current element.
619 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200620 * @return LY_ERR values.
621 */
622static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100623yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200624{
Michal Vasko004d3152020-06-11 19:59:22 +0200625 LY_ERR ret;
626 const char *str_path;
627
628 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +0200629 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +0200630 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200631 lydict_remove(ctx->xmlctx->ctx, str_path);
632 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200633 type->flags |= LYS_SET_PATH;
634
635 return LY_SUCCESS;
636}
637
638/**
David Sedlákd3983112019-07-12 11:20:56 +0200639 * @brief Parse pattern element.
640 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200641 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200642 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200643 * @return LY_ERR values.
644 */
645static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100646yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200647{
648 const char *real_value = NULL;
649 char *saved_value = NULL;
650 struct lysp_restr *restr;
651
Michal Vaskob36053d2020-03-26 15:49:30 +0100652 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
653 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
654 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 +0200655 size_t len = strlen(real_value);
656
657 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100658 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200659 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100660 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100661 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200662 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200663 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100664 restr->arg.mod = PARSER_CUR_PMOD(ctx);
David Sedlákd3983112019-07-12 11:20:56 +0200665 type->flags |= LYS_SET_PATTERN;
666
Radek Krejcif13b87b2020-12-01 22:02:17 +0100667 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200668 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
669 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
670 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
671 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
672 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
673 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
674 };
Michal Vasko69730152020-10-09 16:30:07 +0200675
Radek Krejcif13b87b2020-12-01 22:02:17 +0100676 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200677}
678
David Sedlákc5b20842019-08-13 10:18:31 +0200679/**
680 * @brief Parse fraction-digits element.
681 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200682 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200683 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200684 * @return LY_ERR values.
685 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200686static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100687yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200688{
689 const char *temp_val = NULL;
690 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200691 unsigned long long int num;
David Sedlákf75d55e2019-07-12 16:52:50 +0200692
Michal Vaskob36053d2020-03-26 15:49:30 +0100693 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
694 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 +0200695
Michal Vasko69730152020-10-09 16:30:07 +0200696 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200697 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100698 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200699 return LY_EVALID;
700 }
701
702 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200703 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200704 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200705 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100706 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200707 return LY_EVALID;
708 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100709 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200710 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100711 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200712 return LY_EVALID;
713 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100714 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200715 type->fraction_digits = num;
716 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100717 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200718 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
719 };
Michal Vasko69730152020-10-09 16:30:07 +0200720
Radek Krejcif13b87b2020-12-01 22:02:17 +0100721 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200722}
723
David Sedlák07869a52019-07-12 14:28:19 +0200724/**
David Sedlák43801c92019-08-05 15:58:54 +0200725 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200726 *
727 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200728 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200729 * @return LY_ERR values.
730 */
David Sedlákca36c422019-07-12 12:47:55 +0200731static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100732yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200733{
David Sedlák07869a52019-07-12 14:28:19 +0200734 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200735
Michal Vaskob36053d2020-03-26 15:49:30 +0100736 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200737 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100738 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
739 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 +0200740 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100741 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200742 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200743
Radek Krejcif13b87b2020-12-01 22:02:17 +0100744 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200745 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
746 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
747 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
748 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
749 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
750 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
751 };
Michal Vasko69730152020-10-09 16:30:07 +0200752
Radek Krejcif13b87b2020-12-01 22:02:17 +0100753 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200754}
755
756/**
757 * @brief Parse bit element.
758 *
759 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200760 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200761 * @return LY_ERR values.
762 */
763static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100764yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200765{
766 struct lysp_type_enum *en;
767
Michal Vaskob36053d2020-03-26 15:49:30 +0100768 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200769 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100770 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
771 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
Radek Iša8b640882021-03-12 17:59:34 +0100772 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->bits, name, "bit", en->name);
David Sedlák43801c92019-08-05 15:58:54 +0200773
Radek Krejcif13b87b2020-12-01 22:02:17 +0100774 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200775 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
776 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
777 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
778 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
779 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
780 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
781 };
Michal Vasko69730152020-10-09 16:30:07 +0200782
Radek Krejcif13b87b2020-12-01 22:02:17 +0100783 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200784}
785
David Sedlákd3983112019-07-12 11:20:56 +0200786/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200787 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
788 * more instances, such as base or if-feature.
789 *
790 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200791 * @param[in] kw Type of current element.
792 * @param[out] values Parsed values to add to.
793 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200794 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200795 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200796 * @return LY_ERR values.
797 */
798static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100799yin_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 +0200800 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200801{
802 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200803
Michal Vaskob36053d2020-03-26 15:49:30 +0100804 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200805 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100806 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200807 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
808 };
David Sedlák968ac342019-07-11 15:17:59 +0200809
Michal Vaskob36053d2020-03-26 15:49:30 +0100810 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
811 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200812
Radek Krejcif13b87b2020-12-01 22:02:17 +0100813 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200814}
815
816/**
David Sedlák6542aed2019-08-14 10:47:43 +0200817 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
818 *
819 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200820 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200821 * @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 +0200822 * @param[in] arg_type Expected type of attribute.
823 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200824 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200825 * @return LY_ERR values.
826 */
827static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100828yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200829 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200830{
831 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100832 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200833 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200834 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100835 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200836 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200837 }
838
839 return LY_SUCCESS;
840}
841
842/**
843 * @brief Parse base element.
844 *
845 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200846 * @param[in] parent Identification of parent element.
847 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200848 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200849 * @return LY_ERR values.
850 */
851static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100852yin_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 +0200853{
854 struct lysp_type *type = NULL;
855
Radek Krejcid6b76452019-09-03 17:03:03 +0200856 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200857 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100858 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200859 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200860 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200861 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100862 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200863 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200864 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100865 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200866 return LY_EINT;
867 }
868
869 return LY_SUCCESS;
870}
871
872/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200873 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200874 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200875 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100876 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200877 * @return LY_ERR values.
878 */
879static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100880yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200881{
882 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100883 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200884 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
885 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200886
887 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100888 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
889 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 +0200890 if (strcmp(temp_val, "true") == 0) {
891 type->require_instance = 1;
892 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200893 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200894 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100895 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200896 return LY_EVALID;
897 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100898 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200899
Radek Krejcif13b87b2020-12-01 22:02:17 +0100900 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200901}
902
903/**
David Sedlákce77bf52019-07-11 16:59:31 +0200904 * @brief Parse modifier element.
905 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200906 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200907 * @param[in,out] pat Value to write to.
908 * @param[in,out] exts Extension instances to add to.
909 *
910 * @return LY_ERR values.
911 */
912static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100913yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200914{
David Sedlákd3983112019-07-12 11:20:56 +0200915 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200916 const char *temp_val;
917 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100918 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200919 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
920 };
David Sedlákce77bf52019-07-11 16:59:31 +0200921
Michal Vaskob36053d2020-03-26 15:49:30 +0100922 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
923 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 +0200924 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200925 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200926 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100927 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200928 return LY_EVALID;
929 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100930 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200931
932 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200933 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100934 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200935 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100936 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200937
938 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100939 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200940 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200941
Radek Krejcif13b87b2020-12-01 22:02:17 +0100942 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200943}
944
945/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200946 * @brief Parse a restriction element (length, range or one instance of must).
947 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200948 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200949 * @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 +0200950 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200951 */
952static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100953yin_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 +0200954{
Radek Krejcid6b76452019-09-03 17:03:03 +0200955 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100956 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200957 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
958 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
959 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
960 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
961 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
962 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200963 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200964 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200965
Michal Vaskob36053d2020-03-26 15:49:30 +0100966 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200967 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100968 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Michal Vaskob36053d2020-03-26 15:49:30 +0100969
Radek Krejcif13b87b2020-12-01 22:02:17 +0100970 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200971}
972
973/**
David Sedlák6542aed2019-08-14 10:47:43 +0200974 * @brief Parse range element.
975 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200976 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200977 * @param[out] type Type structure to store parsed value and flags.
978 *
979 * @return LY_ERR values.
980 */
981static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100982yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200983{
984 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100985 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
986 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200987 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200988
989 return LY_SUCCESS;
990}
991
992/**
993 * @brief Parse length element.
994 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200995 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200996 * @param[out] type Type structure to store parsed value and flags.
997 *
998 * @return LY_ERR values.
999 */
1000static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001001yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +02001002{
1003 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001004 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1005 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +02001006 type->flags |= LYS_SET_LENGTH;
1007
1008 return LY_SUCCESS;
1009}
1010
1011/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001012 * @brief Parse must element.
1013 *
1014 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001015 * @param[in,out] restrs Restrictions to add to.
1016 *
1017 * @return LY_ERR values.
1018 */
1019static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001020yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001021{
1022 struct lysp_restr *restr;
1023
Michal Vaskob36053d2020-03-26 15:49:30 +01001024 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1025 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001026}
1027
1028/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001029 * @brief Parse a node id into an array.
1030 *
1031 * @param[in,out] ctx YIN parser context for logging and to store current state.
1032 * @param[in] kw Type of current element.
1033 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1034 * @param[in,out] exts Extension instances to add to.
1035 *
1036 * @return LY_ERR values.
1037 */
1038static LY_ERR
1039yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1040 struct lysp_ext_instance **exts)
1041{
1042 struct lysp_qname *qname, **qnames;
1043
1044 switch (kw) {
1045 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001046 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1047 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001048 } else {
1049 qnames = (struct lysp_qname **)subinfo->dest;
1050 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001051 }
Michal Vasko8a67eff2021-12-07 14:04:47 +01001052 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001053 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
Radek Išabe8a6532021-03-29 08:54:22 +02001054 case LY_STMT_UNIQUE:
1055 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1056 qnames = (struct lysp_qname **)subinfo->dest;
1057 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001058 qname->mod = PARSER_CUR_PMOD(ctx);
Radek Išabe8a6532021-03-29 08:54:22 +02001059 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001060 case LY_STMT_IF_FEATURE:
1061 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1062 qnames = (struct lysp_qname **)subinfo->dest;
1063 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001064 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001065 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001066 default:
1067 break;
1068 }
1069
1070 LOGINT(ctx->xmlctx->ctx);
1071 return LY_EINT;
1072}
1073
1074/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001075 * @brief Parse position or value element.
1076 *
1077 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001078 * @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 +02001079 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001080 *
1081 * @return LY_ERR values.
1082 */
1083static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001084yin_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 +02001085{
Radek Krejcid6b76452019-09-03 17:03:03 +02001086 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001087 const char *temp_val = NULL;
1088 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001089 long long int num = 0;
1090 unsigned long long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001091
1092 /* set value flag */
1093 enm->flags |= LYS_SET_VALUE;
1094
1095 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001096 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1097 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001098 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001099 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-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ák5545f5d2019-07-11 11:55:16 +02001101 goto error;
1102 }
1103
1104 /* convert value */
1105 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001106 if (kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001107 num = strtoll(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001108 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001109 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 +02001110 goto error;
1111 }
1112 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001113 unum = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001114 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001115 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 +02001116 goto error;
1117 }
1118 }
1119 /* check if whole argument value was converted */
1120 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001121 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 +02001122 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001123 }
1124 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001125 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 +02001126 goto error;
1127 }
1128 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001129 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001130 enm->value = num;
1131 } else {
1132 enm->value = unum;
1133 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001134 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001135
1136 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001137 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001138 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1139 };
Michal Vasko69730152020-10-09 16:30:07 +02001140
Radek Krejcif13b87b2020-12-01 22:02:17 +01001141 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001142
David Sedlákbf8a2b72019-08-14 16:48:10 +02001143error:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001144 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskob36053d2020-03-26 15:49:30 +01001145 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001146}
1147
David Sedlák05404f62019-07-24 14:11:53 +02001148/**
1149 * @brief Parse belongs-to element.
1150 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001151 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001152 * @param[out] submod Structure of submodule that is being parsed.
1153 * @param[in,out] exts Extension instances to add to.
1154 *
1155 * @return LY_ERR values
1156 */
1157static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001158yin_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 +02001159{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001160 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001161 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001162 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1163 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1164 };
David Sedlák05404f62019-07-24 14:11:53 +02001165
Michal Vaskob36053d2020-03-26 15:49:30 +01001166 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001167 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001168 if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001169 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
Michal Vasko8a67eff2021-12-07 14:04:47 +01001170 belongsto, PARSER_CUR_PMOD(ctx)->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001171 lydict_remove(ctx->xmlctx->ctx, belongsto);
1172 return LY_EVALID;
1173 }
1174 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001175
Radek Krejcif13b87b2020-12-01 22:02:17 +01001176 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001177}
1178
David Sedlák5545f5d2019-07-11 11:55:16 +02001179/**
David Sedlákc1771b12019-07-10 15:55:46 +02001180 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001181 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001182 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001183 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001184 * @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 +02001185 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001186 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001187 *
1188 * @return LY_ERR values.
1189 */
1190static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001191yin_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 +02001192{
Radek Krejcid6b76452019-09-03 17:03:03 +02001193 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 +02001194
Radek Krejcif13b87b2020-12-01 22:02:17 +01001195 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001196 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1197 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1198 };
Michal Vasko69730152020-10-09 16:30:07 +02001199
David Sedlákdf2a9732019-08-07 13:23:16 +02001200 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001201 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1202 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 +02001203
David Sedlákdf2a9732019-08-07 13:23:16 +02001204 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001205 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001206}
1207
1208/**
David Sedlákc1771b12019-07-10 15:55:46 +02001209 * @brief Parse error-message element.
1210 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001211 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001212 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001213 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001214 *
1215 * @return LY_ERR values.
1216 */
1217static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001218yin_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 +02001219{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001220 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001221 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1222 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1223 };
David Sedlákc1771b12019-07-10 15:55:46 +02001224
David Sedlákdf2a9732019-08-07 13:23:16 +02001225 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001226 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1227 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 +02001228
Radek Krejcif13b87b2020-12-01 22:02:17 +01001229 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001230}
1231
1232/**
David Sedlák6542aed2019-08-14 10:47:43 +02001233 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001234 *
1235 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001236 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001237 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001238 *
1239 * @return LY_ERR values.
1240 */
1241static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001242yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001243{
David Sedlák6542aed2019-08-14 10:47:43 +02001244 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001245
Radek Krejcid6b76452019-09-03 17:03:03 +02001246 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001247 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001248 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001249 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001250 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001251 type = (struct lysp_type *)subinfo->dest;
1252 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001253
David Sedlák6542aed2019-08-14 10:47:43 +02001254 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001255 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001256 struct lysp_type *nested_type = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +02001257
Michal Vaskob36053d2020-03-26 15:49:30 +01001258 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001259 type->flags |= LYS_SET_TYPE;
1260 type = nested_type;
1261 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001262
Michal Vasko8a67eff2021-12-07 14:04:47 +01001263 type->pmod = PARSER_CUR_PMOD(ctx);
Michal Vasko5bbcc242021-02-23 09:29:13 +01001264
Radek Krejcif13b87b2020-12-01 22:02:17 +01001265 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001266 {LY_STMT_BASE, type, 0},
1267 {LY_STMT_BIT, type, 0},
1268 {LY_STMT_ENUM, type, 0},
1269 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1270 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1271 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1272 {LY_STMT_PATTERN, type, 0},
1273 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1274 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
Michal Vasko608b0c02021-09-23 08:26:53 +02001275 {LY_STMT_TYPE, type, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001276 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1277 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001278
1279 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1280 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 +01001281 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001282}
1283
David Sedlák1af868e2019-07-17 17:03:14 +02001284/**
1285 * @brief Parse max-elements element.
1286 *
1287 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001288 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001289 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001290 * @param[in,out] exts Extension instances to add to.
1291 *
1292 * @return LY_ERR values.
1293 */
1294static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001295yin_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 +02001296{
1297 const char *temp_val = NULL;
1298 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001299 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001300 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001301 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1302 };
David Sedlák374d2b32019-07-17 15:06:55 +02001303
David Sedlák1af868e2019-07-17 17:03:14 +02001304 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001305 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1306 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 +02001307 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 +02001308 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001309 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001310 return LY_EVALID;
1311 }
1312
1313 if (strcmp(temp_val, "unbounded")) {
1314 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001315 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001316 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001317 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001318 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001319 return LY_EVALID;
1320 }
1321 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001322 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001323 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001324 return LY_EVALID;
1325 }
1326 *max = num;
1327 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001328 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001329 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001330}
David Sedlák374d2b32019-07-17 15:06:55 +02001331
1332/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001333 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001334 *
1335 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001336 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001337 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001338 * @param[in,out] exts Extension instances to add to.
1339 *
1340 * @return LY_ERR values.
1341 */
1342static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001343yin_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 +02001344{
1345 const char *temp_val = NULL;
1346 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001347 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001348 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001349 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1350 };
David Sedlák09e18c92019-07-18 11:17:11 +02001351
1352 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001353 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1354 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 +02001355
Michal Vasko69730152020-10-09 16:30:07 +02001356 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001357 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001358 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001359 return LY_EVALID;
1360 }
1361
1362 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001363 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001364 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001365 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001366 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001367 return LY_EVALID;
1368 }
Michal Vasko69730152020-10-09 16:30:07 +02001369 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001370 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001371 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001372 return LY_EVALID;
1373 }
1374 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001375 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001376 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001377}
1378
David Sedláka2dad212019-07-18 12:45:19 +02001379/**
1380 * @brief Parse min-elements or max-elements element.
1381 *
1382 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001383 * @param[in] parent Identification of parent element.
1384 * @param[in] current Identification of current element.
1385 * @param[in] dest Where the parsed value and flags should be stored.
1386 *
1387 * @return LY_ERR values.
1388 */
David Sedlák09e18c92019-07-18 11:17:11 +02001389static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001390yin_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 +02001391{
Radek Krejcid6b76452019-09-03 17:03:03 +02001392 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1393 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 +02001394 uint32_t *lim;
1395 uint16_t *flags;
1396 struct lysp_ext_instance **exts;
1397
Radek Krejcid6b76452019-09-03 17:03:03 +02001398 if (parent == LY_STMT_LEAF_LIST) {
1399 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 +02001400 flags = &((struct lysp_node_leaflist *)dest)->flags;
1401 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001402 } else if (parent == LY_STMT_REFINE) {
1403 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001404 flags = &((struct lysp_refine *)dest)->flags;
1405 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001406 } else if (parent == LY_STMT_LIST) {
1407 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 +02001408 flags = &((struct lysp_node_list *)dest)->flags;
1409 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001410 } else {
1411 lim = ((struct minmax_dev_meta *)dest)->lim;
1412 flags = ((struct minmax_dev_meta *)dest)->flags;
1413 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001414 }
1415
Radek Krejcid6b76452019-09-03 17:03:03 +02001416 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001417 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001418 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001419 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001420 }
1421
1422 return LY_SUCCESS;
1423}
1424
1425/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001426 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001427 *
1428 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001429 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001430 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001431 *
1432 * @return LY_ERR values.
1433 */
1434static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001435yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001436{
1437 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001438 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001439 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1440 };
David Sedláka2dad212019-07-18 12:45:19 +02001441
Michal Vaskob36053d2020-03-26 15:49:30 +01001442 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1443 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 +02001444 if (strcmp(temp_val, "system") == 0) {
1445 *flags |= LYS_ORDBY_SYSTEM;
1446 } else if (strcmp(temp_val, "user") == 0) {
1447 *flags |= LYS_ORDBY_USER;
1448 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001449 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001450 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001451 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001452 return LY_EVALID;
1453 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001454 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001455
Radek Krejcif13b87b2020-12-01 22:02:17 +01001456 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001457}
1458
1459/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001460 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001461 *
1462 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001463 * @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 +02001464 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001465 *
1466 * @return LY_ERR values.
1467 */
1468static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001469yin_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 +02001470{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001471 struct lysp_node_anydata *any;
1472
David Sedlák8d552d62019-08-06 15:29:05 +02001473 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001474 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001475 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001476 any->parent = node_meta->parent;
1477
David Sedlákbf8a2b72019-08-14 16:48:10 +02001478 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001479 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1480 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 +02001481
Radek Krejcif13b87b2020-12-01 22:02:17 +01001482 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001483 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1484 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1485 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1486 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1487 {LY_STMT_MUST, &any->musts, 0},
1488 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1489 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1490 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1491 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1492 };
Michal Vasko69730152020-10-09 16:30:07 +02001493
Radek Krejcif13b87b2020-12-01 22:02:17 +01001494 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001495}
1496
1497/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001498 * @brief parse leaf element.
1499 *
1500 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001501 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001502 *
1503 * @return LY_ERR values.
1504 */
1505static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001506yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001507{
David Sedlák203ca3a2019-07-18 15:26:25 +02001508 struct lysp_node_leaf *leaf;
1509
David Sedlák8d552d62019-08-06 15:29:05 +02001510 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001511 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001512 leaf->nodetype = LYS_LEAF;
1513 leaf->parent = node_meta->parent;
1514
David Sedlák203ca3a2019-07-18 15:26:25 +02001515 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001516 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1517 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 +02001518
1519 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001520 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001521 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1522 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1523 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1524 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1525 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1526 {LY_STMT_MUST, &leaf->musts, 0},
1527 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1528 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1529 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1530 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1531 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1532 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1533 };
Michal Vasko69730152020-10-09 16:30:07 +02001534
Radek Krejcif13b87b2020-12-01 22:02:17 +01001535 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001536}
1537
1538/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001539 * @brief Parse leaf-list element.
1540 *
1541 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001542 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001543 *
1544 * @return LY_ERR values.
1545 */
1546static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001547yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001548{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001549 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001550
Michal Vaskob36053d2020-03-26 15:49:30 +01001551 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001552
David Sedlákc3da3ef2019-07-19 12:56:08 +02001553 llist->nodetype = LYS_LEAFLIST;
1554 llist->parent = node_meta->parent;
1555
David Sedlákc3da3ef2019-07-19 12:56:08 +02001556 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001557 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1558 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 +02001559
1560 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001561 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001562 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1563 {LY_STMT_DEFAULT, &llist->dflts, 0},
1564 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1565 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1566 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1567 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1568 {LY_STMT_MUST, &llist->musts, 0},
1569 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1570 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1571 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1572 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1573 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1574 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1575 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1576 };
Michal Vasko69730152020-10-09 16:30:07 +02001577
Radek Krejcif13b87b2020-12-01 22:02:17 +01001578 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 +02001579
David Sedlákbf8a2b72019-08-14 16:48:10 +02001580 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001581 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001582 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001583 return LY_EVALID;
1584 }
Michal Vasko69730152020-10-09 16:30:07 +02001585 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001586 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001587 return LY_EVALID;
1588 }
1589
1590 return LY_SUCCESS;
1591}
1592
1593/**
David Sedlák04e17b22019-07-19 15:29:48 +02001594 * @brief Parse typedef element.
1595 *
1596 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001597 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001598 *
1599 * @return LY_ERR values.
1600 */
1601static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001602yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001603{
1604 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001605 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001606
Michal Vaskob36053d2020-03-26 15:49:30 +01001607 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001608
1609 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001610 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1611 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 +02001612
1613 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001614 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001615 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1616 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1617 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1618 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1619 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1620 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1621 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1622 };
Michal Vasko69730152020-10-09 16:30:07 +02001623
Radek Krejcif13b87b2020-12-01 22:02:17 +01001624 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 +02001625
1626 /* store data for collision check */
aPiecek75b83a02021-06-29 10:34:38 +02001627 if (typedef_meta->parent) {
aPiecek8d4e75d2021-06-24 14:47:06 +02001628 assert(ctx->main_ctx);
1629 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001630 }
1631
1632 return LY_SUCCESS;
1633}
1634
1635/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001636 * @brief Parse refine element.
1637 *
1638 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001639 * @param[in,out] refines Refines to add to.
1640 *
1641 * @return LY_ERR values.
1642 */
1643static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001644yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001645{
1646 struct lysp_refine *rf;
1647
1648 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001649 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001650
1651 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001652 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1653 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1654 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001655
1656 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001657 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001658 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001659 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001660 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001661 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001662 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1663 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1664 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1665 {LY_STMT_MUST, &rf->musts, 0},
1666 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1667 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1668 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1669 };
Michal Vasko69730152020-10-09 16:30:07 +02001670
Radek Krejcif13b87b2020-12-01 22:02:17 +01001671 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001672}
1673
1674/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001675 * @brief Parse uses element.
1676 *
1677 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001678 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001679 *
1680 * @return LY_ERR values.
1681 */
1682static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001683yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001684{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001685 struct lysp_node_uses *uses;
1686
David Sedlák8d552d62019-08-06 15:29:05 +02001687 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001688 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001689 uses->nodetype = LYS_USES;
1690 uses->parent = node_meta->parent;
1691
David Sedlák0d6de5a2019-07-22 13:25:44 +02001692 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001693 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1694 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 +02001695
1696 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001697 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001698 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001699 {LY_STMT_AUGMENT, &augments, 0},
1700 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1701 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1702 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1703 {LY_STMT_REFINE, &uses->refines, 0},
1704 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1705 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1706 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1707 };
Michal Vasko69730152020-10-09 16:30:07 +02001708
Radek Krejcif13b87b2020-12-01 22:02:17 +01001709 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 +02001710
1711 return LY_SUCCESS;
1712}
1713
1714/**
David Sedlákaa854b02019-07-22 14:17:10 +02001715 * @brief Parse revision element.
1716 *
1717 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001718 * @param[in,out] revs Parsed revisions to add to.
1719 *
1720 * @return LY_ERR values.
1721 */
1722static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001723yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001724{
1725 struct lysp_revision *rev;
1726 const char *temp_date = NULL;
1727
1728 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001729 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001730
1731 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001732 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1733 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 +02001734 /* check value */
1735 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001736 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001737 return LY_EVALID;
1738 }
Radek Krejci36642162021-01-12 16:49:22 +01001739 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001740 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001741
1742 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001743 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001744 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1745 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1746 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1747 };
Michal Vasko69730152020-10-09 16:30:07 +02001748
Radek Krejcif13b87b2020-12-01 22:02:17 +01001749 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001750}
1751
David Sedlák5e13dea2019-07-22 16:06:45 +02001752/**
1753 * @brief Parse include element.
1754 *
1755 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001756 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1757 *
1758 * @return LY_ERR values.
1759 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001760static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001761yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001762{
1763 struct lysp_include *inc;
1764
1765 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001766 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001767
1768 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001769 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1770 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 +02001771
1772 /* submodules share the namespace with the module names, so there must not be
1773 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001774 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001775 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001776 return LY_EVALID;
1777 }
1778
1779 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001780 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001781 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1782 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1783 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1784 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1785 };
Michal Vasko69730152020-10-09 16:30:07 +02001786
Radek Krejcif13b87b2020-12-01 22:02:17 +01001787 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001788}
1789
David Sedlákaa854b02019-07-22 14:17:10 +02001790/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001791 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001792 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001793 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001794 * @param[in,out] rev Array to store the parsed value in.
1795 * @param[in,out] exts Extension instances to add to.
1796 *
1797 * @return LY_ERR values.
1798 */
1799static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001800yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001801{
1802 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001803 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001804 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1805 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001806
Michal Vaskob36053d2020-03-26 15:49:30 +01001807 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1808 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 +02001809 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 +01001810 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001811
1812 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001813 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001814
Radek Krejcif13b87b2020-12-01 22:02:17 +01001815 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001816}
1817
1818/**
1819 * @brief Parse config element.
1820 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001821 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001822 * @param[in,out] flags Flags to add to.
1823 * @param[in,out] exts Extension instances to add to.
1824 *
1825 * @return LY_ERR values.
1826 */
1827static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001828yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001829{
1830 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001831 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001832 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1833 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001834
Michal Vaskob36053d2020-03-26 15:49:30 +01001835 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1836 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 +02001837 if (strcmp(temp_val, "true") == 0) {
1838 *flags |= LYS_CONFIG_W;
1839 } else if (strcmp(temp_val, "false") == 0) {
1840 *flags |= LYS_CONFIG_R;
1841 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001842 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001843 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001844 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001845 return LY_EVALID;
1846 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001847 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001848
Radek Krejcif13b87b2020-12-01 22:02:17 +01001849 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001850}
1851
1852/**
1853 * @brief Parse yang-version element.
1854 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001855 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001856 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001857 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001858 *
1859 * @return LY_ERR values.
1860 */
1861static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001862yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001863{
1864 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001865 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001866 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1867 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001868
Michal Vaskob36053d2020-03-26 15:49:30 +01001869 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1870 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 +02001871 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001872 *version = LYS_VERSION_1_0;
1873 } else if (strcmp(temp_version, "1.1") == 0) {
1874 *version = LYS_VERSION_1_1;
1875 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001876 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001877 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001878 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001879 return LY_EVALID;
1880 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001881 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001882
Radek Krejcif13b87b2020-12-01 22:02:17 +01001883 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001884}
1885
1886/**
1887 * @brief Parse import element.
1888 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001889 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001890 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1891 *
1892 * @return LY_ERR values.
1893 */
1894static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001895yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001896{
1897 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001898
David Sedlákdfbbb442019-08-06 16:33:21 +02001899 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001900 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001901
Radek Krejcif13b87b2020-12-01 22:02:17 +01001902 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001903 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1904 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1905 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1906 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1907 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1908 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001909
1910 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001911 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1912 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 +01001913 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 +02001914 /* check prefix validity */
1915 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1916
1917 return LY_SUCCESS;
1918}
1919
1920/**
1921 * @brief Parse mandatory element.
1922 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001923 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001924 * @param[in,out] flags Flags to add to.
1925 * @param[in,out] exts Extension instances to add to.
1926 *
1927 * @return LY_ERR values.
1928 */
1929static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001930yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001931{
1932 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001933 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001934 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1935 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001936
Michal Vaskob36053d2020-03-26 15:49:30 +01001937 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1938 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 +02001939 if (strcmp(temp_val, "true") == 0) {
1940 *flags |= LYS_MAND_TRUE;
1941 } else if (strcmp(temp_val, "false") == 0) {
1942 *flags |= LYS_MAND_FALSE;
1943 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001944 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001945 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001946 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001947 return LY_EVALID;
1948 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001949 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001950
Radek Krejcif13b87b2020-12-01 22:02:17 +01001951 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001952}
1953
1954/**
1955 * @brief Parse status element.
1956 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001957 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001958 * @param[in,out] flags Flags to add to.
1959 * @param[in,out] exts Extension instances to add to.
1960 *
1961 * @return LY_ERR values.
1962 */
1963static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001964yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001965{
1966 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001967 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001968 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1969 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001970
Michal Vaskob36053d2020-03-26 15:49:30 +01001971 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1972 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 +02001973 if (strcmp(value, "current") == 0) {
1974 *flags |= LYS_STATUS_CURR;
1975 } else if (strcmp(value, "deprecated") == 0) {
1976 *flags |= LYS_STATUS_DEPRC;
1977 } else if (strcmp(value, "obsolete") == 0) {
1978 *flags |= LYS_STATUS_OBSLT;
1979 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001980 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001981 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001982 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001983 return LY_EVALID;
1984 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001985 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001986
Radek Krejcif13b87b2020-12-01 22:02:17 +01001987 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001988}
1989
1990/**
1991 * @brief Parse when element.
1992 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001993 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001994 * @param[out] when_p When pointer to parse to.
1995 */
1996static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001997yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001998{
1999 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02002000 LY_ERR ret = LY_SUCCESS;
2001
David Sedlákdfbbb442019-08-06 16:33:21 +02002002 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01002003 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02002004
2005 ret = lyxml_ctx_next(ctx->xmlctx);
2006 LY_CHECK_ERR_RET(ret, free(when), ret);
2007
Michal Vaskob36053d2020-03-26 15:49:30 +01002008 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02002009 LY_CHECK_ERR_RET(ret, free(when), ret);
2010
David Sedlákdfbbb442019-08-06 16:33:21 +02002011 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002012 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002013 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2014 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2015 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2016 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002017
Radek Krejcif13b87b2020-12-01 22:02:17 +01002018 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002019}
2020
2021/**
2022 * @brief Parse yin-elemenet element.
2023 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002024 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002025 * @param[in,out] data Data to read from, always moved to currently handled position.
2026 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002027 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002028 *
2029 * @return LY_ERR values.
2030 */
2031static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002032yin_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 +02002033{
2034 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002035 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002036 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2037 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002038
Michal Vaskob36053d2020-03-26 15:49:30 +01002039 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2040 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 +02002041 if (strcmp(temp_val, "true") == 0) {
2042 *flags |= LYS_YINELEM_TRUE;
2043 } else if (strcmp(temp_val, "false") == 0) {
2044 *flags |= LYS_YINELEM_FALSE;
2045 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002046 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002047 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002048 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002049 return LY_EVALID;
2050 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002051 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002052
Radek Krejcif13b87b2020-12-01 22:02:17 +01002053 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002054}
2055
2056/**
2057 * @brief Parse argument element.
2058 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002059 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002060 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2061 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002062 *
2063 * @return LY_ERR values.
2064 */
2065static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002066yin_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 +02002067{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002068 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002069 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2070 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2071 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002072
Michal Vaskob36053d2020-03-26 15:49:30 +01002073 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2074 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 +02002075
Radek Krejcif13b87b2020-12-01 22:02:17 +01002076 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002077}
2078
2079/**
2080 * @brief Parse the extension statement.
2081 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002082 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002083 * @param[in,out] extensions Extensions to add to.
2084 *
2085 * @return LY_ERR values.
2086 */
2087static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002088yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002089{
2090 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002091
Michal Vaskob36053d2020-03-26 15:49:30 +01002092 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2093 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2094 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 +02002095
Radek Krejci9f87b0c2021-03-05 14:45:26 +01002096 struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002097 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002098 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2099 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2100 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2101 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2102 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2103 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002104
Radek Krejcif13b87b2020-12-01 22:02:17 +01002105 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002106}
2107
2108/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002109 * @brief Parse feature element.
2110 *
2111 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002112 * @param[in,out] features Features to add to.
2113 *
2114 * @return LY_ERR values.
2115 */
2116static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002117yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002118{
2119 struct lysp_feature *feat;
2120
2121 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002122 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002123
2124 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002125 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2126 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 +02002127
2128 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002129 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002130 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2131 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2132 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2133 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2134 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2135 };
Michal Vasko69730152020-10-09 16:30:07 +02002136
Radek Krejcif13b87b2020-12-01 22:02:17 +01002137 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002138}
2139
2140/**
David Sedlák28794f22019-07-22 16:45:00 +02002141 * @brief Parse identity element.
2142 *
2143 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002144 * @param[in,out] identities Identities to add to.
2145 *
2146 * @return LY_ERR values.
2147 */
2148static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002149yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002150{
2151 struct lysp_ident *ident;
2152
2153 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002154 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002155
2156 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002157 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2158 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 +02002159
2160 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002161 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002162 {LY_STMT_BASE, &ident->bases, 0},
2163 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2164 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2165 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2166 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2167 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2168 };
Michal Vasko69730152020-10-09 16:30:07 +02002169
Radek Krejcif13b87b2020-12-01 22:02:17 +01002170 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002171}
2172
2173/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002174 * @brief Parse list element.
2175 *
2176 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002177 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002178 *
2179 * @return LY_ERR values.
2180 */
2181static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002182yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002183{
David Sedlákaf536aa2019-07-23 13:42:23 +02002184 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002185 LY_ERR ret = LY_SUCCESS;
2186 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002187 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002188
Michal Vaskob36053d2020-03-26 15:49:30 +01002189 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002190 list->nodetype = LYS_LIST;
2191 list->parent = node_meta->parent;
2192
David Sedlákaf536aa2019-07-23 13:42:23 +02002193 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002194 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2195 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 +02002196
2197 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002198 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002199 LY_STMT_ACTION, &list->actions, 0,
2200 LY_STMT_ANYDATA, &list->child, 0,
2201 LY_STMT_ANYXML, &list->child, 0,
2202 LY_STMT_CHOICE, &list->child, 0,
2203 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2204 LY_STMT_CONTAINER, &list->child, 0,
2205 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2206 LY_STMT_GROUPING, &list->groupings, 0,
2207 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2208 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2209 LY_STMT_LEAF, &list->child, 0,
2210 LY_STMT_LEAF_LIST, &list->child, 0,
2211 LY_STMT_LIST, &list->child, 0,
2212 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2213 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2214 LY_STMT_MUST, &list->musts, 0,
2215 LY_STMT_NOTIFICATION, &list->notifs, 0,
2216 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2217 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2218 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2219 LY_STMT_TYPEDEF, &list->typedefs, 0,
2220 LY_STMT_UNIQUE, &list->uniques, 0,
2221 LY_STMT_USES, &list->child, 0,
2222 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2223 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002224 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2225 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002226 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002227
Michal Vasko69730152020-10-09 16:30:07 +02002228 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002229 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002230 return LY_EVALID;
2231 }
2232
2233 return LY_SUCCESS;
2234}
2235
2236/**
David Sedlák031b9e72019-07-23 15:19:37 +02002237 * @brief Parse notification element.
2238 *
2239 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002240 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002241 *
2242 * @return LY_ERR values.
2243 */
2244static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002245yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002246{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002247 struct lysp_node_notif *notif;
2248 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002249 LY_ERR ret = LY_SUCCESS;
2250 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002251 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002252
2253 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002254 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002255 notif->nodetype = LYS_NOTIF;
2256 notif->parent = notif_meta->parent;
2257
2258 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002259 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2260 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 +02002261
2262 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002263 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002264 LY_STMT_ANYDATA, &notif->child, 0,
2265 LY_STMT_ANYXML, &notif->child, 0,
2266 LY_STMT_CHOICE, &notif->child, 0,
2267 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002268 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2269 LY_STMT_GROUPING, &notif->groupings, 0,
2270 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002271 LY_STMT_LEAF, &notif->child, 0,
2272 LY_STMT_LEAF_LIST, &notif->child, 0,
2273 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002274 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2275 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2276 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2277 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002278 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002279 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002280
Radek Krejcif13b87b2020-12-01 22:02:17 +01002281 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2282 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002283 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002284
David Sedlák031b9e72019-07-23 15:19:37 +02002285 return LY_SUCCESS;
2286}
2287
2288/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002289 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002290 *
2291 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002292 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002293 *
2294 * @return LY_ERR values.
2295 */
2296static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002297yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002298{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002299 struct lysp_node_grp *grp;
2300 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002301 LY_ERR ret = LY_SUCCESS;
2302 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002303 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002304
2305 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002306 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002307 grp->nodetype = LYS_GROUPING;
2308 grp->parent = gr_meta->parent;
2309
2310 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002311 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2312 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 +02002313
2314 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002315 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002316 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002317 LY_STMT_ANYDATA, &grp->child, 0,
2318 LY_STMT_ANYXML, &grp->child, 0,
2319 LY_STMT_CHOICE, &grp->child, 0,
2320 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002321 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2322 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002323 LY_STMT_LEAF, &grp->child, 0,
2324 LY_STMT_LEAF_LIST, &grp->child, 0,
2325 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002326 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2327 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2328 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2329 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002330 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002331 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002332 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2333 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002334
aPiecek63e080d2021-06-29 13:53:28 +02002335 /* store data for collision check */
2336 if (!ret && grp->parent) {
2337 assert(ctx->main_ctx);
2338 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, grp->parent, 0, NULL));
2339 }
2340
Radek Krejci2a9fc652021-01-22 17:44:34 +01002341 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002342}
2343
2344/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002345 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002346 *
2347 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002348 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002349 *
2350 * @return LY_ERR values.
2351 */
2352static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002353yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002354{
David Sedlákf111bcb2019-07-23 17:15:51 +02002355 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002356 LY_ERR ret = LY_SUCCESS;
2357 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002358 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002359
2360 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002361 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002362 cont->nodetype = LYS_CONTAINER;
2363 cont->parent = node_meta->parent;
2364
David Sedlákf111bcb2019-07-23 17:15:51 +02002365 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002366 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2367 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 +02002368
2369 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002370 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002371 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2372 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2373 LY_STMT_ANYXML, &cont->child, 0,
2374 LY_STMT_CHOICE, &cont->child, 0,
2375 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2376 LY_STMT_CONTAINER, &cont->child, 0,
2377 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2378 LY_STMT_GROUPING, &cont->groupings, 0,
2379 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2380 LY_STMT_LEAF, &cont->child, 0,
2381 LY_STMT_LEAF_LIST, &cont->child, 0,
2382 LY_STMT_LIST, &cont->child, 0,
2383 LY_STMT_MUST, &cont->musts, 0,
2384 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2385 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2386 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2387 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2388 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2389 LY_STMT_USES, &cont->child, 0,
2390 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2391 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002392 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2393 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002394
Radek Krejci2a9fc652021-01-22 17:44:34 +01002395 return ret;
David Sedlákf111bcb2019-07-23 17:15:51 +02002396}
2397
2398/**
David Sedlák5379d392019-07-24 10:42:03 +02002399 * @brief Parse case element.
2400 *
2401 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002402 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002403 *
2404 * @return LY_ERR values.
2405 */
2406static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002407yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002408{
David Sedlák5379d392019-07-24 10:42:03 +02002409 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002410 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002411 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002412 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002413
2414 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002415 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002416 cas->nodetype = LYS_CASE;
2417 cas->parent = node_meta->parent;
2418
David Sedlák5379d392019-07-24 10:42:03 +02002419 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002420 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2421 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 +02002422
2423 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002424 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002425 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2426 LY_STMT_ANYXML, &cas->child, 0,
2427 LY_STMT_CHOICE, &cas->child, 0,
2428 LY_STMT_CONTAINER, &cas->child, 0,
2429 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2430 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2431 LY_STMT_LEAF, &cas->child, 0,
2432 LY_STMT_LEAF_LIST, &cas->child, 0,
2433 LY_STMT_LIST, &cas->child, 0,
2434 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2435 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2436 LY_STMT_USES, &cas->child, 0,
2437 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2438 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002439 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2440 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002441
2442 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002443}
2444
2445/**
David Sedlák05404f62019-07-24 14:11:53 +02002446 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002447 *
2448 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002449 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002450 *
2451 * @return LY_ERR values.
2452 */
2453LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002454yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002455{
David Sedlák81497a32019-08-13 16:56:26 +02002456 LY_ERR ret = LY_SUCCESS;
2457 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002458 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002459 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002460
2461 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002462 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002463
David Sedlákb7abcfa2019-07-24 12:33:35 +02002464 choice->nodetype = LYS_CHOICE;
2465 choice->parent = node_meta->parent;
2466
David Sedlákb7abcfa2019-07-24 12:33:35 +02002467 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002468 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2469 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 +02002470
2471 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002472 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002473 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2474 LY_STMT_ANYXML, &choice->child, 0,
2475 LY_STMT_CASE, &choice->child, 0,
2476 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2477 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2478 LY_STMT_CONTAINER, &choice->child, 0,
2479 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2480 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2481 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2482 LY_STMT_LEAF, &choice->child, 0,
2483 LY_STMT_LEAF_LIST, &choice->child, 0,
2484 LY_STMT_LIST, &choice->child, 0,
2485 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2486 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2487 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2488 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2489 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002490 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2491 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002492 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002493}
2494
2495/**
David Sedlák05404f62019-07-24 14:11:53 +02002496 * @brief Parse input or output element.
2497 *
2498 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002499 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002500 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2501 *
2502 * @return LY_ERR values.
2503 */
2504static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002505yin_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 +02002506{
David Sedlák81497a32019-08-13 16:56:26 +02002507 LY_ERR ret = LY_SUCCESS;
2508 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002509 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002510
David Sedlák05404f62019-07-24 14:11:53 +02002511 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002512 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 +02002513 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002514 inout_meta->inout_p->parent = inout_meta->parent;
2515
2516 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002517 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2518 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 +02002519
2520 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002521 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002522 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2523 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2524 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2525 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002526 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002527 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2528 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2529 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002530 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2531 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002532 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002533 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002534 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2535 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002536 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002537
Radek Krejci01180ac2021-01-27 08:48:22 +01002538 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002539 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2540 return LY_EVALID;
2541 }
2542
David Sedlák05404f62019-07-24 14:11:53 +02002543 return LY_SUCCESS;
2544}
2545
David Sedlák992fb7c2019-07-24 16:51:01 +02002546/**
2547 * @brief Parse action element.
2548 *
2549 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002550 * @param[in] act_meta Meta information about parent node and actions to add to.
2551 *
2552 * @return LY_ERR values.
2553 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002554static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002555yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002556{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002557 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002558 LY_ERR ret = LY_SUCCESS;
2559 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002560 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002561 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002562
2563 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002564 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002565 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002566 act->parent = act_meta->parent;
2567
2568 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002569 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002570 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002571
2572 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002573 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002574 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2575 LY_STMT_GROUPING, &act->groupings, 0,
2576 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2577 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2578 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2579 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2580 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2581 LY_STMT_TYPEDEF, &act->typedefs, 0,
2582 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002583 ret = (yin_parse_content(ctx, subelems, subelems_size, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002584 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002585 LY_CHECK_RET(ret);
2586
Michal Vasko7f45cf22020-10-01 12:49:44 +02002587 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2588 if (!act->input.nodetype) {
2589 act->input.nodetype = LYS_INPUT;
2590 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002591 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002592 }
2593 if (!act->output.nodetype) {
2594 act->output.nodetype = LYS_OUTPUT;
2595 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002596 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002597 }
2598
David Sedlák85d0eca2019-07-24 15:15:21 +02002599 return LY_SUCCESS;
2600}
2601
David Sedlák05404f62019-07-24 14:11:53 +02002602/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002603 * @brief Parse augment element.
2604 *
2605 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002606 * @param[in] aug_meta Meta information about parent node and augments to add to.
2607 *
2608 * @return LY_ERR values.
2609 */
2610static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002611yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002612{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002613 struct lysp_node_augment *aug;
2614 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002615 LY_ERR ret = LY_SUCCESS;
2616 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002617 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002618
2619 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002620 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002621 aug->nodetype = LYS_AUGMENT;
2622 aug->parent = aug_meta->parent;
2623
2624 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002625 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2626 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2627 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002628
2629 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002630 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002631 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2632 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2633 LY_STMT_ANYXML, &aug->child, 0,
2634 LY_STMT_CASE, &aug->child, 0,
2635 LY_STMT_CHOICE, &aug->child, 0,
2636 LY_STMT_CONTAINER, &aug->child, 0,
2637 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002638 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002639 LY_STMT_LEAF, &aug->child, 0,
2640 LY_STMT_LEAF_LIST, &aug->child, 0,
2641 LY_STMT_LIST, &aug->child, 0,
2642 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2643 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2644 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2645 LY_STMT_USES, &aug->child, 0,
2646 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2647 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002648 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2649 subelems_deallocator(subelems_size, subelems);
David Sedlák992fb7c2019-07-24 16:51:01 +02002650
Radek Krejci2a9fc652021-01-22 17:44:34 +01002651 return ret;
David Sedlák992fb7c2019-07-24 16:51:01 +02002652}
2653
David Sedlák8b754462019-07-25 16:22:13 +02002654/**
2655 * @brief Parse deviate element.
2656 *
2657 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002658 * @param[in] deviates Deviates to add to.
2659 *
2660 * @return LY_ERR values.
2661 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002662static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002663yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002664{
2665 LY_ERR ret = LY_SUCCESS;
2666 uint8_t dev_mod;
2667 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002668 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002669 struct lysp_deviate_add *d_add = NULL;
2670 struct lysp_deviate_rpl *d_rpl = NULL;
2671 struct lysp_deviate_del *d_del = NULL;
2672
2673 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002674 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2675 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 +02002676
2677 if (strcmp(temp_val, "not-supported") == 0) {
2678 dev_mod = LYS_DEV_NOT_SUPPORTED;
2679 } else if (strcmp(temp_val, "add") == 0) {
2680 dev_mod = LYS_DEV_ADD;
2681 } else if (strcmp(temp_val, "replace") == 0) {
2682 dev_mod = LYS_DEV_REPLACE;
2683 } else if (strcmp(temp_val, "delete") == 0) {
2684 dev_mod = LYS_DEV_DELETE;
2685 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002686 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002687 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002688 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002689 return LY_EVALID;
2690 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002691 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002692
2693 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2694 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002695 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002696 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002697 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2698 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002699
Radek Krejcif13b87b2020-12-01 22:02:17 +01002700 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002701
2702 } else if (dev_mod == LYS_DEV_ADD) {
2703 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002704 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002705 d = (struct lysp_deviate *)d_add;
2706 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2707 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002708 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002709 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002710 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002711 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2712 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2713 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2714 {LY_STMT_MUST, &d_add->musts, 0},
2715 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2716 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2717 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2718 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002719
Radek Krejcif13b87b2020-12-01 22:02:17 +01002720 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002721
2722 } else if (dev_mod == LYS_DEV_REPLACE) {
2723 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002724 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002725 d = (struct lysp_deviate *)d_rpl;
2726 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2727 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002728 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002729 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002730 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002731 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2732 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2733 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2734 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2735 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2736 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2737 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002738
Radek Krejcif13b87b2020-12-01 22:02:17 +01002739 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002740
2741 } else {
2742 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002743 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002744 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002745 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002746 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002747 {LY_STMT_MUST, &d_del->musts, 0},
2748 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2749 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2750 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2751 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002752
Radek Krejcif13b87b2020-12-01 22:02:17 +01002753 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002754 }
2755 LY_CHECK_GOTO(ret, cleanup);
2756
2757 d->mod = dev_mod;
2758 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002759 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002760
2761 return ret;
2762
2763cleanup:
2764 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002765 return ret;
2766}
2767
David Sedlák992fb7c2019-07-24 16:51:01 +02002768/**
David Sedlák8b754462019-07-25 16:22:13 +02002769 * @brief Parse deviation element.
2770 *
2771 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002772 * @param[in] deviations Deviations to add to.
2773 *
2774 * @return LY_ERR values.
2775 */
2776static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002777yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002778{
Michal Vasko12ef5362022-09-16 15:13:58 +02002779 LY_ERR ret = LY_SUCCESS;
2780 struct lysp_deviation *dev = NULL;
David Sedlák8b754462019-07-25 16:22:13 +02002781
2782 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002783 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002784
2785 /* parse argument */
Michal Vasko12ef5362022-09-16 15:13:58 +02002786 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2787 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION), cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01002788 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002789 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002790 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2791 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2792 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2793 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2794 };
Michal Vasko69730152020-10-09 16:30:07 +02002795
Michal Vasko12ef5362022-09-16 15:13:58 +02002796 LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts), cleanup);
2797
2798cleanup:
2799 if (ret) {
2800 lysp_deviation_free(PARSER_CTX(ctx), dev);
2801 LY_ARRAY_DECREMENT_FREE(*deviations);
2802 }
2803 return ret;
David Sedlák8b754462019-07-25 16:22:13 +02002804}
2805
2806/**
David Sedlákc5b20842019-08-13 10:18:31 +02002807 * @brief map keyword to keyword-group.
2808 *
2809 * @param[in] ctx YIN parser context used for logging.
2810 * @param[in] kw Keyword that is child of module or submodule.
2811 * @param[out] group Group of keyword.
2812 *
2813 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2814 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002815static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002816kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002817{
2818 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002819 /* module header */
2820 case LY_STMT_NONE:
2821 case LY_STMT_NAMESPACE:
2822 case LY_STMT_PREFIX:
2823 case LY_STMT_BELONGS_TO:
2824 case LY_STMT_YANG_VERSION:
2825 *group = Y_MOD_MODULE_HEADER;
2826 break;
2827 /* linkage */
2828 case LY_STMT_INCLUDE:
2829 case LY_STMT_IMPORT:
2830 *group = Y_MOD_LINKAGE;
2831 break;
2832 /* meta */
2833 case LY_STMT_ORGANIZATION:
2834 case LY_STMT_CONTACT:
2835 case LY_STMT_DESCRIPTION:
2836 case LY_STMT_REFERENCE:
2837 *group = Y_MOD_META;
2838 break;
2839 /* revision */
2840 case LY_STMT_REVISION:
2841 *group = Y_MOD_REVISION;
2842 break;
2843 /* body */
2844 case LY_STMT_ANYDATA:
2845 case LY_STMT_ANYXML:
2846 case LY_STMT_AUGMENT:
2847 case LY_STMT_CHOICE:
2848 case LY_STMT_CONTAINER:
2849 case LY_STMT_DEVIATION:
2850 case LY_STMT_EXTENSION:
2851 case LY_STMT_FEATURE:
2852 case LY_STMT_GROUPING:
2853 case LY_STMT_IDENTITY:
2854 case LY_STMT_LEAF:
2855 case LY_STMT_LEAF_LIST:
2856 case LY_STMT_LIST:
2857 case LY_STMT_NOTIFICATION:
2858 case LY_STMT_RPC:
2859 case LY_STMT_TYPEDEF:
2860 case LY_STMT_USES:
2861 case LY_STMT_EXTENSION_INSTANCE:
2862 *group = Y_MOD_BODY;
2863 break;
2864 default:
2865 LOGINT(ctx->xmlctx->ctx);
2866 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002867 }
2868
2869 return LY_SUCCESS;
2870}
2871
David Sedlákc5b20842019-08-13 10:18:31 +02002872/**
2873 * @brief Check if relative order of two keywords is valid.
2874 *
2875 * @param[in] ctx YIN parser context used for logging.
2876 * @param[in] kw Current keyword.
2877 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002878 * @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 +02002879 * because relative order is required only in module and submodule sub-elements, used for logging.
2880 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002881 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002882 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002883static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002884yin_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 +02002885{
Radek Krejcid6b76452019-09-03 17:03:03 +02002886 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002887 enum yang_module_stmt gr, next_gr;
2888
Michal Vaskoc78293f2021-12-16 15:40:33 +01002889 if (kw == LY_STMT_EXTENSION_INSTANCE) {
2890 /* no order defined */
2891 return LY_SUCCESS;
2892 }
2893
David Sedláke6cd89e2019-08-07 12:46:02 +02002894 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2895 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2896
2897 if (gr > next_gr) {
2898 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2899 return LY_EVALID;
2900 }
2901
2902 return LY_SUCCESS;
2903}
2904
David Sedlákc5dd0942019-09-13 10:23:59 +02002905/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002906 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2907 *
2908 * @param[in,out] ctx Yin parser context for logging and to store current state.
2909 * @param[in] elem_type Type of element that is currently being parsed.
2910 * @param[out] arg Value to write to.
2911 *
2912 * @return LY_ERR values.
2913 */
2914static LY_ERR
2915yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2916{
2917 enum ly_stmt child;
2918
2919 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2920
2921 switch (elem_type) {
2922 case LY_STMT_ACTION:
2923 case LY_STMT_ANYDATA:
2924 case LY_STMT_ANYXML:
2925 case LY_STMT_ARGUMENT:
2926 case LY_STMT_BASE:
2927 case LY_STMT_BIT:
2928 case LY_STMT_CASE:
2929 case LY_STMT_CHOICE:
2930 case LY_STMT_CONTAINER:
2931 case LY_STMT_ENUM:
2932 case LY_STMT_EXTENSION:
2933 case LY_STMT_FEATURE:
2934 case LY_STMT_GROUPING:
2935 case LY_STMT_IDENTITY:
2936 case LY_STMT_IF_FEATURE:
2937 case LY_STMT_LEAF:
2938 case LY_STMT_LEAF_LIST:
2939 case LY_STMT_LIST:
2940 case LY_STMT_MODULE:
2941 case LY_STMT_NOTIFICATION:
2942 case LY_STMT_RPC:
2943 case LY_STMT_SUBMODULE:
2944 case LY_STMT_TYPE:
2945 case LY_STMT_TYPEDEF:
2946 case LY_STMT_UNITS:
2947 case LY_STMT_USES:
2948 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
2949 break;
2950 case LY_STMT_AUGMENT:
2951 case LY_STMT_DEVIATION:
2952 case LY_STMT_REFINE:
2953 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
2954 break;
2955 case LY_STMT_CONFIG:
2956 case LY_STMT_DEFAULT:
2957 case LY_STMT_DEVIATE:
2958 case LY_STMT_ERROR_APP_TAG:
2959 case LY_STMT_FRACTION_DIGITS:
2960 case LY_STMT_KEY:
2961 case LY_STMT_LENGTH:
2962 case LY_STMT_MANDATORY:
2963 case LY_STMT_MAX_ELEMENTS:
2964 case LY_STMT_MIN_ELEMENTS:
2965 case LY_STMT_MODIFIER:
2966 case LY_STMT_ORDERED_BY:
2967 case LY_STMT_PATH:
2968 case LY_STMT_PATTERN:
2969 case LY_STMT_POSITION:
2970 case LY_STMT_PREFIX:
2971 case LY_STMT_PRESENCE:
2972 case LY_STMT_RANGE:
2973 case LY_STMT_REQUIRE_INSTANCE:
2974 case LY_STMT_STATUS:
2975 case LY_STMT_VALUE:
2976 case LY_STMT_YANG_VERSION:
2977 case LY_STMT_YIN_ELEMENT:
2978 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
2979 break;
2980 case LY_STMT_IMPORT:
2981 case LY_STMT_INCLUDE:
2982 case LY_STMT_BELONGS_TO:
2983 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
2984 break;
2985 case LY_STMT_INPUT:
2986 case LY_STMT_OUTPUT:
2987 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2988 break;
2989 case LY_STMT_MUST:
2990 case LY_STMT_WHEN:
2991 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
2992 break;
2993 case LY_STMT_NAMESPACE:
2994 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
2995 break;
2996 case LY_STMT_REVISION:
2997 case LY_STMT_REVISION_DATE:
2998 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
2999 break;
3000 case LY_STMT_UNIQUE:
3001 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
3002 break;
3003 /* argument is mapped to yin element */
3004 case LY_STMT_CONTACT:
3005 case LY_STMT_DESCRIPTION:
3006 case LY_STMT_ORGANIZATION:
3007 case LY_STMT_REFERENCE:
3008 case LY_STMT_ERROR_MESSAGE:
3009 /* there shouldn't be any attribute, argument is supposed to be first subelement */
3010 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3011
3012 /* no content */
3013 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3014 if (ctx->xmlctx->ws_only) {
3015 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3016 }
3017 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3018 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3019 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
3020 return LY_EVALID;
3021 }
3022
3023 /* parse child element */
3024 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3025 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3026 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
3027 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3028 ly_stmt2str(elem_type));
3029 return LY_EVALID;
3030 }
3031 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3032
3033 /* no attributes expected? TODO */
3034 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3035 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3036 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3037 }
3038
3039 /* load and save content */
3040 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3041 LY_CHECK_RET(!*arg, LY_EMEM);
3042
3043 /* load closing tag of subelement */
3044 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3045
3046 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3047 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3048 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3049 }*/
3050 break;
3051 default:
3052 LOGINT(ctx->xmlctx->ctx);
3053 return LY_EINT;
3054 }
3055
3056 return LY_SUCCESS;
3057}
3058
3059/**
3060 * @brief Parse yin element into generic structure.
3061 *
3062 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3063 * @param[in] parent Identification of parent element.
3064 * @param[out] element Where the element structure should be stored.
3065 *
3066 * @return LY_ERR values.
3067 */
3068LY_ERR
3069yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3070{
3071 LY_ERR ret = LY_SUCCESS;
3072 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003073 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003074
3075 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3076
3077 /* allocate new structure for element */
3078 *element = calloc(1, sizeof(**element));
3079 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003080
3081 /* store identifier */
3082 if (ctx->xmlctx->prefix_len) {
3083 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3084 ctx->xmlctx->name) == -1) {
3085 LOGMEM(ctx->xmlctx->ctx);
3086 ret = LY_EMEM;
3087 goto cleanup;
3088 }
3089 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3090
3091 /* store prefix data for the statement */
Radek Krejci8df109d2021-04-23 12:19:08 +02003092 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->stmt, strlen((*element)->stmt), LY_VALUE_XML,
Michal Vaskofc2cd072021-02-24 13:17:17 +01003093 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3094 } else {
3095 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3096 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003097
3098 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3099 ctx->xmlctx->prefix_len, parent);
3100
3101 last = (*element)->child;
3102 if ((*element)->kw == LY_STMT_NONE) {
3103 /* unrecognized element */
3104 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3105 ly_stmt2str(parent));
3106 ret = LY_EVALID;
3107 goto cleanup;
3108 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3109 /* element is known yang keyword, which means argument can be parsed correctly. */
3110 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3111 LY_CHECK_GOTO(ret, cleanup);
3112 } else {
3113 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3114
3115 /* load attributes in generic way, save all attributes in linked list */
3116 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3117 new = calloc(1, sizeof(*last));
3118 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3119 if (!(*element)->child) {
3120 /* save first */
3121 (*element)->child = new;
3122 } else {
3123 last->next = new;
3124 }
3125 last = new;
3126
3127 last->flags |= LYS_YIN_ATTR;
3128 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3129 last->kw = LY_STMT_NONE;
3130 /* attributes with prefix are ignored */
3131 if (!ctx->xmlctx->prefix) {
3132 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3133
3134 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3135 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3136 } else {
3137 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3138 }
3139 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3140 }
3141 }
3142
3143 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3144 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3145 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3146 /* parse subelements */
3147 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3148 LY_CHECK_GOTO(ret, cleanup);
3149 if (!(*element)->child) {
3150 /* save first */
3151 (*element)->child = new;
3152 } else {
3153 last->next = new;
3154 }
3155 last = new;
3156
3157 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3158 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3159 }
3160 } else {
3161 /* save element content */
3162 if (ctx->xmlctx->value_len) {
3163 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3164 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003165
3166 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003167 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->arg, strlen((*element)->arg), LY_VALUE_XML,
Michal Vaskofc2cd072021-02-24 13:17:17 +01003168 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003169 }
3170
3171 /* read closing tag */
3172 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3173 }
3174
3175cleanup:
3176 return ret;
3177}
3178
3179/**
3180 * @brief Parse instance of extension.
3181 *
3182 * @param[in,out] ctx Yin parser context for logging and to store current state.
Radek Krejcifc596f92021-02-26 22:40:26 +01003183 * @param[in] subelem The statement this extension instance is a subelement of.
Michal Vaskoafac7822020-10-20 14:22:26 +02003184 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3185 * @param[in,out] exts Extension instance to add to.
3186 *
3187 * @return LY_ERR values.
3188 */
3189LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01003190yin_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 +02003191 struct lysp_ext_instance **exts)
3192{
3193 struct lysp_ext_instance *e;
3194 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003195 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003196
3197 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003198 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003199
3200 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3201
Michal Vaskofc2cd072021-02-24 13:17:17 +01003202 if (!ctx->xmlctx->prefix_len) {
3203 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3204 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3205 return LY_EVALID;
3206 }
3207
3208 /* store prefixed name */
3209 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3210 ctx->xmlctx->name) == -1) {
3211 LOGMEM(ctx->xmlctx->ctx);
3212 return LY_EMEM;
3213 }
3214 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3215
3216 /* store prefix data for the name */
Radek Krejci8df109d2021-04-23 12:19:08 +02003217 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->name, strlen(e->name), LY_VALUE_XML, &ctx->xmlctx->ns,
Michal Vaskofc2cd072021-02-24 13:17:17 +01003218 &e->format, &e->prefix_data));
3219
Radek Krejciab430862021-03-02 20:13:40 +01003220 e->parent_stmt = subelem;
3221 e->parent_stmt_index = subelem_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003222
Michal Vaskoafac7822020-10-20 14:22:26 +02003223 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3224
3225 /* store attributes as subelements */
3226 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3227 if (!ctx->xmlctx->prefix) {
3228 new_subelem = calloc(1, sizeof(*new_subelem));
3229 if (!e->child) {
3230 e->child = new_subelem;
3231 } else {
3232 last_subelem->next = new_subelem;
3233 }
3234 last_subelem = new_subelem;
3235
3236 last_subelem->flags |= LYS_YIN_ATTR;
3237 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3238 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3239 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3240
Michal Vaskofc2cd072021-02-24 13:17:17 +01003241 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3242 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003243 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3244 } else {
3245 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3246 }
3247
3248 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3249 }
3250
3251 /* parse subelements */
3252 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3253 if (ctx->xmlctx->ws_only) {
3254 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3255 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3256 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3257 if (!e->child) {
3258 e->child = new_subelem;
3259 } else {
3260 last_subelem->next = new_subelem;
3261 }
3262 last_subelem = new_subelem;
3263
3264 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3265 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3266 }
3267 } else if (ctx->xmlctx->value_len) {
3268 /* save text content */
3269 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3270 LY_CHECK_RET(!e->argument, LY_EMEM);
3271
Michal Vaskofc2cd072021-02-24 13:17:17 +01003272 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003273 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->argument, strlen(e->argument), LY_VALUE_XML,
Radek Krejci07a55962021-03-02 20:16:43 +01003274 &ctx->xmlctx->ns, &e->format, &e->prefix_data));
Michal Vaskofc2cd072021-02-24 13:17:17 +01003275
Michal Vaskoafac7822020-10-20 14:22:26 +02003276 /* parser next */
3277 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3278 }
3279
aPiecek60d9d672021-04-27 15:49:57 +02003280 e->parsed = NULL;
3281
Michal Vaskoafac7822020-10-20 14:22:26 +02003282 return LY_SUCCESS;
3283}
3284
3285/**
3286 * @brief Generic function for content parsing
3287 *
3288 * @param[in,out] ctx Yin parser context for logging and to store current state.
3289 * @param[in] subelem_info array of valid subelement types and meta information
3290 * @param[in] subelem_info_size Size of subelem_info array.
3291 * @param[in] current_element Type of current element.
3292 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3293 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3294 *
3295 * @return LY_ERR values.
3296 */
David Sedlákd6e56892019-07-01 15:40:24 +02003297LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003298yin_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 +02003299 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003300{
3301 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003302 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003303 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003304 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003305
Michal Vaskob36053d2020-03-26 15:49:30 +01003306 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003307
Michal Vaskob36053d2020-03-26 15:49:30 +01003308 if (ctx->xmlctx->ws_only) {
3309 /* check whether there are any children */
3310 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3311 } else {
3312 /* we want to parse the value */
3313 next_status = LYXML_ELEM_CLOSE;
3314 }
3315
3316 if (next_status == LYXML_ELEMENT) {
3317 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3318
3319 /* current element has subelements as content */
3320 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3321 /* match keyword */
3322 last_kw = kw;
3323 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003324 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003325
3326 /* check if this element can be child of current element */
3327 subelem = get_record(kw, subelem_info_size, subelem_info);
3328 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003329 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003330 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3331 } else {
3332 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003333 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003334 }
3335 ret = LY_EVALID;
3336 goto cleanup;
3337 }
3338
3339 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003340 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003341 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3342 LY_CHECK_GOTO(ret, cleanup);
3343 }
3344
3345 /* flag check */
3346 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3347 /* subelement uniquenes */
3348 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3349 return LY_EVALID;
3350 }
3351 if (subelem->flags & YIN_SUBELEM_FIRST) {
3352 /* subelement is supposed to be defined as first subelement */
3353 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3354 LY_CHECK_GOTO(ret, cleanup);
3355 }
3356 if (subelem->flags & YIN_SUBELEM_VER2) {
3357 /* subelement is supported only in version 1.1 or higher */
Michal Vasko8a67eff2021-12-07 14:04:47 +01003358 if (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003359 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 +02003360 ret = LY_EVALID;
3361 goto cleanup;
3362 }
David Sedlákd6e56892019-07-01 15:40:24 +02003363 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003364 /* note that element was parsed for easy uniqueness check in next iterations */
3365 subelem->flags |= YIN_SUBELEM_PARSED;
3366
3367 switch (kw) {
3368 /* call responsible function */
3369 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003370 ret = yin_parse_extension_instance(ctx, current_element,
Michal Vasko69730152020-10-09 16:30:07 +02003371 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003372 break;
3373 case LY_STMT_ACTION:
3374 case LY_STMT_RPC:
3375 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3376 break;
3377 case LY_STMT_ANYDATA:
3378 case LY_STMT_ANYXML:
3379 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3380 break;
3381 case LY_STMT_ARGUMENT:
3382 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3383 break;
3384 case LY_STMT_AUGMENT:
3385 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3386 break;
3387 case LY_STMT_BASE:
3388 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3389 break;
3390 case LY_STMT_BELONGS_TO:
3391 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3392 break;
3393 case LY_STMT_BIT:
3394 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3395 break;
3396 case LY_STMT_CASE:
3397 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3398 break;
3399 case LY_STMT_CHOICE:
3400 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3401 break;
3402 case LY_STMT_CONFIG:
3403 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3404 break;
3405 case LY_STMT_CONTACT:
3406 case LY_STMT_DESCRIPTION:
3407 case LY_STMT_ORGANIZATION:
3408 case LY_STMT_REFERENCE:
3409 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3410 break;
3411 case LY_STMT_CONTAINER:
3412 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3413 break;
3414 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003415 ret = yin_parse_qname(ctx, kw, subelem, exts);
3416 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003417 case LY_STMT_ERROR_APP_TAG:
3418 case LY_STMT_KEY:
3419 case LY_STMT_PRESENCE:
3420 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3421 break;
3422 case LY_STMT_DEVIATE:
3423 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3424 break;
3425 case LY_STMT_DEVIATION:
3426 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3427 break;
3428 case LY_STMT_ENUM:
3429 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3430 break;
3431 case LY_STMT_ERROR_MESSAGE:
3432 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3433 break;
3434 case LY_STMT_EXTENSION:
3435 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3436 break;
3437 case LY_STMT_FEATURE:
3438 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3439 break;
3440 case LY_STMT_FRACTION_DIGITS:
3441 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3442 break;
3443 case LY_STMT_GROUPING:
3444 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3445 break;
3446 case LY_STMT_IDENTITY:
3447 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3448 break;
Radek Išabe8a6532021-03-29 08:54:22 +02003449 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003450 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003451 ret = yin_parse_qname(ctx, kw, subelem, exts);
3452 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003453 case LY_STMT_UNITS:
3454 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3455 break;
3456 case LY_STMT_IMPORT:
3457 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3458 break;
3459 case LY_STMT_INCLUDE:
Michal Vasko8a67eff2021-12-07 14:04:47 +01003460 if ((current_element == LY_STMT_SUBMODULE) && (PARSER_CUR_PMOD(ctx)->version == LYS_VERSION_1_1)) {
Radek Krejcieeee95c2021-01-19 10:57:22 +01003461 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
Michal Vasko8a67eff2021-12-07 14:04:47 +01003462 ((struct lysp_submodule *)PARSER_CUR_PMOD(ctx))->name);
Radek Krejcieeee95c2021-01-19 10:57:22 +01003463 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003464 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3465 break;
3466 case LY_STMT_INPUT:
3467 case LY_STMT_OUTPUT:
3468 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3469 break;
3470 case LY_STMT_LEAF:
3471 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3472 break;
3473 case LY_STMT_LEAF_LIST:
3474 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3475 break;
3476 case LY_STMT_LENGTH:
3477 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3478 break;
3479 case LY_STMT_LIST:
3480 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3481 break;
3482 case LY_STMT_MANDATORY:
3483 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3484 break;
3485 case LY_STMT_MAX_ELEMENTS:
3486 case LY_STMT_MIN_ELEMENTS:
3487 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3488 break;
3489 case LY_STMT_MODIFIER:
3490 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3491 break;
3492 case LY_STMT_MUST:
3493 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3494 break;
3495 case LY_STMT_NAMESPACE:
3496 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3497 break;
3498 case LY_STMT_NOTIFICATION:
3499 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3500 break;
3501 case LY_STMT_ORDERED_BY:
3502 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3503 break;
3504 case LY_STMT_PATH:
3505 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3506 break;
3507 case LY_STMT_PATTERN:
3508 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3509 break;
3510 case LY_STMT_VALUE:
3511 case LY_STMT_POSITION:
3512 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3513 break;
3514 case LY_STMT_PREFIX:
3515 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3516 break;
3517 case LY_STMT_RANGE:
3518 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3519 break;
3520 case LY_STMT_REFINE:
3521 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3522 break;
3523 case LY_STMT_REQUIRE_INSTANCE:
3524 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3525 break;
3526 case LY_STMT_REVISION:
3527 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3528 break;
3529 case LY_STMT_REVISION_DATE:
3530 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3531 break;
3532 case LY_STMT_STATUS:
3533 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3534 break;
3535 case LY_STMT_TYPE:
3536 ret = yin_parse_type(ctx, current_element, subelem);
3537 break;
3538 case LY_STMT_TYPEDEF:
3539 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3540 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003541 case LY_STMT_USES:
3542 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3543 break;
3544 case LY_STMT_WHEN:
3545 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3546 break;
3547 case LY_STMT_YANG_VERSION:
3548 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3549 break;
3550 case LY_STMT_YIN_ELEMENT:
3551 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3552 break;
3553 case LY_STMT_ARG_TEXT:
3554 case LY_STMT_ARG_VALUE:
3555 /* TODO what to do with content/attributes? */
3556 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3557 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3558 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3559 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3560 }
3561 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3562 break;
3563 default:
3564 LOGINT(ctx->xmlctx->ctx);
3565 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003566 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003567 LY_CHECK_GOTO(ret, cleanup);
3568 subelem = NULL;
3569
3570 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003571 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003572 } else {
3573 LY_CHECK_RET(ret);
3574 /* elements with text or none content */
3575 /* save text content, if text_content isn't set, it's just ignored */
3576 /* no resources are allocated in this branch, no need to use cleanup label */
3577 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3578 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003579 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 +01003580 LY_CHECK_RET(!*text_content, LY_EMEM);
3581 }
3582
3583 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003584 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003585
David Sedlák8b754462019-07-25 16:22:13 +02003586 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3587 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003588
3589cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003590 return ret;
3591}
3592
David Sedlákaa98bba2019-09-12 11:52:14 +02003593/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003594 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003595 *
3596 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003597 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003598 *
3599 * @return LY_ERR values.
3600 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003601LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003602yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003603{
David Sedlák81497a32019-08-13 16:56:26 +02003604 LY_ERR ret = LY_SUCCESS;
3605 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003606 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003607 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003608
Michal Vaskoc3781c32020-10-06 14:04:08 +02003609 mod->is_submod = 0;
3610
Michal Vaskob36053d2020-03-26 15:49:30 +01003611 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3612 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 +01003613 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003614 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3615 LY_STMT_ANYXML, &mod->data, 0,
3616 LY_STMT_AUGMENT, &mod->augments, 0,
3617 LY_STMT_CHOICE, &mod->data, 0,
3618 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3619 LY_STMT_CONTAINER, &mod->data, 0,
3620 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3621 LY_STMT_DEVIATION, &mod->deviations, 0,
3622 LY_STMT_EXTENSION, &mod->extensions, 0,
3623 LY_STMT_FEATURE, &mod->features, 0,
3624 LY_STMT_GROUPING, &mod->groupings, 0,
3625 LY_STMT_IDENTITY, &mod->identities, 0,
3626 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3627 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3628 LY_STMT_LEAF, &mod->data, 0,
3629 LY_STMT_LEAF_LIST, &mod->data, 0,
3630 LY_STMT_LIST, &mod->data, 0,
3631 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3632 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3633 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3634 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3635 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3636 LY_STMT_REVISION, &mod->revs, 0,
3637 LY_STMT_RPC, &mod->rpcs, 0,
3638 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3639 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003640 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003641 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003642
Radek Krejcif13b87b2020-12-01 22:02:17 +01003643 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3644 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003645 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003646
David Sedláked809f12019-09-13 10:15:11 +02003647 /* submodules share the namespace with the module names, so there must not be
3648 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003649 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003650 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003651 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003652 return LY_EVALID;
3653 }
3654
3655 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003656}
3657
Michal Vaskoafac7822020-10-20 14:22:26 +02003658/**
3659 * @brief Parse submodule element.
3660 *
3661 * @param[in,out] ctx Yin parser context for logging and to store current state.
3662 * @param[in] mod_attrs Attributes of submodule element.
3663 * @param[out] submod Parsed submodule structure.
3664 *
3665 * @return LY_ERR values.
3666 */
David Sedlák3b4db242018-10-19 16:11:01 +02003667LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003668yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003669{
David Sedlák81497a32019-08-13 16:56:26 +02003670 LY_ERR ret = LY_SUCCESS;
3671 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003672 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003673 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003674
Michal Vaskoc3781c32020-10-06 14:04:08 +02003675 submod->is_submod = 1;
3676
Michal Vaskob36053d2020-03-26 15:49:30 +01003677 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3678 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 +01003679 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003680 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3681 LY_STMT_ANYXML, &submod->data, 0,
3682 LY_STMT_AUGMENT, &submod->augments, 0,
3683 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3684 LY_STMT_CHOICE, &submod->data, 0,
3685 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3686 LY_STMT_CONTAINER, &submod->data, 0,
3687 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3688 LY_STMT_DEVIATION, &submod->deviations, 0,
3689 LY_STMT_EXTENSION, &submod->extensions, 0,
3690 LY_STMT_FEATURE, &submod->features, 0,
3691 LY_STMT_GROUPING, &submod->groupings, 0,
3692 LY_STMT_IDENTITY, &submod->identities, 0,
3693 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3694 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3695 LY_STMT_LEAF, &submod->data, 0,
3696 LY_STMT_LEAF_LIST, &submod->data, 0,
3697 LY_STMT_LIST, &submod->data, 0,
3698 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3699 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3700 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3701 LY_STMT_REVISION, &submod->revs, 0,
3702 LY_STMT_RPC, &submod->rpcs, 0,
3703 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3704 LY_STMT_USES, &submod->data, 0,
3705 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3706 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003707
Radek Krejcif13b87b2020-12-01 22:02:17 +01003708 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3709 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003710 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003711
David Sedláked809f12019-09-13 10:15:11 +02003712 /* submodules share the namespace with the module names, so there must not be
3713 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003714 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003715 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003716 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003717 return LY_EVALID;
3718 }
3719
3720 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003721}
3722
3723LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003724yin_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 +02003725 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003726{
Radek Krejcid6b76452019-09-03 17:03:03 +02003727 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003728 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003729 struct lysp_submodule *mod_p = NULL;
3730
aPiecek56be92a2021-07-01 07:18:10 +02003731 assert(yin_ctx && ctx && main_ctx && in && submod);
3732
David Sedlák8985a142019-07-31 16:43:06 +02003733 /* create context */
3734 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003735 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003736 (*yin_ctx)->format = LYS_IN_YIN;
aPiecek56be92a2021-07-01 07:18:10 +02003737 (*yin_ctx)->main_ctx = main_ctx;
Michal Vasko63f3d842020-07-08 10:10:14 +02003738 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003739
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003740 mod_p = calloc(1, sizeof *mod_p);
3741 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01003742 mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003743 mod_p->parsing = 1;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003744
3745 /* use main context parsed mods adding the current one */
3746 (*yin_ctx)->parsed_mods = main_ctx->parsed_mods;
3747 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003748
David Sedlák8985a142019-07-31 16:43:06 +02003749 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003750 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 +02003751 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003752 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003753 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3754 ret = LY_EINVAL;
3755 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003756 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003757 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003758 ret = LY_EVALID;
3759 goto cleanup;
3760 }
3761
Michal Vaskob36053d2020-03-26 15:49:30 +01003762 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003763 LY_CHECK_GOTO(ret, cleanup);
3764
David Sedlákbf8a2b72019-08-14 16:48:10 +02003765 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003766 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003767 if (in->current[0] == '\n') {
3768 LY_IN_NEW_LINE(in);
3769 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003770 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003771 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003772 if (in->current[0]) {
3773 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003774 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003775 ret = LY_EVALID;
3776 goto cleanup;
3777 }
3778
David Sedlák8985a142019-07-31 16:43:06 +02003779 mod_p->parsing = 0;
3780 *submod = mod_p;
3781
3782cleanup:
3783 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003784 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003785 yin_parser_ctx_free(*yin_ctx);
3786 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003787 }
David Sedlák8985a142019-07-31 16:43:06 +02003788 return ret;
3789}
3790
3791LY_ERR
aPiecekc3e26142021-06-22 14:25:49 +02003792yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003793{
David Sedláke4889912018-11-02 09:52:40 +01003794 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003795 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003796 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003797
David Sedlák8985a142019-07-31 16:43:06 +02003798 /* create context */
3799 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003800 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003801 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003802 LY_CHECK_ERR_RET(ly_set_new(&(*yin_ctx)->parsed_mods), free(*yin_ctx); LOGMEM(mod->ctx), LY_EMEM);
Michal Vasko63f3d842020-07-08 10:10:14 +02003803 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
aPiecek8d4e75d2021-06-24 14:47:06 +02003804 (*yin_ctx)->main_ctx = (struct lys_parser_ctx *)(*yin_ctx);
David Sedlákda8ffa32019-07-08 14:17:10 +02003805
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003806 mod_p = calloc(1, sizeof *mod_p);
3807 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3808 mod_p->mod = mod;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003809 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003810
David Sedlák8985a142019-07-31 16:43:06 +02003811 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003812 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 +02003813 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003814 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003815 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 +01003816 ret = LY_EINVAL;
3817 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003818 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003819 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003820 ret = LY_EVALID;
3821 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003822 }
3823
David Sedlák00250342019-06-21 14:19:39 +02003824 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003825 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003826 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003827
David Sedlákbf8a2b72019-08-14 16:48:10 +02003828 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003829 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003830 if (in->current[0] == '\n') {
3831 LY_IN_NEW_LINE(in);
3832 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003833 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003834 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003835 if (in->current[0]) {
3836 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003837 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003838 ret = LY_EVALID;
3839 goto cleanup;
3840 }
3841
David Sedlák3017da42019-02-15 09:48:04 +01003842 mod->parsed = mod_p;
3843
3844cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003845 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003846 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003847 yin_parser_ctx_free(*yin_ctx);
3848 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003849 }
David Sedlák2e411422018-12-17 02:35:39 +01003850 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003851}