blob: 889d2c362a76f3364dac34f151f6e7ea9f774812 [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;
358 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200359 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200360 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200361 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200362 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200363 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200364 struct import_meta *imp_meta = NULL;
365 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200366 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200367 imp_meta->prefix = va_arg(ap, const char *);
368 imp_meta->imports = va_arg(ap, struct lysp_import **);
369 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200370 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200371 struct include_meta *inc_meta = NULL;
372 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200373 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200374 inc_meta->name = va_arg(ap, const char *);
375 inc_meta->includes = va_arg(ap, struct lysp_include **);
376 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200377 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200378 struct inout_meta *inout_meta = NULL;
379 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200380 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200381 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100382 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200383 (*result)[i].dest = inout_meta;
384 } else {
385 (*result)[i].dest = va_arg(ap, void *);
386 }
387 /* FLAGS */
388 (*result)[i].flags = va_arg(ap, int);
389 }
390 va_end(ap);
391
392 return LY_SUCCESS;
393
David Sedlákbf8a2b72019-08-14 16:48:10 +0200394mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200395 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100396 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200397 return LY_EMEM;
398}
399
Michal Vaskoafac7822020-10-20 14:22:26 +0200400/**
401 * @brief Check that val is valid UTF8 character sequence of val_type.
402 * Doesn't check empty string, only character validity.
403 *
404 * @param[in] ctx Yin parser context for logging.
405 * @param[in] val_type Type of the input string to select method of checking character validity.
406 *
407 * @return LY_ERR values.
408 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200409LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100410yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200411{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200412 uint8_t prefix = 0;
413 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100414 size_t utf8_char_len, already_read = 0;
415 const char *val;
416
417 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
418
419 val = ctx->xmlctx->value;
420 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200421 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200422 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200423
424 switch (val_type) {
425 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200426 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 +0200427 break;
428 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200429 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 +0200430 break;
431 case Y_STR_ARG:
432 case Y_MAYBE_STR_ARG:
433 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
434 break;
435 }
Radek Iša2eac74c2021-03-15 15:53:08 +0100436
437 already_read += utf8_char_len;
438 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200439 }
440
Radek Iša42cc0b72021-03-15 16:51:31 +0100441 if ((already_read == 0) &&
442 ((val_type == Y_PREF_IDENTIF_ARG) || (val_type == Y_IDENTIF_ARG))) {
443 /* Empty identifier or prefix*/
444 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Empty identifier is not allowed.");
445 return LY_EVALID;
446 }
447
David Sedlák4a650532019-07-10 11:55:18 +0200448 return LY_SUCCESS;
449}
450
David Sedlákb4e44562019-07-04 15:42:12 +0200451/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100452 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200453 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200454 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200455 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
456 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200457 * @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 +0200458 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200459 * @param[in] current_element Identification of current element, used for logging.
460 *
461 * @return LY_ERR values.
462 */
463static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100464yin_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 +0200465 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200466{
David Sedlákc5b20842019-08-13 10:18:31 +0200467 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200468 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200469
David Sedlák1bccdfa2019-06-17 15:55:27 +0200470 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100471 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200472 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100473 if (!ctx->xmlctx->prefix) {
474 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200475 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100476 /* skip it */
477 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200478 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200479 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200480 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200481 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100482
483 /* go to value */
484 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
485 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200486 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 +0200487 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200488 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100489 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200490 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200491 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200492 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100493 } else {
494 /* skip it */
495 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200496 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100497
498 /* next attribute */
499 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200500 }
501
David Sedlák292763b2019-07-09 11:10:53 +0200502 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200503 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100504 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200505 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200506 return LY_EVALID;
507 }
508
509 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200510}
511
David Sedlákd6e56892019-07-01 15:40:24 +0200512/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200513 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200514 *
515 * @param[in] type Type of wanted record.
516 * @param[in] array_size Size of array.
517 * @param[in] array Searched array.
518 *
519 * @return Pointer to desired record on success, NULL if element is not in the array.
520 */
David Sedlákb4e44562019-07-04 15:42:12 +0200521static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200522get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200523{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200524 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200525 if (array[u].type == type) {
526 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200527 }
528 }
David Sedlákd6e56892019-07-01 15:40:24 +0200529 return NULL;
530}
531
David Sedlákbba38e52019-07-09 15:20:01 +0200532/**
533 * @brief Helper function to check mandatory constraint of subelement.
534 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200535 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200536 * @param[in] subelem_info Array of information about subelements.
537 * @param[in] subelem_info_size Size of subelem_info array.
538 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
539 *
540 * @return LY_ERR values.
541 */
542static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100543yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200544 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200545{
David Sedlákb0faad82019-07-04 14:28:59 +0200546 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200547 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200548 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200549 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200550 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200551 return LY_EVALID;
552 }
553 }
554
555 return LY_SUCCESS;
556}
557
David Sedlákbba38e52019-07-09 15:20:01 +0200558/**
559 * @brief Helper function to check "first" constraint of subelement.
560 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200561 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200562 * @param[in] subelem_info Array of information about subelements.
563 * @param[in] subelem_info_size Size of subelem_info array.
564 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200565 * @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 +0200566 *
567 * @return LY_ERR values.
568 */
569static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100570yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200571 signed char subelem_info_size, enum ly_stmt current_element,
572 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200573{
David Sedlákb0faad82019-07-04 14:28:59 +0200574 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200575 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200576 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200577 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200578 return LY_EVALID;
579 }
580 }
581
582 return LY_SUCCESS;
583}
584
David Sedlákbba38e52019-07-09 15:20:01 +0200585/**
David Sedlákb4e44562019-07-04 15:42:12 +0200586 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
587 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200588 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200589 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200590 * @param[in] kw Type of current element.
591 * @param[out] value Where value of attribute should be stored.
592 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200593 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200594 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200595 * @return LY_ERR values.
596 */
David Sedlákb4e44562019-07-04 15:42:12 +0200597static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100598yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200599 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200600{
Michal Vaskob36053d2020-03-26 15:49:30 +0100601 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
602 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100603 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200604 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
605 };
David Sedlákb4e44562019-07-04 15:42:12 +0200606
Radek Krejcif13b87b2020-12-01 22:02:17 +0100607 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200608}
609
610/**
David Sedlák6542aed2019-08-14 10:47:43 +0200611 * @brief Parse path element.
612 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200613 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200614 * @param[in] kw Type of current element.
615 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200616 * @return LY_ERR values.
617 */
618static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100619yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200620{
Michal Vasko004d3152020-06-11 19:59:22 +0200621 LY_ERR ret;
622 const char *str_path;
623
624 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
Michal Vasko6b26e742020-07-17 15:02:10 +0200625 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +0200626 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200627 lydict_remove(ctx->xmlctx->ctx, str_path);
628 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200629 type->flags |= LYS_SET_PATH;
630
631 return LY_SUCCESS;
632}
633
634/**
David Sedlákd3983112019-07-12 11:20:56 +0200635 * @brief Parse pattern element.
636 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200637 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200638 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200639 * @return LY_ERR values.
640 */
641static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100642yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200643{
644 const char *real_value = NULL;
645 char *saved_value = NULL;
646 struct lysp_restr *restr;
647
Michal Vaskob36053d2020-03-26 15:49:30 +0100648 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
649 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
650 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 +0200651 size_t len = strlen(real_value);
652
653 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100654 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200655 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100656 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100657 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200658 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200659 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200660 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200661 type->flags |= LYS_SET_PATTERN;
662
Radek Krejcif13b87b2020-12-01 22:02:17 +0100663 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200664 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
665 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
666 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
667 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
668 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
669 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
670 };
Michal Vasko69730152020-10-09 16:30:07 +0200671
Radek Krejcif13b87b2020-12-01 22:02:17 +0100672 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200673}
674
David Sedlákc5b20842019-08-13 10:18:31 +0200675/**
676 * @brief Parse fraction-digits element.
677 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200678 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200679 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200680 * @return LY_ERR values.
681 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200682static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100683yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200684{
685 const char *temp_val = NULL;
686 char *ptr;
687 unsigned long int num;
688
Michal Vaskob36053d2020-03-26 15:49:30 +0100689 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
690 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 +0200691
Michal Vasko69730152020-10-09 16:30:07 +0200692 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200693 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100694 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200695 return LY_EVALID;
696 }
697
698 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100699 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200700 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200701 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100702 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200703 return LY_EVALID;
704 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100705 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200706 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100707 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200708 return LY_EVALID;
709 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100710 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200711 type->fraction_digits = num;
712 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100713 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200714 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
715 };
Michal Vasko69730152020-10-09 16:30:07 +0200716
Radek Krejcif13b87b2020-12-01 22:02:17 +0100717 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200718}
719
David Sedlák07869a52019-07-12 14:28:19 +0200720/**
David Sedlák43801c92019-08-05 15:58:54 +0200721 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200722 *
723 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200724 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200725 * @return LY_ERR values.
726 */
David Sedlákca36c422019-07-12 12:47:55 +0200727static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100728yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200729{
David Sedlák07869a52019-07-12 14:28:19 +0200730 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200731
Michal Vaskob36053d2020-03-26 15:49:30 +0100732 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200733 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100734 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
735 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 +0200736 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100737 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200738 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200739
Radek Krejcif13b87b2020-12-01 22:02:17 +0100740 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200741 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
742 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
743 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
744 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
745 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
746 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
747 };
Michal Vasko69730152020-10-09 16:30:07 +0200748
Radek Krejcif13b87b2020-12-01 22:02:17 +0100749 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200750}
751
752/**
753 * @brief Parse bit element.
754 *
755 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200756 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200757 * @return LY_ERR values.
758 */
759static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100760yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200761{
762 struct lysp_type_enum *en;
763
Michal Vaskob36053d2020-03-26 15:49:30 +0100764 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200765 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100766 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
767 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 +0100768 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->bits, name, "bit", en->name);
David Sedlák43801c92019-08-05 15:58:54 +0200769
Radek Krejcif13b87b2020-12-01 22:02:17 +0100770 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200771 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
772 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
773 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
774 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
775 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
776 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
777 };
Michal Vasko69730152020-10-09 16:30:07 +0200778
Radek Krejcif13b87b2020-12-01 22:02:17 +0100779 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200780}
781
David Sedlákd3983112019-07-12 11:20:56 +0200782/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200783 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
784 * more instances, such as base or if-feature.
785 *
786 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200787 * @param[in] kw Type of current element.
788 * @param[out] values Parsed values to add to.
789 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200790 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200791 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200792 * @return LY_ERR values.
793 */
794static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100795yin_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 +0200796 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200797{
798 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200799
Michal Vaskob36053d2020-03-26 15:49:30 +0100800 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200801 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100802 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200803 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
804 };
David Sedlák968ac342019-07-11 15:17:59 +0200805
Michal Vaskob36053d2020-03-26 15:49:30 +0100806 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
807 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200808
Radek Krejcif13b87b2020-12-01 22:02:17 +0100809 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200810}
811
812/**
David Sedlák6542aed2019-08-14 10:47:43 +0200813 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
814 *
815 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200816 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200817 * @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 +0200818 * @param[in] arg_type Expected type of attribute.
819 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200820 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200821 * @return LY_ERR values.
822 */
823static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100824yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200825 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200826{
827 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100828 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200829 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200830 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100831 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200832 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200833 }
834
835 return LY_SUCCESS;
836}
837
838/**
839 * @brief Parse base element.
840 *
841 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200842 * @param[in] parent Identification of parent element.
843 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200844 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200845 * @return LY_ERR values.
846 */
847static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100848yin_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 +0200849{
850 struct lysp_type *type = NULL;
851
Radek Krejcid6b76452019-09-03 17:03:03 +0200852 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200853 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100854 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200855 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200856 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200857 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100858 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200859 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200860 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100861 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200862 return LY_EINT;
863 }
864
865 return LY_SUCCESS;
866}
867
868/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200869 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200870 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200871 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100872 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200873 * @return LY_ERR values.
874 */
875static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100876yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200877{
878 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100879 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200880 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
881 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200882
883 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100884 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
885 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 +0200886 if (strcmp(temp_val, "true") == 0) {
887 type->require_instance = 1;
888 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200889 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200890 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100891 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200892 return LY_EVALID;
893 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100894 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200895
Radek Krejcif13b87b2020-12-01 22:02:17 +0100896 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200897}
898
899/**
David Sedlákce77bf52019-07-11 16:59:31 +0200900 * @brief Parse modifier element.
901 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200902 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200903 * @param[in,out] pat Value to write to.
904 * @param[in,out] exts Extension instances to add to.
905 *
906 * @return LY_ERR values.
907 */
908static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100909yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200910{
David Sedlákd3983112019-07-12 11:20:56 +0200911 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200912 const char *temp_val;
913 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100914 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200915 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
916 };
David Sedlákce77bf52019-07-11 16:59:31 +0200917
Michal Vaskob36053d2020-03-26 15:49:30 +0100918 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
919 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 +0200920 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200921 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200922 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100923 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200924 return LY_EVALID;
925 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100926 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200927
928 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200929 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100930 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200931 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100932 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200933
934 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100935 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200936 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200937
Radek Krejcif13b87b2020-12-01 22:02:17 +0100938 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200939}
940
941/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200942 * @brief Parse a restriction element (length, range or one instance of must).
943 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200944 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200945 * @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 +0200946 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200947 */
948static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100949yin_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 +0200950{
Radek Krejcid6b76452019-09-03 17:03:03 +0200951 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100952 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200953 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
954 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
955 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
956 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
957 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
958 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200959 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200960 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200961
Michal Vaskob36053d2020-03-26 15:49:30 +0100962 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200963 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200964 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100965
Radek Krejcif13b87b2020-12-01 22:02:17 +0100966 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200967}
968
969/**
David Sedlák6542aed2019-08-14 10:47:43 +0200970 * @brief Parse range element.
971 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200972 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200973 * @param[out] type Type structure to store parsed value and flags.
974 *
975 * @return LY_ERR values.
976 */
977static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100978yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200979{
980 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100981 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
982 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200983 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200984
985 return LY_SUCCESS;
986}
987
988/**
989 * @brief Parse length element.
990 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200991 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200992 * @param[out] type Type structure to store parsed value and flags.
993 *
994 * @return LY_ERR values.
995 */
996static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100997yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200998{
999 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001000 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1001 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +02001002 type->flags |= LYS_SET_LENGTH;
1003
1004 return LY_SUCCESS;
1005}
1006
1007/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001008 * @brief Parse must element.
1009 *
1010 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001011 * @param[in,out] restrs Restrictions to add to.
1012 *
1013 * @return LY_ERR values.
1014 */
1015static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001016yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001017{
1018 struct lysp_restr *restr;
1019
Michal Vaskob36053d2020-03-26 15:49:30 +01001020 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1021 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001022}
1023
1024/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001025 * @brief Parse a node id into an array.
1026 *
1027 * @param[in,out] ctx YIN parser context for logging and to store current state.
1028 * @param[in] kw Type of current element.
1029 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1030 * @param[in,out] exts Extension instances to add to.
1031 *
1032 * @return LY_ERR values.
1033 */
1034static LY_ERR
1035yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1036 struct lysp_ext_instance **exts)
1037{
1038 struct lysp_qname *qname, **qnames;
1039
1040 switch (kw) {
1041 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001042 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1043 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001044 } else {
1045 qnames = (struct lysp_qname **)subinfo->dest;
1046 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001047 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001048 qname->mod = ctx->parsed_mod;
1049 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
Radek Išabe8a6532021-03-29 08:54:22 +02001050 case LY_STMT_UNIQUE:
1051 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1052 qnames = (struct lysp_qname **)subinfo->dest;
1053 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1054 qname->mod = ctx->parsed_mod;
1055 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001056 case LY_STMT_IF_FEATURE:
1057 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1058 qnames = (struct lysp_qname **)subinfo->dest;
1059 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1060 qname->mod = ctx->parsed_mod;
1061 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001062 default:
1063 break;
1064 }
1065
1066 LOGINT(ctx->xmlctx->ctx);
1067 return LY_EINT;
1068}
1069
1070/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001071 * @brief Parse position or value element.
1072 *
1073 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001074 * @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 +02001075 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001076 *
1077 * @return LY_ERR values.
1078 */
1079static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001080yin_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 +02001081{
Radek Krejcid6b76452019-09-03 17:03:03 +02001082 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001083 const char *temp_val = NULL;
1084 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +02001085 long int num = 0;
1086 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001087
1088 /* set value flag */
1089 enm->flags |= LYS_SET_VALUE;
1090
1091 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001092 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1093 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001094 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001095 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001096 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 +02001097 goto error;
1098 }
1099
1100 /* convert value */
1101 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001102 if (kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001103 num = strtol(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001104 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001105 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 +02001106 goto error;
1107 }
1108 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001109 unum = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001110 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001111 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 +02001112 goto error;
1113 }
1114 }
1115 /* check if whole argument value was converted */
1116 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001117 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 +02001118 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001119 }
1120 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001121 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 +02001122 goto error;
1123 }
1124 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001125 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001126 enm->value = num;
1127 } else {
1128 enm->value = unum;
1129 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001130 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001131
1132 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001133 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001134 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1135 };
Michal Vasko69730152020-10-09 16:30:07 +02001136
Radek Krejcif13b87b2020-12-01 22:02:17 +01001137 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001138
David Sedlákbf8a2b72019-08-14 16:48:10 +02001139error:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001140 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskob36053d2020-03-26 15:49:30 +01001141 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001142}
1143
David Sedlák05404f62019-07-24 14:11:53 +02001144/**
1145 * @brief Parse belongs-to element.
1146 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001147 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001148 * @param[out] submod Structure of submodule that is being parsed.
1149 * @param[in,out] exts Extension instances to add to.
1150 *
1151 * @return LY_ERR values
1152 */
1153static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001154yin_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 +02001155{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001156 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001157 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001158 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1159 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1160 };
David Sedlák05404f62019-07-24 14:11:53 +02001161
Michal Vaskob36053d2020-03-26 15:49:30 +01001162 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001163 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001164 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001165 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001166 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001167 lydict_remove(ctx->xmlctx->ctx, belongsto);
1168 return LY_EVALID;
1169 }
1170 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001171
Radek Krejcif13b87b2020-12-01 22:02:17 +01001172 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001173}
1174
David Sedlák5545f5d2019-07-11 11:55:16 +02001175/**
David Sedlákc1771b12019-07-10 15:55:46 +02001176 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001177 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001178 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001179 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001180 * @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 +02001181 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001182 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001183 *
1184 * @return LY_ERR values.
1185 */
1186static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001187yin_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 +02001188{
Radek Krejcid6b76452019-09-03 17:03:03 +02001189 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 +02001190
Radek Krejcif13b87b2020-12-01 22:02:17 +01001191 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001192 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1193 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1194 };
Michal Vasko69730152020-10-09 16:30:07 +02001195
David Sedlákdf2a9732019-08-07 13:23:16 +02001196 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001197 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1198 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 +02001199
David Sedlákdf2a9732019-08-07 13:23:16 +02001200 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001201 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001202}
1203
1204/**
David Sedlákc1771b12019-07-10 15:55:46 +02001205 * @brief Parse error-message element.
1206 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001207 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001208 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001209 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001210 *
1211 * @return LY_ERR values.
1212 */
1213static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001214yin_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 +02001215{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001216 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001217 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1218 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1219 };
David Sedlákc1771b12019-07-10 15:55:46 +02001220
David Sedlákdf2a9732019-08-07 13:23:16 +02001221 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001222 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1223 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 +02001224
Radek Krejcif13b87b2020-12-01 22:02:17 +01001225 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001226}
1227
1228/**
David Sedlák6542aed2019-08-14 10:47:43 +02001229 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001230 *
1231 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001232 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001233 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001234 *
1235 * @return LY_ERR values.
1236 */
1237static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001238yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001239{
David Sedlák6542aed2019-08-14 10:47:43 +02001240 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001241
Radek Krejcid6b76452019-09-03 17:03:03 +02001242 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001243 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001244 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001245 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001246 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001247 type = (struct lysp_type *)subinfo->dest;
1248 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001249
David Sedlák6542aed2019-08-14 10:47:43 +02001250 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001251 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001252 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001253 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001254 type->flags |= LYS_SET_TYPE;
1255 type = nested_type;
1256 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001257
Michal Vasko5bbcc242021-02-23 09:29:13 +01001258 type->pmod = ctx->parsed_mod;
1259
Radek Krejcif13b87b2020-12-01 22:02:17 +01001260 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001261 {LY_STMT_BASE, type, 0},
1262 {LY_STMT_BIT, type, 0},
1263 {LY_STMT_ENUM, type, 0},
1264 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1265 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1266 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1267 {LY_STMT_PATTERN, type, 0},
1268 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1269 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1270 {LY_STMT_TYPE, type},
1271 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1272 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001273
1274 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1275 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 +01001276 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001277}
1278
David Sedlák1af868e2019-07-17 17:03:14 +02001279/**
1280 * @brief Parse max-elements element.
1281 *
1282 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001283 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001284 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001285 * @param[in,out] exts Extension instances to add to.
1286 *
1287 * @return LY_ERR values.
1288 */
1289static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001290yin_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 +02001291{
1292 const char *temp_val = NULL;
1293 char *ptr;
1294 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001295 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001296 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1297 };
David Sedlák374d2b32019-07-17 15:06:55 +02001298
David Sedlák1af868e2019-07-17 17:03:14 +02001299 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001300 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1301 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 +02001302 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 +02001303 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001304 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001305 return LY_EVALID;
1306 }
1307
1308 if (strcmp(temp_val, "unbounded")) {
1309 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001310 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001311 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001312 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001313 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001314 return LY_EVALID;
1315 }
1316 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001317 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_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 *max = num;
1322 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001323 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001324 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001325}
David Sedlák374d2b32019-07-17 15:06:55 +02001326
1327/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001328 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001329 *
1330 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001331 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001332 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001333 * @param[in,out] exts Extension instances to add to.
1334 *
1335 * @return LY_ERR values.
1336 */
1337static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001338yin_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 +02001339{
1340 const char *temp_val = NULL;
1341 char *ptr;
1342 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001343 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001344 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1345 };
David Sedlák09e18c92019-07-18 11:17:11 +02001346
1347 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001348 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1349 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 +02001350
Michal Vasko69730152020-10-09 16:30:07 +02001351 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001352 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001353 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001354 return LY_EVALID;
1355 }
1356
1357 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001358 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001359 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001360 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001361 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001362 return LY_EVALID;
1363 }
Michal Vasko69730152020-10-09 16:30:07 +02001364 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001365 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_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 }
1369 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001370 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001371 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001372}
1373
David Sedláka2dad212019-07-18 12:45:19 +02001374/**
1375 * @brief Parse min-elements or max-elements element.
1376 *
1377 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001378 * @param[in] parent Identification of parent element.
1379 * @param[in] current Identification of current element.
1380 * @param[in] dest Where the parsed value and flags should be stored.
1381 *
1382 * @return LY_ERR values.
1383 */
David Sedlák09e18c92019-07-18 11:17:11 +02001384static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001385yin_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 +02001386{
Radek Krejcid6b76452019-09-03 17:03:03 +02001387 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1388 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 +02001389 uint32_t *lim;
1390 uint16_t *flags;
1391 struct lysp_ext_instance **exts;
1392
Radek Krejcid6b76452019-09-03 17:03:03 +02001393 if (parent == LY_STMT_LEAF_LIST) {
1394 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 +02001395 flags = &((struct lysp_node_leaflist *)dest)->flags;
1396 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001397 } else if (parent == LY_STMT_REFINE) {
1398 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001399 flags = &((struct lysp_refine *)dest)->flags;
1400 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001401 } else if (parent == LY_STMT_LIST) {
1402 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 +02001403 flags = &((struct lysp_node_list *)dest)->flags;
1404 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001405 } else {
1406 lim = ((struct minmax_dev_meta *)dest)->lim;
1407 flags = ((struct minmax_dev_meta *)dest)->flags;
1408 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001409 }
1410
Radek Krejcid6b76452019-09-03 17:03:03 +02001411 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001412 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001413 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001414 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001415 }
1416
1417 return LY_SUCCESS;
1418}
1419
1420/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001421 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001422 *
1423 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001424 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001425 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001426 *
1427 * @return LY_ERR values.
1428 */
1429static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001430yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001431{
1432 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001433 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001434 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1435 };
David Sedláka2dad212019-07-18 12:45:19 +02001436
Michal Vaskob36053d2020-03-26 15:49:30 +01001437 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1438 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 +02001439 if (strcmp(temp_val, "system") == 0) {
1440 *flags |= LYS_ORDBY_SYSTEM;
1441 } else if (strcmp(temp_val, "user") == 0) {
1442 *flags |= LYS_ORDBY_USER;
1443 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001444 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001445 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001446 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001447 return LY_EVALID;
1448 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001449 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001450
Radek Krejcif13b87b2020-12-01 22:02:17 +01001451 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001452}
1453
1454/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001455 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001456 *
1457 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001458 * @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 +02001459 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001460 *
1461 * @return LY_ERR values.
1462 */
1463static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001464yin_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 +02001465{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001466 struct lysp_node_anydata *any;
1467
David Sedlák8d552d62019-08-06 15:29:05 +02001468 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001469 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001470 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001471 any->parent = node_meta->parent;
1472
David Sedlákbf8a2b72019-08-14 16:48:10 +02001473 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001474 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1475 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 +02001476
Radek Krejcif13b87b2020-12-01 22:02:17 +01001477 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001478 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1479 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1480 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1481 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1482 {LY_STMT_MUST, &any->musts, 0},
1483 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1484 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1485 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1486 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1487 };
Michal Vasko69730152020-10-09 16:30:07 +02001488
Radek Krejcif13b87b2020-12-01 22:02:17 +01001489 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001490}
1491
1492/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001493 * @brief parse leaf element.
1494 *
1495 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001496 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001497 *
1498 * @return LY_ERR values.
1499 */
1500static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001501yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001502{
David Sedlák203ca3a2019-07-18 15:26:25 +02001503 struct lysp_node_leaf *leaf;
1504
David Sedlák8d552d62019-08-06 15:29:05 +02001505 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001506 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001507 leaf->nodetype = LYS_LEAF;
1508 leaf->parent = node_meta->parent;
1509
David Sedlák203ca3a2019-07-18 15:26:25 +02001510 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001511 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1512 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 +02001513
1514 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001515 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001516 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1517 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1518 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1519 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1520 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1521 {LY_STMT_MUST, &leaf->musts, 0},
1522 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1523 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1524 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1525 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1526 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1527 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1528 };
Michal Vasko69730152020-10-09 16:30:07 +02001529
Radek Krejcif13b87b2020-12-01 22:02:17 +01001530 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001531}
1532
1533/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001534 * @brief Parse leaf-list element.
1535 *
1536 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001537 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001538 *
1539 * @return LY_ERR values.
1540 */
1541static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001542yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001543{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001544 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001545
Michal Vaskob36053d2020-03-26 15:49:30 +01001546 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001547
David Sedlákc3da3ef2019-07-19 12:56:08 +02001548 llist->nodetype = LYS_LEAFLIST;
1549 llist->parent = node_meta->parent;
1550
David Sedlákc3da3ef2019-07-19 12:56:08 +02001551 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001552 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1553 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 +02001554
1555 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001556 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001557 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1558 {LY_STMT_DEFAULT, &llist->dflts, 0},
1559 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1560 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1561 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1562 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1563 {LY_STMT_MUST, &llist->musts, 0},
1564 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1565 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1566 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1567 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1568 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1569 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1570 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1571 };
Michal Vasko69730152020-10-09 16:30:07 +02001572
Radek Krejcif13b87b2020-12-01 22:02:17 +01001573 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 +02001574
David Sedlákbf8a2b72019-08-14 16:48:10 +02001575 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001576 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001577 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001578 return LY_EVALID;
1579 }
Michal Vasko69730152020-10-09 16:30:07 +02001580 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001581 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001582 return LY_EVALID;
1583 }
1584
1585 return LY_SUCCESS;
1586}
1587
1588/**
David Sedlák04e17b22019-07-19 15:29:48 +02001589 * @brief Parse typedef element.
1590 *
1591 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001592 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001593 *
1594 * @return LY_ERR values.
1595 */
1596static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001597yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001598{
1599 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001600 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001601
Michal Vaskob36053d2020-03-26 15:49:30 +01001602 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001603
1604 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001605 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1606 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 +02001607
1608 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001609 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001610 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1611 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1612 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1613 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1614 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1615 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1616 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1617 };
Michal Vasko69730152020-10-09 16:30:07 +02001618
Radek Krejcif13b87b2020-12-01 22:02:17 +01001619 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 +02001620
1621 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001622 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1623 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001624 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001625 }
1626
1627 return LY_SUCCESS;
1628}
1629
1630/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001631 * @brief Parse refine element.
1632 *
1633 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001634 * @param[in,out] refines Refines to add to.
1635 *
1636 * @return LY_ERR values.
1637 */
1638static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001639yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001640{
1641 struct lysp_refine *rf;
1642
1643 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001644 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001645
1646 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001647 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1648 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1649 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001650
1651 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001652 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001653 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001654 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001655 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001656 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001657 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1658 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1659 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1660 {LY_STMT_MUST, &rf->musts, 0},
1661 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1662 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1663 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1664 };
Michal Vasko69730152020-10-09 16:30:07 +02001665
Radek Krejcif13b87b2020-12-01 22:02:17 +01001666 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001667}
1668
1669/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001670 * @brief Parse uses element.
1671 *
1672 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001673 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001674 *
1675 * @return LY_ERR values.
1676 */
1677static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001678yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001679{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001680 struct lysp_node_uses *uses;
1681
David Sedlák8d552d62019-08-06 15:29:05 +02001682 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001683 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001684 uses->nodetype = LYS_USES;
1685 uses->parent = node_meta->parent;
1686
David Sedlák0d6de5a2019-07-22 13:25:44 +02001687 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001688 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1689 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 +02001690
1691 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001692 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001693 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001694 {LY_STMT_AUGMENT, &augments, 0},
1695 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1696 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1697 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1698 {LY_STMT_REFINE, &uses->refines, 0},
1699 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1700 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1701 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1702 };
Michal Vasko69730152020-10-09 16:30:07 +02001703
Radek Krejcif13b87b2020-12-01 22:02:17 +01001704 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 +02001705
1706 return LY_SUCCESS;
1707}
1708
1709/**
David Sedlákaa854b02019-07-22 14:17:10 +02001710 * @brief Parse revision element.
1711 *
1712 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001713 * @param[in,out] revs Parsed revisions to add to.
1714 *
1715 * @return LY_ERR values.
1716 */
1717static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001718yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001719{
1720 struct lysp_revision *rev;
1721 const char *temp_date = NULL;
1722
1723 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001724 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001725
1726 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001727 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1728 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 +02001729 /* check value */
1730 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001731 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001732 return LY_EVALID;
1733 }
Radek Krejci36642162021-01-12 16:49:22 +01001734 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001735 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001736
1737 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001738 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001739 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1740 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1741 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1742 };
Michal Vasko69730152020-10-09 16:30:07 +02001743
Radek Krejcif13b87b2020-12-01 22:02:17 +01001744 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001745}
1746
David Sedlák5e13dea2019-07-22 16:06:45 +02001747/**
1748 * @brief Parse include element.
1749 *
1750 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001751 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1752 *
1753 * @return LY_ERR values.
1754 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001755static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001756yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001757{
1758 struct lysp_include *inc;
1759
1760 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001761 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001762
1763 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001764 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1765 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 +02001766
1767 /* submodules share the namespace with the module names, so there must not be
1768 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001769 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001770 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001771 return LY_EVALID;
1772 }
1773
1774 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001775 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001776 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1777 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1778 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1779 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1780 };
Michal Vasko69730152020-10-09 16:30:07 +02001781
Radek Krejcif13b87b2020-12-01 22:02:17 +01001782 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001783}
1784
David Sedlákaa854b02019-07-22 14:17:10 +02001785/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001786 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001787 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001788 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001789 * @param[in,out] rev Array to store the parsed value in.
1790 * @param[in,out] exts Extension instances to add to.
1791 *
1792 * @return LY_ERR values.
1793 */
1794static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001795yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001796{
1797 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001798 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001799 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1800 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001801
Michal Vaskob36053d2020-03-26 15:49:30 +01001802 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1803 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 +02001804 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 +01001805 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001806
1807 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001808 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001809
Radek Krejcif13b87b2020-12-01 22:02:17 +01001810 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001811}
1812
1813/**
1814 * @brief Parse config element.
1815 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001816 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001817 * @param[in,out] flags Flags to add to.
1818 * @param[in,out] exts Extension instances to add to.
1819 *
1820 * @return LY_ERR values.
1821 */
1822static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001823yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001824{
1825 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001826 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001827 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1828 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001829
Michal Vaskob36053d2020-03-26 15:49:30 +01001830 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1831 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 +02001832 if (strcmp(temp_val, "true") == 0) {
1833 *flags |= LYS_CONFIG_W;
1834 } else if (strcmp(temp_val, "false") == 0) {
1835 *flags |= LYS_CONFIG_R;
1836 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001837 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001838 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001839 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001840 return LY_EVALID;
1841 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001842 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001843
Radek Krejcif13b87b2020-12-01 22:02:17 +01001844 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001845}
1846
1847/**
1848 * @brief Parse yang-version element.
1849 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001850 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001851 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001852 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001853 *
1854 * @return LY_ERR values.
1855 */
1856static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001857yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001858{
1859 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001860 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001861 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1862 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001863
Michal Vaskob36053d2020-03-26 15:49:30 +01001864 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1865 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 +02001866 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001867 *version = LYS_VERSION_1_0;
1868 } else if (strcmp(temp_version, "1.1") == 0) {
1869 *version = LYS_VERSION_1_1;
1870 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001871 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001872 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001873 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001874 return LY_EVALID;
1875 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001876 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001877
Radek Krejcif13b87b2020-12-01 22:02:17 +01001878 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001879}
1880
1881/**
1882 * @brief Parse import element.
1883 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001884 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001885 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1886 *
1887 * @return LY_ERR values.
1888 */
1889static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001890yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001891{
1892 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001893
David Sedlákdfbbb442019-08-06 16:33:21 +02001894 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001895 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001896
Radek Krejcif13b87b2020-12-01 22:02:17 +01001897 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001898 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1899 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1900 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1901 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1902 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1903 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001904
1905 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001906 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1907 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 +01001908 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 +02001909 /* check prefix validity */
1910 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1911
1912 return LY_SUCCESS;
1913}
1914
1915/**
1916 * @brief Parse mandatory element.
1917 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001918 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001919 * @param[in,out] flags Flags to add to.
1920 * @param[in,out] exts Extension instances to add to.
1921 *
1922 * @return LY_ERR values.
1923 */
1924static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001925yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001926{
1927 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001928 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001929 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1930 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001931
Michal Vaskob36053d2020-03-26 15:49:30 +01001932 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1933 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 +02001934 if (strcmp(temp_val, "true") == 0) {
1935 *flags |= LYS_MAND_TRUE;
1936 } else if (strcmp(temp_val, "false") == 0) {
1937 *flags |= LYS_MAND_FALSE;
1938 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001939 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001940 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001941 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001942 return LY_EVALID;
1943 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001944 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001945
Radek Krejcif13b87b2020-12-01 22:02:17 +01001946 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001947}
1948
1949/**
1950 * @brief Parse status element.
1951 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001952 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001953 * @param[in,out] flags Flags to add to.
1954 * @param[in,out] exts Extension instances to add to.
1955 *
1956 * @return LY_ERR values.
1957 */
1958static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001959yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001960{
1961 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001962 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001963 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1964 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001965
Michal Vaskob36053d2020-03-26 15:49:30 +01001966 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1967 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 +02001968 if (strcmp(value, "current") == 0) {
1969 *flags |= LYS_STATUS_CURR;
1970 } else if (strcmp(value, "deprecated") == 0) {
1971 *flags |= LYS_STATUS_DEPRC;
1972 } else if (strcmp(value, "obsolete") == 0) {
1973 *flags |= LYS_STATUS_OBSLT;
1974 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001975 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001976 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001977 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001978 return LY_EVALID;
1979 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001980 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001981
Radek Krejcif13b87b2020-12-01 22:02:17 +01001982 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001983}
1984
1985/**
1986 * @brief Parse when element.
1987 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001988 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001989 * @param[out] when_p When pointer to parse to.
1990 */
1991static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001992yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001993{
1994 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001995 LY_ERR ret = LY_SUCCESS;
1996
David Sedlákdfbbb442019-08-06 16:33:21 +02001997 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001998 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001999
2000 ret = lyxml_ctx_next(ctx->xmlctx);
2001 LY_CHECK_ERR_RET(ret, free(when), ret);
2002
Michal Vaskob36053d2020-03-26 15:49:30 +01002003 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02002004 LY_CHECK_ERR_RET(ret, free(when), ret);
2005
David Sedlákdfbbb442019-08-06 16:33:21 +02002006 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002007 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002008 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2009 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2010 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2011 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002012
Radek Krejcif13b87b2020-12-01 22:02:17 +01002013 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002014}
2015
2016/**
2017 * @brief Parse yin-elemenet element.
2018 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002019 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002020 * @param[in,out] data Data to read from, always moved to currently handled position.
2021 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002022 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002023 *
2024 * @return LY_ERR values.
2025 */
2026static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002027yin_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 +02002028{
2029 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002030 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002031 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2032 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002033
Michal Vaskob36053d2020-03-26 15:49:30 +01002034 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2035 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 +02002036 if (strcmp(temp_val, "true") == 0) {
2037 *flags |= LYS_YINELEM_TRUE;
2038 } else if (strcmp(temp_val, "false") == 0) {
2039 *flags |= LYS_YINELEM_FALSE;
2040 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002041 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002042 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002043 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002044 return LY_EVALID;
2045 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002046 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002047
Radek Krejcif13b87b2020-12-01 22:02:17 +01002048 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002049}
2050
2051/**
2052 * @brief Parse argument element.
2053 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002054 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002055 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2056 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002057 *
2058 * @return LY_ERR values.
2059 */
2060static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002061yin_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 +02002062{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002063 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002064 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2065 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2066 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002067
Michal Vaskob36053d2020-03-26 15:49:30 +01002068 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2069 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 +02002070
Radek Krejcif13b87b2020-12-01 22:02:17 +01002071 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002072}
2073
2074/**
2075 * @brief Parse the extension statement.
2076 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002077 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002078 * @param[in,out] extensions Extensions to add to.
2079 *
2080 * @return LY_ERR values.
2081 */
2082static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002083yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002084{
2085 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002086
Michal Vaskob36053d2020-03-26 15:49:30 +01002087 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2088 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2089 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 +02002090
Radek Krejci9f87b0c2021-03-05 14:45:26 +01002091 struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002092 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002093 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2094 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2095 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2096 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2097 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2098 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002099
Radek Krejcif13b87b2020-12-01 22:02:17 +01002100 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002101}
2102
2103/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002104 * @brief Parse feature element.
2105 *
2106 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002107 * @param[in,out] features Features to add to.
2108 *
2109 * @return LY_ERR values.
2110 */
2111static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002112yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002113{
2114 struct lysp_feature *feat;
2115
2116 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002117 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002118
2119 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002120 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2121 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 +02002122
2123 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002124 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002125 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2126 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2127 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2128 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2129 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2130 };
Michal Vasko69730152020-10-09 16:30:07 +02002131
Radek Krejcif13b87b2020-12-01 22:02:17 +01002132 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002133}
2134
2135/**
David Sedlák28794f22019-07-22 16:45:00 +02002136 * @brief Parse identity element.
2137 *
2138 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002139 * @param[in,out] identities Identities to add to.
2140 *
2141 * @return LY_ERR values.
2142 */
2143static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002144yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002145{
2146 struct lysp_ident *ident;
2147
2148 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002149 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002150
2151 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002152 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2153 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 +02002154
2155 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002156 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002157 {LY_STMT_BASE, &ident->bases, 0},
2158 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2159 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2160 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2161 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2162 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2163 };
Michal Vasko69730152020-10-09 16:30:07 +02002164
Radek Krejcif13b87b2020-12-01 22:02:17 +01002165 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002166}
2167
2168/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002169 * @brief Parse list element.
2170 *
2171 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002172 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002173 *
2174 * @return LY_ERR values.
2175 */
2176static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002177yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002178{
David Sedlákaf536aa2019-07-23 13:42:23 +02002179 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002180 LY_ERR ret = LY_SUCCESS;
2181 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002182 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002183
Michal Vaskob36053d2020-03-26 15:49:30 +01002184 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002185 list->nodetype = LYS_LIST;
2186 list->parent = node_meta->parent;
2187
David Sedlákaf536aa2019-07-23 13:42:23 +02002188 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002189 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2190 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 +02002191
2192 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002193 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002194 LY_STMT_ACTION, &list->actions, 0,
2195 LY_STMT_ANYDATA, &list->child, 0,
2196 LY_STMT_ANYXML, &list->child, 0,
2197 LY_STMT_CHOICE, &list->child, 0,
2198 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2199 LY_STMT_CONTAINER, &list->child, 0,
2200 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2201 LY_STMT_GROUPING, &list->groupings, 0,
2202 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2203 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2204 LY_STMT_LEAF, &list->child, 0,
2205 LY_STMT_LEAF_LIST, &list->child, 0,
2206 LY_STMT_LIST, &list->child, 0,
2207 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2208 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2209 LY_STMT_MUST, &list->musts, 0,
2210 LY_STMT_NOTIFICATION, &list->notifs, 0,
2211 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2212 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2213 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2214 LY_STMT_TYPEDEF, &list->typedefs, 0,
2215 LY_STMT_UNIQUE, &list->uniques, 0,
2216 LY_STMT_USES, &list->child, 0,
2217 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2218 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002219 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2220 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002221 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002222
Michal Vasko69730152020-10-09 16:30:07 +02002223 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002224 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002225 return LY_EVALID;
2226 }
2227
2228 return LY_SUCCESS;
2229}
2230
2231/**
David Sedlák031b9e72019-07-23 15:19:37 +02002232 * @brief Parse notification element.
2233 *
2234 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002235 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002236 *
2237 * @return LY_ERR values.
2238 */
2239static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002240yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002241{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002242 struct lysp_node_notif *notif;
2243 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002244 LY_ERR ret = LY_SUCCESS;
2245 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002246 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002247
2248 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002249 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002250 notif->nodetype = LYS_NOTIF;
2251 notif->parent = notif_meta->parent;
2252
2253 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002254 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2255 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 +02002256
2257 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002258 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002259 LY_STMT_ANYDATA, &notif->child, 0,
2260 LY_STMT_ANYXML, &notif->child, 0,
2261 LY_STMT_CHOICE, &notif->child, 0,
2262 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002263 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2264 LY_STMT_GROUPING, &notif->groupings, 0,
2265 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002266 LY_STMT_LEAF, &notif->child, 0,
2267 LY_STMT_LEAF_LIST, &notif->child, 0,
2268 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002269 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2270 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2271 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2272 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002273 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002274 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002275
Radek Krejcif13b87b2020-12-01 22:02:17 +01002276 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2277 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002278 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002279
David Sedlák031b9e72019-07-23 15:19:37 +02002280 return LY_SUCCESS;
2281}
2282
2283/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002284 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002285 *
2286 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002287 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002288 *
2289 * @return LY_ERR values.
2290 */
2291static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002292yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002293{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002294 struct lysp_node_grp *grp;
2295 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002296 LY_ERR ret = LY_SUCCESS;
2297 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002298 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002299
2300 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002301 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002302 grp->nodetype = LYS_GROUPING;
2303 grp->parent = gr_meta->parent;
2304
2305 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002306 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2307 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 +02002308
2309 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002310 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002311 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002312 LY_STMT_ANYDATA, &grp->child, 0,
2313 LY_STMT_ANYXML, &grp->child, 0,
2314 LY_STMT_CHOICE, &grp->child, 0,
2315 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002316 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2317 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002318 LY_STMT_LEAF, &grp->child, 0,
2319 LY_STMT_LEAF_LIST, &grp->child, 0,
2320 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002321 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2322 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2323 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2324 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002325 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002326 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002327 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2328 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002329
Radek Krejci2a9fc652021-01-22 17:44:34 +01002330 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002331}
2332
2333/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002334 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002335 *
2336 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002337 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002338 *
2339 * @return LY_ERR values.
2340 */
2341static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002342yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002343{
David Sedlákf111bcb2019-07-23 17:15:51 +02002344 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002345 LY_ERR ret = LY_SUCCESS;
2346 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002347 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002348
2349 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002350 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002351 cont->nodetype = LYS_CONTAINER;
2352 cont->parent = node_meta->parent;
2353
David Sedlákf111bcb2019-07-23 17:15:51 +02002354 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002355 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2356 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 +02002357
2358 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002359 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002360 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2361 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2362 LY_STMT_ANYXML, &cont->child, 0,
2363 LY_STMT_CHOICE, &cont->child, 0,
2364 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2365 LY_STMT_CONTAINER, &cont->child, 0,
2366 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2367 LY_STMT_GROUPING, &cont->groupings, 0,
2368 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2369 LY_STMT_LEAF, &cont->child, 0,
2370 LY_STMT_LEAF_LIST, &cont->child, 0,
2371 LY_STMT_LIST, &cont->child, 0,
2372 LY_STMT_MUST, &cont->musts, 0,
2373 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2374 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2375 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2376 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2377 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2378 LY_STMT_USES, &cont->child, 0,
2379 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2380 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002381 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2382 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002383
Radek Krejci2a9fc652021-01-22 17:44:34 +01002384 return ret;
David Sedlákf111bcb2019-07-23 17:15:51 +02002385}
2386
2387/**
David Sedlák5379d392019-07-24 10:42:03 +02002388 * @brief Parse case element.
2389 *
2390 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002391 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002392 *
2393 * @return LY_ERR values.
2394 */
2395static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002396yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002397{
David Sedlák5379d392019-07-24 10:42:03 +02002398 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002399 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002400 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002401 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002402
2403 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002404 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002405 cas->nodetype = LYS_CASE;
2406 cas->parent = node_meta->parent;
2407
David Sedlák5379d392019-07-24 10:42:03 +02002408 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002409 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2410 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 +02002411
2412 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002413 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002414 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2415 LY_STMT_ANYXML, &cas->child, 0,
2416 LY_STMT_CHOICE, &cas->child, 0,
2417 LY_STMT_CONTAINER, &cas->child, 0,
2418 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2419 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2420 LY_STMT_LEAF, &cas->child, 0,
2421 LY_STMT_LEAF_LIST, &cas->child, 0,
2422 LY_STMT_LIST, &cas->child, 0,
2423 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2424 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2425 LY_STMT_USES, &cas->child, 0,
2426 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2427 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002428 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2429 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002430
2431 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002432}
2433
2434/**
David Sedlák05404f62019-07-24 14:11:53 +02002435 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002436 *
2437 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002438 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002439 *
2440 * @return LY_ERR values.
2441 */
2442LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002443yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002444{
David Sedlák81497a32019-08-13 16:56:26 +02002445 LY_ERR ret = LY_SUCCESS;
2446 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002447 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002448 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002449
2450 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002451 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002452
David Sedlákb7abcfa2019-07-24 12:33:35 +02002453 choice->nodetype = LYS_CHOICE;
2454 choice->parent = node_meta->parent;
2455
David Sedlákb7abcfa2019-07-24 12:33:35 +02002456 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002457 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2458 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 +02002459
2460 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002461 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002462 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2463 LY_STMT_ANYXML, &choice->child, 0,
2464 LY_STMT_CASE, &choice->child, 0,
2465 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2466 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2467 LY_STMT_CONTAINER, &choice->child, 0,
2468 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2469 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2470 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2471 LY_STMT_LEAF, &choice->child, 0,
2472 LY_STMT_LEAF_LIST, &choice->child, 0,
2473 LY_STMT_LIST, &choice->child, 0,
2474 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2475 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2476 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2477 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2478 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002479 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2480 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002481 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002482}
2483
2484/**
David Sedlák05404f62019-07-24 14:11:53 +02002485 * @brief Parse input or output element.
2486 *
2487 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002488 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002489 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2490 *
2491 * @return LY_ERR values.
2492 */
2493static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002494yin_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 +02002495{
David Sedlák81497a32019-08-13 16:56:26 +02002496 LY_ERR ret = LY_SUCCESS;
2497 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002498 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002499
David Sedlák05404f62019-07-24 14:11:53 +02002500 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002501 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 +02002502 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002503 inout_meta->inout_p->parent = inout_meta->parent;
2504
2505 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002506 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2507 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 +02002508
2509 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002510 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002511 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2512 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2513 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2514 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002515 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002516 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2517 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2518 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002519 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2520 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002521 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002522 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002523 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2524 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002525 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002526
Radek Krejci01180ac2021-01-27 08:48:22 +01002527 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002528 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2529 return LY_EVALID;
2530 }
2531
David Sedlák05404f62019-07-24 14:11:53 +02002532 return LY_SUCCESS;
2533}
2534
David Sedlák992fb7c2019-07-24 16:51:01 +02002535/**
2536 * @brief Parse action element.
2537 *
2538 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002539 * @param[in] act_meta Meta information about parent node and actions to add to.
2540 *
2541 * @return LY_ERR values.
2542 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002543static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002544yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002545{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002546 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002547 LY_ERR ret = LY_SUCCESS;
2548 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002549 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002550 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002551
2552 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002553 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002554 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002555 act->parent = act_meta->parent;
2556
2557 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002558 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002559 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002560
2561 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002562 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002563 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2564 LY_STMT_GROUPING, &act->groupings, 0,
2565 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2566 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2567 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2568 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2569 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2570 LY_STMT_TYPEDEF, &act->typedefs, 0,
2571 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002572 ret = (yin_parse_content(ctx, subelems, subelems_size, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002573 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002574 LY_CHECK_RET(ret);
2575
Michal Vasko7f45cf22020-10-01 12:49:44 +02002576 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2577 if (!act->input.nodetype) {
2578 act->input.nodetype = LYS_INPUT;
2579 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002580 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002581 }
2582 if (!act->output.nodetype) {
2583 act->output.nodetype = LYS_OUTPUT;
2584 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002585 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002586 }
2587
David Sedlák85d0eca2019-07-24 15:15:21 +02002588 return LY_SUCCESS;
2589}
2590
David Sedlák05404f62019-07-24 14:11:53 +02002591/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002592 * @brief Parse augment element.
2593 *
2594 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002595 * @param[in] aug_meta Meta information about parent node and augments to add to.
2596 *
2597 * @return LY_ERR values.
2598 */
2599static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002600yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002601{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002602 struct lysp_node_augment *aug;
2603 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002604 LY_ERR ret = LY_SUCCESS;
2605 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002606 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002607
2608 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002609 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002610 aug->nodetype = LYS_AUGMENT;
2611 aug->parent = aug_meta->parent;
2612
2613 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002614 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2615 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2616 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002617
2618 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002619 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002620 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2621 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2622 LY_STMT_ANYXML, &aug->child, 0,
2623 LY_STMT_CASE, &aug->child, 0,
2624 LY_STMT_CHOICE, &aug->child, 0,
2625 LY_STMT_CONTAINER, &aug->child, 0,
2626 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002627 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002628 LY_STMT_LEAF, &aug->child, 0,
2629 LY_STMT_LEAF_LIST, &aug->child, 0,
2630 LY_STMT_LIST, &aug->child, 0,
2631 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2632 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2633 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2634 LY_STMT_USES, &aug->child, 0,
2635 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2636 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002637 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2638 subelems_deallocator(subelems_size, subelems);
David Sedlák992fb7c2019-07-24 16:51:01 +02002639
Radek Krejci2a9fc652021-01-22 17:44:34 +01002640 return ret;
David Sedlák992fb7c2019-07-24 16:51:01 +02002641}
2642
David Sedlák8b754462019-07-25 16:22:13 +02002643/**
2644 * @brief Parse deviate element.
2645 *
2646 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002647 * @param[in] deviates Deviates to add to.
2648 *
2649 * @return LY_ERR values.
2650 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002651static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002652yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002653{
2654 LY_ERR ret = LY_SUCCESS;
2655 uint8_t dev_mod;
2656 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002657 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002658 struct lysp_deviate_add *d_add = NULL;
2659 struct lysp_deviate_rpl *d_rpl = NULL;
2660 struct lysp_deviate_del *d_del = NULL;
2661
2662 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002663 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2664 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 +02002665
2666 if (strcmp(temp_val, "not-supported") == 0) {
2667 dev_mod = LYS_DEV_NOT_SUPPORTED;
2668 } else if (strcmp(temp_val, "add") == 0) {
2669 dev_mod = LYS_DEV_ADD;
2670 } else if (strcmp(temp_val, "replace") == 0) {
2671 dev_mod = LYS_DEV_REPLACE;
2672 } else if (strcmp(temp_val, "delete") == 0) {
2673 dev_mod = LYS_DEV_DELETE;
2674 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002675 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002676 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002677 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002678 return LY_EVALID;
2679 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002680 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002681
2682 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2683 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002684 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002685 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002686 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2687 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002688 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002689
2690 } else if (dev_mod == LYS_DEV_ADD) {
2691 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002692 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002693 d = (struct lysp_deviate *)d_add;
2694 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2695 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002696 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002697 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002698 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002699 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2700 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2701 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2702 {LY_STMT_MUST, &d_add->musts, 0},
2703 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2704 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2705 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2706 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002707 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002708
2709 } else if (dev_mod == LYS_DEV_REPLACE) {
2710 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002711 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002712 d = (struct lysp_deviate *)d_rpl;
2713 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2714 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002715 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002716 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002717 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002718 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2719 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2720 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2721 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2722 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2723 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2724 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002725 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002726
2727 } else {
2728 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002729 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002730 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002731 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002732 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002733 {LY_STMT_MUST, &d_del->musts, 0},
2734 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2735 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2736 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2737 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002738 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002739 }
2740 LY_CHECK_GOTO(ret, cleanup);
2741
2742 d->mod = dev_mod;
2743 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002744 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002745
2746 return ret;
2747
2748cleanup:
2749 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002750 return ret;
2751}
2752
David Sedlák992fb7c2019-07-24 16:51:01 +02002753/**
David Sedlák8b754462019-07-25 16:22:13 +02002754 * @brief Parse deviation element.
2755 *
2756 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002757 * @param[in] deviations Deviations to add to.
2758 *
2759 * @return LY_ERR values.
2760 */
2761static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002762yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002763{
2764 struct lysp_deviation *dev;
2765
2766 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002767 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002768
2769 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002770 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2771 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2772 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002773 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002774 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2775 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2776 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2777 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2778 };
Michal Vasko69730152020-10-09 16:30:07 +02002779
Radek Krejcif13b87b2020-12-01 22:02:17 +01002780 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002781}
2782
2783/**
David Sedlákc5b20842019-08-13 10:18:31 +02002784 * @brief map keyword to keyword-group.
2785 *
2786 * @param[in] ctx YIN parser context used for logging.
2787 * @param[in] kw Keyword that is child of module or submodule.
2788 * @param[out] group Group of keyword.
2789 *
2790 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2791 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002792static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002793kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002794{
2795 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002796 /* module header */
2797 case LY_STMT_NONE:
2798 case LY_STMT_NAMESPACE:
2799 case LY_STMT_PREFIX:
2800 case LY_STMT_BELONGS_TO:
2801 case LY_STMT_YANG_VERSION:
2802 *group = Y_MOD_MODULE_HEADER;
2803 break;
2804 /* linkage */
2805 case LY_STMT_INCLUDE:
2806 case LY_STMT_IMPORT:
2807 *group = Y_MOD_LINKAGE;
2808 break;
2809 /* meta */
2810 case LY_STMT_ORGANIZATION:
2811 case LY_STMT_CONTACT:
2812 case LY_STMT_DESCRIPTION:
2813 case LY_STMT_REFERENCE:
2814 *group = Y_MOD_META;
2815 break;
2816 /* revision */
2817 case LY_STMT_REVISION:
2818 *group = Y_MOD_REVISION;
2819 break;
2820 /* body */
2821 case LY_STMT_ANYDATA:
2822 case LY_STMT_ANYXML:
2823 case LY_STMT_AUGMENT:
2824 case LY_STMT_CHOICE:
2825 case LY_STMT_CONTAINER:
2826 case LY_STMT_DEVIATION:
2827 case LY_STMT_EXTENSION:
2828 case LY_STMT_FEATURE:
2829 case LY_STMT_GROUPING:
2830 case LY_STMT_IDENTITY:
2831 case LY_STMT_LEAF:
2832 case LY_STMT_LEAF_LIST:
2833 case LY_STMT_LIST:
2834 case LY_STMT_NOTIFICATION:
2835 case LY_STMT_RPC:
2836 case LY_STMT_TYPEDEF:
2837 case LY_STMT_USES:
2838 case LY_STMT_EXTENSION_INSTANCE:
2839 *group = Y_MOD_BODY;
2840 break;
2841 default:
2842 LOGINT(ctx->xmlctx->ctx);
2843 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002844 }
2845
2846 return LY_SUCCESS;
2847}
2848
David Sedlákc5b20842019-08-13 10:18:31 +02002849/**
2850 * @brief Check if relative order of two keywords is valid.
2851 *
2852 * @param[in] ctx YIN parser context used for logging.
2853 * @param[in] kw Current keyword.
2854 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002855 * @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 +02002856 * because relative order is required only in module and submodule sub-elements, used for logging.
2857 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002858 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002859 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002860static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002861yin_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 +02002862{
Radek Krejcid6b76452019-09-03 17:03:03 +02002863 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002864 enum yang_module_stmt gr, next_gr;
2865
2866 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2867 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2868
2869 if (gr > next_gr) {
2870 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2871 return LY_EVALID;
2872 }
2873
2874 return LY_SUCCESS;
2875}
2876
David Sedlákc5dd0942019-09-13 10:23:59 +02002877/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002878 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2879 *
2880 * @param[in,out] ctx Yin parser context for logging and to store current state.
2881 * @param[in] elem_type Type of element that is currently being parsed.
2882 * @param[out] arg Value to write to.
2883 *
2884 * @return LY_ERR values.
2885 */
2886static LY_ERR
2887yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2888{
2889 enum ly_stmt child;
2890
2891 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2892
2893 switch (elem_type) {
2894 case LY_STMT_ACTION:
2895 case LY_STMT_ANYDATA:
2896 case LY_STMT_ANYXML:
2897 case LY_STMT_ARGUMENT:
2898 case LY_STMT_BASE:
2899 case LY_STMT_BIT:
2900 case LY_STMT_CASE:
2901 case LY_STMT_CHOICE:
2902 case LY_STMT_CONTAINER:
2903 case LY_STMT_ENUM:
2904 case LY_STMT_EXTENSION:
2905 case LY_STMT_FEATURE:
2906 case LY_STMT_GROUPING:
2907 case LY_STMT_IDENTITY:
2908 case LY_STMT_IF_FEATURE:
2909 case LY_STMT_LEAF:
2910 case LY_STMT_LEAF_LIST:
2911 case LY_STMT_LIST:
2912 case LY_STMT_MODULE:
2913 case LY_STMT_NOTIFICATION:
2914 case LY_STMT_RPC:
2915 case LY_STMT_SUBMODULE:
2916 case LY_STMT_TYPE:
2917 case LY_STMT_TYPEDEF:
2918 case LY_STMT_UNITS:
2919 case LY_STMT_USES:
2920 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
2921 break;
2922 case LY_STMT_AUGMENT:
2923 case LY_STMT_DEVIATION:
2924 case LY_STMT_REFINE:
2925 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
2926 break;
2927 case LY_STMT_CONFIG:
2928 case LY_STMT_DEFAULT:
2929 case LY_STMT_DEVIATE:
2930 case LY_STMT_ERROR_APP_TAG:
2931 case LY_STMT_FRACTION_DIGITS:
2932 case LY_STMT_KEY:
2933 case LY_STMT_LENGTH:
2934 case LY_STMT_MANDATORY:
2935 case LY_STMT_MAX_ELEMENTS:
2936 case LY_STMT_MIN_ELEMENTS:
2937 case LY_STMT_MODIFIER:
2938 case LY_STMT_ORDERED_BY:
2939 case LY_STMT_PATH:
2940 case LY_STMT_PATTERN:
2941 case LY_STMT_POSITION:
2942 case LY_STMT_PREFIX:
2943 case LY_STMT_PRESENCE:
2944 case LY_STMT_RANGE:
2945 case LY_STMT_REQUIRE_INSTANCE:
2946 case LY_STMT_STATUS:
2947 case LY_STMT_VALUE:
2948 case LY_STMT_YANG_VERSION:
2949 case LY_STMT_YIN_ELEMENT:
2950 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
2951 break;
2952 case LY_STMT_IMPORT:
2953 case LY_STMT_INCLUDE:
2954 case LY_STMT_BELONGS_TO:
2955 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
2956 break;
2957 case LY_STMT_INPUT:
2958 case LY_STMT_OUTPUT:
2959 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2960 break;
2961 case LY_STMT_MUST:
2962 case LY_STMT_WHEN:
2963 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
2964 break;
2965 case LY_STMT_NAMESPACE:
2966 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
2967 break;
2968 case LY_STMT_REVISION:
2969 case LY_STMT_REVISION_DATE:
2970 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
2971 break;
2972 case LY_STMT_UNIQUE:
2973 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
2974 break;
2975 /* argument is mapped to yin element */
2976 case LY_STMT_CONTACT:
2977 case LY_STMT_DESCRIPTION:
2978 case LY_STMT_ORGANIZATION:
2979 case LY_STMT_REFERENCE:
2980 case LY_STMT_ERROR_MESSAGE:
2981 /* there shouldn't be any attribute, argument is supposed to be first subelement */
2982 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2983
2984 /* no content */
2985 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
2986 if (ctx->xmlctx->ws_only) {
2987 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2988 }
2989 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
2990 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
2991 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
2992 return LY_EVALID;
2993 }
2994
2995 /* parse child element */
2996 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
2997 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
2998 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
2999 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3000 ly_stmt2str(elem_type));
3001 return LY_EVALID;
3002 }
3003 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3004
3005 /* no attributes expected? TODO */
3006 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3007 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3008 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3009 }
3010
3011 /* load and save content */
3012 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3013 LY_CHECK_RET(!*arg, LY_EMEM);
3014
3015 /* load closing tag of subelement */
3016 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3017
3018 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3019 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3020 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3021 }*/
3022 break;
3023 default:
3024 LOGINT(ctx->xmlctx->ctx);
3025 return LY_EINT;
3026 }
3027
3028 return LY_SUCCESS;
3029}
3030
3031/**
3032 * @brief Parse yin element into generic structure.
3033 *
3034 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3035 * @param[in] parent Identification of parent element.
3036 * @param[out] element Where the element structure should be stored.
3037 *
3038 * @return LY_ERR values.
3039 */
3040LY_ERR
3041yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3042{
3043 LY_ERR ret = LY_SUCCESS;
3044 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003045 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003046
3047 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3048
3049 /* allocate new structure for element */
3050 *element = calloc(1, sizeof(**element));
3051 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003052
3053 /* store identifier */
3054 if (ctx->xmlctx->prefix_len) {
3055 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3056 ctx->xmlctx->name) == -1) {
3057 LOGMEM(ctx->xmlctx->ctx);
3058 ret = LY_EMEM;
3059 goto cleanup;
3060 }
3061 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3062
3063 /* store prefix data for the statement */
Radek Krejci8df109d2021-04-23 12:19:08 +02003064 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 +01003065 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3066 } else {
3067 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3068 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003069
3070 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3071 ctx->xmlctx->prefix_len, parent);
3072
3073 last = (*element)->child;
3074 if ((*element)->kw == LY_STMT_NONE) {
3075 /* unrecognized element */
3076 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3077 ly_stmt2str(parent));
3078 ret = LY_EVALID;
3079 goto cleanup;
3080 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3081 /* element is known yang keyword, which means argument can be parsed correctly. */
3082 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3083 LY_CHECK_GOTO(ret, cleanup);
3084 } else {
3085 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3086
3087 /* load attributes in generic way, save all attributes in linked list */
3088 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3089 new = calloc(1, sizeof(*last));
3090 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3091 if (!(*element)->child) {
3092 /* save first */
3093 (*element)->child = new;
3094 } else {
3095 last->next = new;
3096 }
3097 last = new;
3098
3099 last->flags |= LYS_YIN_ATTR;
3100 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3101 last->kw = LY_STMT_NONE;
3102 /* attributes with prefix are ignored */
3103 if (!ctx->xmlctx->prefix) {
3104 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3105
3106 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3107 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3108 } else {
3109 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3110 }
3111 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3112 }
3113 }
3114
3115 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3116 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3117 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3118 /* parse subelements */
3119 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3120 LY_CHECK_GOTO(ret, cleanup);
3121 if (!(*element)->child) {
3122 /* save first */
3123 (*element)->child = new;
3124 } else {
3125 last->next = new;
3126 }
3127 last = new;
3128
3129 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3130 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3131 }
3132 } else {
3133 /* save element content */
3134 if (ctx->xmlctx->value_len) {
3135 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3136 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003137
3138 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003139 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 +01003140 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003141 }
3142
3143 /* read closing tag */
3144 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3145 }
3146
3147cleanup:
3148 return ret;
3149}
3150
3151/**
3152 * @brief Parse instance of extension.
3153 *
3154 * @param[in,out] ctx Yin parser context for logging and to store current state.
Radek Krejcifc596f92021-02-26 22:40:26 +01003155 * @param[in] subelem The statement this extension instance is a subelement of.
Michal Vaskoafac7822020-10-20 14:22:26 +02003156 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3157 * @param[in,out] exts Extension instance to add to.
3158 *
3159 * @return LY_ERR values.
3160 */
3161LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01003162yin_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 +02003163 struct lysp_ext_instance **exts)
3164{
3165 struct lysp_ext_instance *e;
3166 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003167 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003168
3169 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003170 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003171
3172 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3173
Michal Vaskofc2cd072021-02-24 13:17:17 +01003174 if (!ctx->xmlctx->prefix_len) {
3175 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3176 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3177 return LY_EVALID;
3178 }
3179
3180 /* store prefixed name */
3181 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3182 ctx->xmlctx->name) == -1) {
3183 LOGMEM(ctx->xmlctx->ctx);
3184 return LY_EMEM;
3185 }
3186 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3187
3188 /* store prefix data for the name */
Radek Krejci8df109d2021-04-23 12:19:08 +02003189 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 +01003190 &e->format, &e->prefix_data));
3191
Radek Krejciab430862021-03-02 20:13:40 +01003192 e->parent_stmt = subelem;
3193 e->parent_stmt_index = subelem_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003194
Michal Vaskoafac7822020-10-20 14:22:26 +02003195 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3196
3197 /* store attributes as subelements */
3198 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3199 if (!ctx->xmlctx->prefix) {
3200 new_subelem = calloc(1, sizeof(*new_subelem));
3201 if (!e->child) {
3202 e->child = new_subelem;
3203 } else {
3204 last_subelem->next = new_subelem;
3205 }
3206 last_subelem = new_subelem;
3207
3208 last_subelem->flags |= LYS_YIN_ATTR;
3209 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3210 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3211 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3212
Michal Vaskofc2cd072021-02-24 13:17:17 +01003213 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3214 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003215 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3216 } else {
3217 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3218 }
3219
3220 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3221 }
3222
3223 /* parse subelements */
3224 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3225 if (ctx->xmlctx->ws_only) {
3226 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3227 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3228 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &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 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3237 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3238 }
3239 } else if (ctx->xmlctx->value_len) {
3240 /* save text content */
3241 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3242 LY_CHECK_RET(!e->argument, LY_EMEM);
3243
Michal Vaskofc2cd072021-02-24 13:17:17 +01003244 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003245 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 +01003246 &ctx->xmlctx->ns, &e->format, &e->prefix_data));
Michal Vaskofc2cd072021-02-24 13:17:17 +01003247
Michal Vaskoafac7822020-10-20 14:22:26 +02003248 /* parser next */
3249 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3250 }
3251
3252 return LY_SUCCESS;
3253}
3254
3255/**
3256 * @brief Generic function for content parsing
3257 *
3258 * @param[in,out] ctx Yin parser context for logging and to store current state.
3259 * @param[in] subelem_info array of valid subelement types and meta information
3260 * @param[in] subelem_info_size Size of subelem_info array.
3261 * @param[in] current_element Type of current element.
3262 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3263 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3264 *
3265 * @return LY_ERR values.
3266 */
David Sedlákd6e56892019-07-01 15:40:24 +02003267LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003268yin_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 +02003269 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003270{
3271 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003272 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003273 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003274 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003275
Michal Vaskob36053d2020-03-26 15:49:30 +01003276 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003277
Michal Vaskob36053d2020-03-26 15:49:30 +01003278 if (ctx->xmlctx->ws_only) {
3279 /* check whether there are any children */
3280 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3281 } else {
3282 /* we want to parse the value */
3283 next_status = LYXML_ELEM_CLOSE;
3284 }
3285
3286 if (next_status == LYXML_ELEMENT) {
3287 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3288
3289 /* current element has subelements as content */
3290 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3291 /* match keyword */
3292 last_kw = kw;
3293 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003294 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003295
3296 /* check if this element can be child of current element */
3297 subelem = get_record(kw, subelem_info_size, subelem_info);
3298 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003299 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003300 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3301 } else {
3302 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003303 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003304 }
3305 ret = LY_EVALID;
3306 goto cleanup;
3307 }
3308
3309 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003310 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003311 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3312 LY_CHECK_GOTO(ret, cleanup);
3313 }
3314
3315 /* flag check */
3316 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3317 /* subelement uniquenes */
3318 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3319 return LY_EVALID;
3320 }
3321 if (subelem->flags & YIN_SUBELEM_FIRST) {
3322 /* subelement is supposed to be defined as first subelement */
3323 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3324 LY_CHECK_GOTO(ret, cleanup);
3325 }
3326 if (subelem->flags & YIN_SUBELEM_VER2) {
3327 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003328 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003329 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 +02003330 ret = LY_EVALID;
3331 goto cleanup;
3332 }
David Sedlákd6e56892019-07-01 15:40:24 +02003333 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003334 /* note that element was parsed for easy uniqueness check in next iterations */
3335 subelem->flags |= YIN_SUBELEM_PARSED;
3336
3337 switch (kw) {
3338 /* call responsible function */
3339 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003340 ret = yin_parse_extension_instance(ctx, current_element,
Michal Vasko69730152020-10-09 16:30:07 +02003341 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003342 break;
3343 case LY_STMT_ACTION:
3344 case LY_STMT_RPC:
3345 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3346 break;
3347 case LY_STMT_ANYDATA:
3348 case LY_STMT_ANYXML:
3349 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3350 break;
3351 case LY_STMT_ARGUMENT:
3352 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3353 break;
3354 case LY_STMT_AUGMENT:
3355 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3356 break;
3357 case LY_STMT_BASE:
3358 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3359 break;
3360 case LY_STMT_BELONGS_TO:
3361 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3362 break;
3363 case LY_STMT_BIT:
3364 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3365 break;
3366 case LY_STMT_CASE:
3367 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3368 break;
3369 case LY_STMT_CHOICE:
3370 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3371 break;
3372 case LY_STMT_CONFIG:
3373 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3374 break;
3375 case LY_STMT_CONTACT:
3376 case LY_STMT_DESCRIPTION:
3377 case LY_STMT_ORGANIZATION:
3378 case LY_STMT_REFERENCE:
3379 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3380 break;
3381 case LY_STMT_CONTAINER:
3382 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3383 break;
3384 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003385 ret = yin_parse_qname(ctx, kw, subelem, exts);
3386 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003387 case LY_STMT_ERROR_APP_TAG:
3388 case LY_STMT_KEY:
3389 case LY_STMT_PRESENCE:
3390 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3391 break;
3392 case LY_STMT_DEVIATE:
3393 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3394 break;
3395 case LY_STMT_DEVIATION:
3396 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3397 break;
3398 case LY_STMT_ENUM:
3399 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3400 break;
3401 case LY_STMT_ERROR_MESSAGE:
3402 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3403 break;
3404 case LY_STMT_EXTENSION:
3405 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3406 break;
3407 case LY_STMT_FEATURE:
3408 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3409 break;
3410 case LY_STMT_FRACTION_DIGITS:
3411 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3412 break;
3413 case LY_STMT_GROUPING:
3414 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3415 break;
3416 case LY_STMT_IDENTITY:
3417 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3418 break;
Radek Išabe8a6532021-03-29 08:54:22 +02003419 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003420 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003421 ret = yin_parse_qname(ctx, kw, subelem, exts);
3422 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003423 case LY_STMT_UNITS:
3424 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3425 break;
3426 case LY_STMT_IMPORT:
3427 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3428 break;
3429 case LY_STMT_INCLUDE:
Radek Krejcieeee95c2021-01-19 10:57:22 +01003430 if ((current_element == LY_STMT_SUBMODULE) && (ctx->parsed_mod->version == LYS_VERSION_1_1)) {
3431 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
3432 ((struct lysp_submodule *)(ctx->parsed_mod))->name);
3433 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003434 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3435 break;
3436 case LY_STMT_INPUT:
3437 case LY_STMT_OUTPUT:
3438 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3439 break;
3440 case LY_STMT_LEAF:
3441 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3442 break;
3443 case LY_STMT_LEAF_LIST:
3444 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3445 break;
3446 case LY_STMT_LENGTH:
3447 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3448 break;
3449 case LY_STMT_LIST:
3450 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3451 break;
3452 case LY_STMT_MANDATORY:
3453 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3454 break;
3455 case LY_STMT_MAX_ELEMENTS:
3456 case LY_STMT_MIN_ELEMENTS:
3457 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3458 break;
3459 case LY_STMT_MODIFIER:
3460 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3461 break;
3462 case LY_STMT_MUST:
3463 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3464 break;
3465 case LY_STMT_NAMESPACE:
3466 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3467 break;
3468 case LY_STMT_NOTIFICATION:
3469 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3470 break;
3471 case LY_STMT_ORDERED_BY:
3472 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3473 break;
3474 case LY_STMT_PATH:
3475 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3476 break;
3477 case LY_STMT_PATTERN:
3478 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3479 break;
3480 case LY_STMT_VALUE:
3481 case LY_STMT_POSITION:
3482 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3483 break;
3484 case LY_STMT_PREFIX:
3485 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3486 break;
3487 case LY_STMT_RANGE:
3488 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3489 break;
3490 case LY_STMT_REFINE:
3491 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3492 break;
3493 case LY_STMT_REQUIRE_INSTANCE:
3494 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3495 break;
3496 case LY_STMT_REVISION:
3497 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3498 break;
3499 case LY_STMT_REVISION_DATE:
3500 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3501 break;
3502 case LY_STMT_STATUS:
3503 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3504 break;
3505 case LY_STMT_TYPE:
3506 ret = yin_parse_type(ctx, current_element, subelem);
3507 break;
3508 case LY_STMT_TYPEDEF:
3509 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3510 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003511 case LY_STMT_USES:
3512 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3513 break;
3514 case LY_STMT_WHEN:
3515 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3516 break;
3517 case LY_STMT_YANG_VERSION:
3518 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3519 break;
3520 case LY_STMT_YIN_ELEMENT:
3521 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3522 break;
3523 case LY_STMT_ARG_TEXT:
3524 case LY_STMT_ARG_VALUE:
3525 /* TODO what to do with content/attributes? */
3526 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3527 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3528 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3529 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3530 }
3531 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3532 break;
3533 default:
3534 LOGINT(ctx->xmlctx->ctx);
3535 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003536 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003537 LY_CHECK_GOTO(ret, cleanup);
3538 subelem = NULL;
3539
3540 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003541 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003542 } else {
3543 LY_CHECK_RET(ret);
3544 /* elements with text or none content */
3545 /* save text content, if text_content isn't set, it's just ignored */
3546 /* no resources are allocated in this branch, no need to use cleanup label */
3547 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3548 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003549 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 +01003550 LY_CHECK_RET(!*text_content, LY_EMEM);
3551 }
3552
3553 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003554 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003555
David Sedlák8b754462019-07-25 16:22:13 +02003556 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3557 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003558
3559cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003560 return ret;
3561}
3562
David Sedlákaa98bba2019-09-12 11:52:14 +02003563/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003564 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003565 *
3566 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003567 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003568 *
3569 * @return LY_ERR values.
3570 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003571LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003572yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003573{
David Sedlák81497a32019-08-13 16:56:26 +02003574 LY_ERR ret = LY_SUCCESS;
3575 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003576 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003577 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003578
Michal Vaskoc3781c32020-10-06 14:04:08 +02003579 mod->is_submod = 0;
3580
Michal Vaskob36053d2020-03-26 15:49:30 +01003581 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3582 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 +01003583 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003584 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3585 LY_STMT_ANYXML, &mod->data, 0,
3586 LY_STMT_AUGMENT, &mod->augments, 0,
3587 LY_STMT_CHOICE, &mod->data, 0,
3588 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3589 LY_STMT_CONTAINER, &mod->data, 0,
3590 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3591 LY_STMT_DEVIATION, &mod->deviations, 0,
3592 LY_STMT_EXTENSION, &mod->extensions, 0,
3593 LY_STMT_FEATURE, &mod->features, 0,
3594 LY_STMT_GROUPING, &mod->groupings, 0,
3595 LY_STMT_IDENTITY, &mod->identities, 0,
3596 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3597 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3598 LY_STMT_LEAF, &mod->data, 0,
3599 LY_STMT_LEAF_LIST, &mod->data, 0,
3600 LY_STMT_LIST, &mod->data, 0,
3601 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3602 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3603 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3604 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3605 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3606 LY_STMT_REVISION, &mod->revs, 0,
3607 LY_STMT_RPC, &mod->rpcs, 0,
3608 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3609 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003610 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003611 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003612
Radek Krejcif13b87b2020-12-01 22:02:17 +01003613 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3614 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003615 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003616
David Sedláked809f12019-09-13 10:15:11 +02003617 /* submodules share the namespace with the module names, so there must not be
3618 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003619 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003620 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003621 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003622 return LY_EVALID;
3623 }
3624
3625 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003626}
3627
Michal Vaskoafac7822020-10-20 14:22:26 +02003628/**
3629 * @brief Parse submodule element.
3630 *
3631 * @param[in,out] ctx Yin parser context for logging and to store current state.
3632 * @param[in] mod_attrs Attributes of submodule element.
3633 * @param[out] submod Parsed submodule structure.
3634 *
3635 * @return LY_ERR values.
3636 */
David Sedlák3b4db242018-10-19 16:11:01 +02003637LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003638yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003639{
David Sedlák81497a32019-08-13 16:56:26 +02003640 LY_ERR ret = LY_SUCCESS;
3641 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003642 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003643 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003644
Michal Vaskoc3781c32020-10-06 14:04:08 +02003645 submod->is_submod = 1;
3646
Michal Vaskob36053d2020-03-26 15:49:30 +01003647 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3648 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 +01003649 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003650 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3651 LY_STMT_ANYXML, &submod->data, 0,
3652 LY_STMT_AUGMENT, &submod->augments, 0,
3653 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3654 LY_STMT_CHOICE, &submod->data, 0,
3655 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3656 LY_STMT_CONTAINER, &submod->data, 0,
3657 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3658 LY_STMT_DEVIATION, &submod->deviations, 0,
3659 LY_STMT_EXTENSION, &submod->extensions, 0,
3660 LY_STMT_FEATURE, &submod->features, 0,
3661 LY_STMT_GROUPING, &submod->groupings, 0,
3662 LY_STMT_IDENTITY, &submod->identities, 0,
3663 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3664 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3665 LY_STMT_LEAF, &submod->data, 0,
3666 LY_STMT_LEAF_LIST, &submod->data, 0,
3667 LY_STMT_LIST, &submod->data, 0,
3668 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3669 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3670 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3671 LY_STMT_REVISION, &submod->revs, 0,
3672 LY_STMT_RPC, &submod->rpcs, 0,
3673 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3674 LY_STMT_USES, &submod->data, 0,
3675 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3676 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003677
Radek Krejcif13b87b2020-12-01 22:02:17 +01003678 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3679 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003680 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003681
David Sedláked809f12019-09-13 10:15:11 +02003682 /* submodules share the namespace with the module names, so there must not be
3683 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003684 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003685 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003686 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003687 return LY_EVALID;
3688 }
3689
3690 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003691}
3692
3693LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003694yin_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 +02003695 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003696{
Radek Krejcid6b76452019-09-03 17:03:03 +02003697 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003698 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003699 struct lysp_submodule *mod_p = NULL;
3700
3701 /* create context */
3702 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003703 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003704 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003705 (*yin_ctx)->unres = main_ctx->unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003706 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003707
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003708 mod_p = calloc(1, sizeof *mod_p);
3709 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3710 mod_p->mod = main_ctx->parsed_mod->mod;
3711 mod_p->parsing = 1;
3712 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3713
David Sedlák1b623122019-08-05 15:27:49 +02003714 /* map the typedefs and groupings list from main context to the submodule's context */
3715 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3716 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3717
David Sedlák8985a142019-07-31 16:43:06 +02003718 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003719 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 +02003720 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003721 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003722 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3723 ret = LY_EINVAL;
3724 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003725 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003726 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003727 ret = LY_EVALID;
3728 goto cleanup;
3729 }
3730
Michal Vaskob36053d2020-03-26 15:49:30 +01003731 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003732 LY_CHECK_GOTO(ret, cleanup);
3733
David Sedlákbf8a2b72019-08-14 16:48:10 +02003734 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003735 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003736 if (in->current[0] == '\n') {
3737 LY_IN_NEW_LINE(in);
3738 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003739 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003740 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003741 if (in->current[0]) {
3742 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003743 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003744 ret = LY_EVALID;
3745 goto cleanup;
3746 }
3747
David Sedlák8985a142019-07-31 16:43:06 +02003748 mod_p->parsing = 0;
3749 *submod = mod_p;
3750
3751cleanup:
3752 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003753 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003754 yin_parser_ctx_free(*yin_ctx);
3755 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003756 }
David Sedlák8985a142019-07-31 16:43:06 +02003757 return ret;
3758}
3759
3760LY_ERR
Michal Vasko405cc9e2020-12-01 12:01:27 +01003761yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
David Sedlák3b4db242018-10-19 16:11:01 +02003762{
David Sedláke4889912018-11-02 09:52:40 +01003763 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003764 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003765 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003766
David Sedlák8985a142019-07-31 16:43:06 +02003767 /* create context */
3768 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003769 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003770 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003771 (*yin_ctx)->unres = unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003772 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003773
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003774 mod_p = calloc(1, sizeof *mod_p);
3775 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3776 mod_p->mod = mod;
3777 mod_p->parsing = 1;
3778 (*yin_ctx)->parsed_mod = mod_p;
3779
David Sedlák8985a142019-07-31 16:43:06 +02003780 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003781 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 +02003782 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003783 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003784 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 +01003785 ret = LY_EINVAL;
3786 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003787 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003788 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003789 ret = LY_EVALID;
3790 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003791 }
3792
David Sedlák00250342019-06-21 14:19:39 +02003793 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003794 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003795 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003796
David Sedlákbf8a2b72019-08-14 16:48:10 +02003797 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003798 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003799 if (in->current[0] == '\n') {
3800 LY_IN_NEW_LINE(in);
3801 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003802 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003803 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003804 if (in->current[0]) {
3805 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003806 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003807 ret = LY_EVALID;
3808 goto cleanup;
3809 }
3810
David Sedlák3017da42019-02-15 09:48:04 +01003811 mod_p->parsing = 0;
3812 mod->parsed = mod_p;
3813
3814cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003815 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003816 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003817 yin_parser_ctx_free(*yin_ctx);
3818 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003819 }
David Sedlák2e411422018-12-17 02:35:39 +01003820 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003821}