blob: 6b5ff775b03bcbd438f1d1501ea79fe323025c6c [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>
Michal Vaskoc636ea42022-09-16 10:20:31 +02004 * @author Michal Vasko <mvasko@cesnet.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02005 * @brief YIN parser.
6 *
Michal Vaskoc636ea42022-09-16 10:20:31 +02007 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02008 *
9 * This source code is licensed under BSD 3-Clause License (the "License").
10 * You may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020014 */
Michal Vaskofc2cd072021-02-24 13:17:17 +010015#define _GNU_SOURCE
16
David Sedlák3ffbc522019-07-02 17:49:28 +020017#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020018#include <ctype.h>
19#include <errno.h>
20#include <stdarg.h>
21#include <stdbool.h>
Radek Krejci47fab892020-11-05 17:02:41 +010022#include <stdint.h>
David Sedlák3b4db242018-10-19 16:11:01 +020023#include <stdio.h>
24#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020025#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020026
Radek Krejci535ea9f2020-05-29 16:01:05 +020027#include "common.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010028#include "compat.h"
David Sedlákf824ad52018-10-14 23:58:15 +020029#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020030#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010031#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020032#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010033#include "log.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020034#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020035#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020036#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020038#include "tree.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010039#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010040#include "tree_edit.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020041#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020042#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020043#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020044
Radek Krejci77114102021-03-10 15:21:57 +010045struct lys_glob_unres;
46
David Sedlák2b214ac2019-06-06 16:11:03 +020047/**
48 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020049 *
David Sedlák2b214ac2019-06-06 16:11:03 +020050 * @param ns Namespace URI to check.
51 *
52 * @return true if ns equals YIN_NS_URI false otherwise.
53 */
54#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
55
Michal Vaskoafac7822020-10-20 14:22:26 +020056enum yin_argument {
57 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
58 YIN_ARG_NAME, /**< argument name */
59 YIN_ARG_TARGET_NODE, /**< argument target-node */
60 YIN_ARG_MODULE, /**< argument module */
61 YIN_ARG_VALUE, /**< argument value */
62 YIN_ARG_TEXT, /**< argument text */
63 YIN_ARG_CONDITION, /**< argument condition */
64 YIN_ARG_URI, /**< argument uri */
65 YIN_ARG_DATE, /**< argument data */
66 YIN_ARG_TAG, /**< argument tag */
67 YIN_ARG_NONE /**< empty (special value) */
68};
69
Michal Vasko22df3f02020-08-24 13:29:22 +020070const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020071 [YIN_ARG_NAME] = "name",
72 [YIN_ARG_TARGET_NODE] = "target-node",
73 [YIN_ARG_MODULE] = "module",
74 [YIN_ARG_VALUE] = "value",
75 [YIN_ARG_TEXT] = "text",
76 [YIN_ARG_CONDITION] = "condition",
77 [YIN_ARG_URI] = "uri",
78 [YIN_ARG_DATE] = "date",
79 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020080 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020081};
82
Michal Vaskoafac7822020-10-20 14:22:26 +020083#define yin_attr2str(STMT) yin_attr_list[STMT]
84
85#define VALID_VALS1 " Only valid value is \"%s\"."
86#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
87#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
88#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
89
90/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
91#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
92 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
93 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
94 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
95
96/* flags to set constraints of subelements */
97#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
98#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
99#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
100#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
101
102#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
103 time to simply check validity of given constraints */
104
105struct yin_subelement {
106 enum ly_stmt type; /**< type of keyword */
Michal Vasko193dacd2022-10-13 08:43:05 +0200107 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed
108 subelement should be stored) */
109 uint16_t flags; /**< describes constraints of subelement can be set to YIN_SUBELEM_MANDATORY,
110 YIN_SUBELEM_UNIQUE, YIN_SUBELEM_FIRST, YIN_SUBELEM_VER2, and YIN_SUBELEM_DEFAULT_TEXT */
Michal Vaskoafac7822020-10-20 14:22:26 +0200111};
112
113/* Meta information passed to yin_parse_argument function,
114 holds information about where content of argument element will be stored. */
115struct yin_argument_meta {
116 uint16_t *flags; /**< Argument flags */
117 const char **argument; /**< Argument value */
118};
119
120/**
121 * @brief Meta information passed to functions working with tree_schema,
122 * that require additional information about parent node.
123 */
124struct tree_node_meta {
125 struct lysp_node *parent; /**< parent node */
126 struct lysp_node **nodes; /**< linked list of siblings */
127};
128
129/**
130 * @brief Meta information passed to yin_parse_import function.
131 */
132struct import_meta {
133 const char *prefix; /**< module prefix. */
134 struct lysp_import **imports; /**< imports to add to. */
135};
136
137/**
138 * @brief Meta information passed to yin_parse_include function.
139 */
140struct include_meta {
141 const char *name; /**< Module/submodule name. */
142 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
143};
144
145/**
146 * @brief Meta information passed to yin_parse_inout function.
147 */
148struct inout_meta {
149 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100150 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200151};
152
153/**
154 * @brief Meta information passed to yin_parse_minmax function.
155 */
156struct minmax_dev_meta {
157 uint32_t *lim; /**< min/max value to write to. */
158 uint16_t *flags; /**< min/max flags to write to. */
159 struct lysp_ext_instance **exts; /**< extension instances to add to. */
160};
161
Michal Vaskod0625d72022-10-06 15:02:50 +0200162LY_ERR yin_parse_content(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Michal Vasko193dacd2022-10-13 08:43:05 +0200163 const void *parent, enum ly_stmt parent_stmt, const char **text_content, struct lysp_ext_instance **exts);
Michal Vaskoafac7822020-10-20 14:22:26 +0200164
165/**
166 * @brief Match yang keyword from yin data.
167 *
168 * @param[in,out] ctx Yin parser context for logging and to store current state.
169 * @param[in] name Start of keyword name
170 * @param[in] name_len Lenght of keyword name.
171 * @param[in] prefix Start of keyword prefix.
172 * @param[in] prefix_len Lenght of prefix.
Michal Vasko193dacd2022-10-13 08:43:05 +0200173 * @param[in] parent Identification of parent element, use LY_STMT_NONE for elements without parent.
Michal Vaskoafac7822020-10-20 14:22:26 +0200174 * @return yang_keyword values.
175 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200176enum ly_stmt
Michal Vasko193dacd2022-10-13 08:43:05 +0200177yin_match_keyword(struct lysp_yin_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len,
178 enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200179{
David Sedlák8f7a1172019-06-20 14:42:18 +0200180 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200181 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200182 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200183 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200184
Michal Vasko69730152020-10-09 16:30:07 +0200185 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200186 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200187 }
188
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200189 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200190 if (ns) {
191 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200192 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200193 }
194 } else {
195 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200196 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200197 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200198
Michal Vasko63f3d842020-07-08 10:10:14 +0200199 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
200 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100201 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200202 name = in->current;
203 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200204
205 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200206 /* 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 +0200207 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200208 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200209 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200210 return kw;
211 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200212 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200213 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200214 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200215 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200216 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200217 }
218}
219
Michal Vaskoafac7822020-10-20 14:22:26 +0200220/**
221 * @brief Match argument name.
222 *
223 * @param[in] name String representing name.
224 * @param[in] len Lenght of the name.
Michal Vaskoafac7822020-10-20 14:22:26 +0200225 * @return yin_argument values.
226 */
David Sedlákc5b20842019-08-13 10:18:31 +0200227enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200228yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200229{
David Sedlákc5b20842019-08-13 10:18:31 +0200230 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200231 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200232
David Sedlák7ff55a92019-06-17 11:11:41 +0200233 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200234
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200235#define READ_INC(LEN) already_read += LEN
236#define ARG_SET(STMT) arg=STMT
237#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100238
David Sedlák1c8b2702019-02-22 11:03:02 +0100239 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100240 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200241 READ_INC(1);
242 if (ARG_CHECK("ondition", 8)) {
243 ARG_SET(YIN_ARG_CONDITION);
244 }
David Sedlák3b4db242018-10-19 16:11:01 +0200245 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200246
David Sedlák94de2aa2019-02-15 12:42:11 +0100247 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200248 READ_INC(1);
249 if (ARG_CHECK("ate", 3)) {
250 ARG_SET(YIN_ARG_DATE);
251 }
David Sedlák3b4db242018-10-19 16:11:01 +0200252 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200253
David Sedlák94de2aa2019-02-15 12:42:11 +0100254 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200255 READ_INC(1);
256 if (ARG_CHECK("odule", 5)) {
257 ARG_SET(YIN_ARG_MODULE);
258 }
David Sedlák872c7b42018-10-26 13:15:20 +0200259 break;
260
David Sedlák94de2aa2019-02-15 12:42:11 +0100261 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200262 READ_INC(1);
263 if (ARG_CHECK("ame", 3)) {
264 ARG_SET(YIN_ARG_NAME);
265 }
David Sedlák872c7b42018-10-26 13:15:20 +0200266 break;
267
David Sedlák94de2aa2019-02-15 12:42:11 +0100268 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200269 READ_INC(1);
270 if (ARG_CHECK("a", 1)) {
271 if (ARG_CHECK("g", 1)) {
272 ARG_SET(YIN_ARG_TAG);
273 } else if (ARG_CHECK("rget-node", 9)) {
274 ARG_SET(YIN_ARG_TARGET_NODE);
275 }
276 } else if (ARG_CHECK("ext", 3)) {
277 ARG_SET(YIN_ARG_TEXT);
278 }
David Sedlák3b4db242018-10-19 16:11:01 +0200279 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200280
David Sedlák94de2aa2019-02-15 12:42:11 +0100281 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200282 READ_INC(1);
283 if (ARG_CHECK("ri", 2)) {
284 ARG_SET(YIN_ARG_URI);
285 }
David Sedlák3b4db242018-10-19 16:11:01 +0200286 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200287
David Sedlák94de2aa2019-02-15 12:42:11 +0100288 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200289 READ_INC(1);
290 if (ARG_CHECK("alue", 4)) {
291 ARG_SET(YIN_ARG_VALUE);
292 }
David Sedlák3b4db242018-10-19 16:11:01 +0200293 break;
294 }
295
David Sedlákc10e7902018-12-17 02:17:59 +0100296 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200297 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200298 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200299 }
300
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200301#undef ARG_CHECK
302#undef ARG_SET
303#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100304
David Sedlák872c7b42018-10-26 13:15:20 +0200305 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200306}
307
Radek Krejcid6b76452019-09-03 17:03:03 +0200308#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
309 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
310 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
311 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200312
Radek Krejcid6b76452019-09-03 17:03:03 +0200313#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 +0200314
David Sedlák26ea1432019-08-14 13:42:23 +0200315/**
316 * @brief Free subelems information allocated on heap.
317 *
318 * @param[in] count Size of subelems array.
319 * @param[in] subelems Subelems array to free.
320 */
David Sedlák81497a32019-08-13 16:56:26 +0200321static void
322subelems_deallocator(size_t count, struct yin_subelement *subelems)
323{
Michal Vaskod989ba02020-08-24 10:59:24 +0200324 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200325 if (HAS_META(subelems[i].type)) {
326 free(subelems[i].dest);
327 }
328 }
329
330 free(subelems);
331}
332
David Sedlák26ea1432019-08-14 13:42:23 +0200333/**
334 * @brief Allocate subelems information on heap.
335 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200336 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200337 * @param[in] count Number of subelements.
338 * @param[in] parent Parent node if any.
339 * @param[out] result Allocated subelems array.
Michal Vasko193dacd2022-10-13 08:43:05 +0200340 * @return LY_ERR values.
David Sedlák26ea1432019-08-14 13:42:23 +0200341 */
David Sedlák81497a32019-08-13 16:56:26 +0200342static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200343subelems_allocator(struct lysp_yin_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200344 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200345{
346 va_list ap;
347
348 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200349 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200350
351 va_start(ap, result);
352 for (size_t i = 0; i < count; ++i) {
353 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200354 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200355 /* DEST */
356 if (IS_NODE_ELEM((*result)[i].type)) {
357 struct tree_node_meta *node_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200358
David Sedlák81497a32019-08-13 16:56:26 +0200359 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200360 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200361 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200362 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200363 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200364 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200365 struct import_meta *imp_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200366
David Sedlák81497a32019-08-13 16:56:26 +0200367 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200368 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200369 imp_meta->prefix = va_arg(ap, const char *);
370 imp_meta->imports = va_arg(ap, struct lysp_import **);
371 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200372 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200373 struct include_meta *inc_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200374
David Sedlák81497a32019-08-13 16:56:26 +0200375 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200376 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200377 inc_meta->name = va_arg(ap, const char *);
378 inc_meta->includes = va_arg(ap, struct lysp_include **);
379 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200380 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200381 struct inout_meta *inout_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200382
David Sedlák81497a32019-08-13 16:56:26 +0200383 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200384 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200385 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100386 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200387 (*result)[i].dest = inout_meta;
388 } else {
389 (*result)[i].dest = va_arg(ap, void *);
390 }
391 /* FLAGS */
392 (*result)[i].flags = va_arg(ap, int);
393 }
394 va_end(ap);
395
396 return LY_SUCCESS;
397
David Sedlákbf8a2b72019-08-14 16:48:10 +0200398mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200399 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100400 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200401 return LY_EMEM;
402}
403
Michal Vaskoafac7822020-10-20 14:22:26 +0200404/**
405 * @brief Check that val is valid UTF8 character sequence of val_type.
406 * Doesn't check empty string, only character validity.
407 *
408 * @param[in] ctx Yin parser context for logging.
409 * @param[in] val_type Type of the input string to select method of checking character validity.
Michal Vaskoafac7822020-10-20 14:22:26 +0200410 * @return LY_ERR values.
411 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200412LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200413yin_validate_value(struct lysp_yin_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200414{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200415 uint8_t prefix = 0;
416 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100417 size_t utf8_char_len, already_read = 0;
418 const char *val;
419
420 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
421
422 val = ctx->xmlctx->value;
423 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200424 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vaskod0625d72022-10-06 15:02:50 +0200425 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200426
427 switch (val_type) {
428 case Y_IDENTIF_ARG:
Michal Vaskod0625d72022-10-06 15:02:50 +0200429 LY_CHECK_RET(lysp_check_identifierchar((struct lysp_ctx *)ctx, c, already_read ? 0 : 1, NULL));
David Sedlák4a650532019-07-10 11:55:18 +0200430 break;
431 case Y_PREF_IDENTIF_ARG:
Michal Vaskod0625d72022-10-06 15:02:50 +0200432 LY_CHECK_RET(lysp_check_identifierchar((struct lysp_ctx *)ctx, c, already_read ? 0 : 1, &prefix));
David Sedlák4a650532019-07-10 11:55:18 +0200433 break;
434 case Y_STR_ARG:
435 case Y_MAYBE_STR_ARG:
Michal Vaskod0625d72022-10-06 15:02:50 +0200436 LY_CHECK_RET(lysp_check_stringchar((struct lysp_ctx *)ctx, c));
David Sedlák4a650532019-07-10 11:55:18 +0200437 break;
438 }
Radek Iša2eac74c2021-03-15 15:53:08 +0100439
440 already_read += utf8_char_len;
441 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200442 }
443
Radek Iša42cc0b72021-03-15 16:51:31 +0100444 if ((already_read == 0) &&
445 ((val_type == Y_PREF_IDENTIF_ARG) || (val_type == Y_IDENTIF_ARG))) {
446 /* Empty identifier or prefix*/
447 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Empty identifier is not allowed.");
448 return LY_EVALID;
449 }
450
David Sedlák4a650532019-07-10 11:55:18 +0200451 return LY_SUCCESS;
452}
453
David Sedlákb4e44562019-07-04 15:42:12 +0200454/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100455 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200456 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200457 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200458 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
459 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200460 * @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 +0200461 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200462 * @param[in] current_element Identification of current element, used for logging.
David Sedlákb4e44562019-07-04 15:42:12 +0200463 * @return LY_ERR values.
464 */
465static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200466yin_parse_attribute(struct lysp_yin_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200467 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200468{
David Sedlákc5b20842019-08-13 10:18:31 +0200469 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200470 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200471
David Sedlák1bccdfa2019-06-17 15:55:27 +0200472 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100473 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200474 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100475 if (!ctx->xmlctx->prefix) {
476 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200477 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100478 /* skip it */
479 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200480 } else if (arg == arg_type) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200481 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko193dacd2022-10-13 08:43:05 +0200482 yin_attr2str(arg), lyplg_ext_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200483 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100484
485 /* go to value */
486 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
487 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200488 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 +0200489 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200490 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +0200491 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko193dacd2022-10-13 08:43:05 +0200492 ctx->xmlctx->name, lyplg_ext_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200493 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200494 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100495 } else {
496 /* skip it */
497 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200498 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100499
500 /* next attribute */
501 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200502 }
503
David Sedlák292763b2019-07-09 11:10:53 +0200504 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200505 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200506 LOGVAL_PARSER((struct lysp_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko193dacd2022-10-13 08:43:05 +0200507 yin_attr2str(arg_type), lyplg_ext_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200508 return LY_EVALID;
509 }
510
511 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200512}
513
David Sedlákd6e56892019-07-01 15:40:24 +0200514/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200515 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200516 *
517 * @param[in] type Type of wanted record.
518 * @param[in] array_size Size of array.
519 * @param[in] array Searched array.
David Sedlákd6e56892019-07-01 15:40:24 +0200520 * @return Pointer to desired record on success, NULL if element is not in the array.
521 */
David Sedlákb4e44562019-07-04 15:42:12 +0200522static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200523get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200524{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200525 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200526 if (array[u].type == type) {
527 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200528 }
529 }
David Sedlákd6e56892019-07-01 15:40:24 +0200530 return NULL;
531}
532
David Sedlákbba38e52019-07-09 15:20:01 +0200533/**
534 * @brief Helper function to check mandatory constraint of subelement.
535 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200536 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200537 * @param[in] subelem_info Array of information about subelements.
538 * @param[in] subelem_info_size Size of subelem_info array.
539 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbba38e52019-07-09 15:20:01 +0200540 * @return LY_ERR values.
541 */
542static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200543yin_check_subelem_mandatory_constraint(struct lysp_yin_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)) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200549 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko193dacd2022-10-13 08:43:05 +0200550 lyplg_ext_stmt2str(subelem_info[i].type), lyplg_ext_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 * @return LY_ERR values.
567 */
568static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200569yin_check_subelem_first_constraint(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200570 signed char subelem_info_size, enum ly_stmt current_element,
571 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200572{
David Sedlákb0faad82019-07-04 14:28:59 +0200573 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200574 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200575 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko193dacd2022-10-13 08:43:05 +0200576 lyplg_ext_stmt2str(exp_first->type), lyplg_ext_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200577 return LY_EVALID;
578 }
579 }
580
581 return LY_SUCCESS;
582}
583
David Sedlákbba38e52019-07-09 15:20:01 +0200584/**
David Sedlákb4e44562019-07-04 15:42:12 +0200585 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
586 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200587 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200588 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +0200589 * @param[in] parent Current statement parent.
590 * @param[in] parent_stmt Type of @p parent statement.
David Sedlákb4e44562019-07-04 15:42:12 +0200591 * @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 Vasko193dacd2022-10-13 08:43:05 +0200598yin_parse_simple_element(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, 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{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100601 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200602 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
603 };
David Sedlákb4e44562019-07-04 15:42:12 +0200604
Michal Vasko193dacd2022-10-13 08:43:05 +0200605 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
606 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, parent_stmt));
607
608 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, parent_stmt, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200609}
610
611/**
David Sedlák6542aed2019-08-14 10:47:43 +0200612 * @brief Parse path element.
613 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200614 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200615 * @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 Vasko193dacd2022-10-13 08:43:05 +0200619yin_parse_path(struct lysp_yin_ctx *ctx, 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
Michal Vasko193dacd2022-10-13 08:43:05 +0200624 LY_CHECK_RET(yin_parse_simple_element(ctx, type, LY_STMT_PATH, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
625
Michal Vaskoed725d72021-06-23 12:03:45 +0200626 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +0200627 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200628 lydict_remove(ctx->xmlctx->ctx, str_path);
629 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200630 type->flags |= LYS_SET_PATH;
631
632 return LY_SUCCESS;
633}
634
635/**
Michal Vasko4929d5f2022-11-08 13:21:02 +0100636 * @brief Add extension array to context exts instances.
637 *
638 * @param[in] ctx YIN parser context.
639 * @param[in] exts Parsed extension array that is final (no realloc anymore).
640 * @return LY_ERR value.
641 */
642static LY_ERR
643yin_unres_exts_add(struct lysp_yin_ctx *ctx, struct lysp_ext_instance *exts)
644{
645 if (!exts) {
646 return LY_SUCCESS;
647 }
648
Michal Vaskoc8806c82022-12-06 10:31:24 +0100649 return ly_set_add(&ctx->main_ctx->ext_inst, exts, 1, NULL);
Michal Vasko4929d5f2022-11-08 13:21:02 +0100650}
651
652/**
David Sedlákd3983112019-07-12 11:20:56 +0200653 * @brief Parse pattern element.
654 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200655 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200656 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200657 * @return LY_ERR values.
658 */
659static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200660yin_parse_pattern(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200661{
662 const char *real_value = NULL;
663 char *saved_value = NULL;
664 struct lysp_restr *restr;
665
Michal Vaskob36053d2020-03-26 15:49:30 +0100666 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
667 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
668 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 +0200669 size_t len = strlen(real_value);
670
671 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100672 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200673 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100674 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100675 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200676 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200677 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100678 restr->arg.mod = PARSER_CUR_PMOD(ctx);
David Sedlákd3983112019-07-12 11:20:56 +0200679 type->flags |= LYS_SET_PATTERN;
680
Radek Krejcif13b87b2020-12-01 22:02:17 +0100681 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200682 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
683 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
684 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
685 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
686 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
687 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
688 };
Michal Vasko69730152020-10-09 16:30:07 +0200689
Michal Vasko193dacd2022-10-13 08:43:05 +0200690 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr, LY_STMT_PATTERN, NULL, &restr->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200691
692 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +0100693 LY_CHECK_RET(yin_unres_exts_add(ctx, restr->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200694
695 return LY_SUCCESS;
David Sedlákd3983112019-07-12 11:20:56 +0200696}
697
David Sedlákc5b20842019-08-13 10:18:31 +0200698/**
699 * @brief Parse fraction-digits element.
700 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200701 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200702 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200703 * @return LY_ERR values.
704 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200705static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200706yin_parse_fracdigits(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200707{
708 const char *temp_val = NULL;
709 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200710 unsigned long long int num;
David Sedlákf75d55e2019-07-12 16:52:50 +0200711
Michal Vaskob36053d2020-03-26 15:49:30 +0100712 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
713 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 +0200714
Michal Vasko69730152020-10-09 16:30:07 +0200715 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200716 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100717 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200718 return LY_EVALID;
719 }
720
721 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200722 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200723 if (*ptr != '\0') {
Michal Vaskod0625d72022-10-06 15:02:50 +0200724 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100725 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200726 return LY_EVALID;
727 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100728 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200729 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100730 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200731 return LY_EVALID;
732 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100733 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200734 type->fraction_digits = num;
735 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100736 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200737 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
738 };
Michal Vasko69730152020-10-09 16:30:07 +0200739
Michal Vasko193dacd2022-10-13 08:43:05 +0200740 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_FRACTION_DIGITS, NULL, &type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200741
742 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +0100743 LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200744
745 return LY_SUCCESS;
David Sedlákf75d55e2019-07-12 16:52:50 +0200746}
747
David Sedlák07869a52019-07-12 14:28:19 +0200748/**
David Sedlák43801c92019-08-05 15:58:54 +0200749 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200750 *
751 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200752 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200753 * @return LY_ERR values.
754 */
David Sedlákca36c422019-07-12 12:47:55 +0200755static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200756yin_parse_enum(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200757{
David Sedlák07869a52019-07-12 14:28:19 +0200758 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200759
Michal Vaskob36053d2020-03-26 15:49:30 +0100760 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200761 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100762 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
763 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
Michal Vaskod0625d72022-10-06 15:02:50 +0200764 LY_CHECK_RET(lysp_check_enum_name((struct lysp_ctx *)ctx, en->name, strlen(en->name)));
765 CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(en->name), "enum");
766 CHECK_UNIQUENESS((struct lysp_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200767
Radek Krejcif13b87b2020-12-01 22:02:17 +0100768 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200769 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
770 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
771 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
772 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
773 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
774 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
775 };
Michal Vasko69730152020-10-09 16:30:07 +0200776
Michal Vasko193dacd2022-10-13 08:43:05 +0200777 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), en, LY_STMT_ENUM, NULL, &en->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200778
779 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +0100780 LY_CHECK_RET(yin_unres_exts_add(ctx, en->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200781
782 return LY_SUCCESS;
David Sedlák43801c92019-08-05 15:58:54 +0200783}
784
785/**
786 * @brief Parse bit element.
787 *
788 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200789 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200790 * @return LY_ERR values.
791 */
792static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200793yin_parse_bit(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200794{
795 struct lysp_type_enum *en;
796
Michal Vaskob36053d2020-03-26 15:49:30 +0100797 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200798 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100799 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
800 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
Michal Vaskod0625d72022-10-06 15:02:50 +0200801 CHECK_UNIQUENESS((struct lysp_ctx *)ctx, type->bits, name, "bit", en->name);
David Sedlák43801c92019-08-05 15:58:54 +0200802
Radek Krejcif13b87b2020-12-01 22:02:17 +0100803 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200804 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
805 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
806 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
807 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
808 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
809 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
810 };
Michal Vasko69730152020-10-09 16:30:07 +0200811
Michal Vasko193dacd2022-10-13 08:43:05 +0200812 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), en, LY_STMT_BIT, NULL, &en->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200813
814 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +0100815 LY_CHECK_RET(yin_unres_exts_add(ctx, en->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200816
817 return LY_SUCCESS;
David Sedlákca36c422019-07-12 12:47:55 +0200818}
819
David Sedlákd3983112019-07-12 11:20:56 +0200820/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200821 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
822 * more instances, such as base or if-feature.
823 *
824 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +0200825 * @param[in] parent_stmt Type of parent statement.
David Sedlák5f8191e2019-07-08 16:35:52 +0200826 * @param[out] values Parsed values to add to.
827 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200828 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200829 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200830 * @return LY_ERR values.
831 */
832static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200833yin_parse_simple_elements(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, const char ***values,
834 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200835{
836 const char **value;
Michal Vasko193dacd2022-10-13 08:43:05 +0200837 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100838 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200839 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
840 };
David Sedlák968ac342019-07-11 15:17:59 +0200841
Michal Vasko193dacd2022-10-13 08:43:05 +0200842 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
David Sedlák5f8191e2019-07-08 16:35:52 +0200843
Michal Vasko193dacd2022-10-13 08:43:05 +0200844 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
845 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, parent_stmt));
846
847 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), *values, parent_stmt, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200848
849 return LY_SUCCESS;
David Sedlák5f8191e2019-07-08 16:35:52 +0200850}
851
852/**
David Sedlák6542aed2019-08-14 10:47:43 +0200853 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
854 *
855 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +0200856 * @param[in] parent Current statement parent.
857 * @param[in] parent_stmt Type of @p parent statement.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200858 * @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 +0200859 * @param[in] arg_type Expected type of attribute.
860 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200861 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200862 * @return LY_ERR values.
863 */
864static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200865yin_parse_simple_elem(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200866 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200867{
868 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200869 LY_CHECK_RET(yin_parse_simple_element(ctx, parent, parent_stmt, (const char **)subinfo->dest, arg_type,
870 arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200871 } else {
Michal Vasko193dacd2022-10-13 08:43:05 +0200872 LY_CHECK_RET(yin_parse_simple_elements(ctx, parent_stmt, (const char ***)subinfo->dest, arg_type,
873 arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200874 }
875
876 return LY_SUCCESS;
877}
878
879/**
880 * @brief Parse base element.
881 *
882 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +0200883 * @param[in] parent_stmt Type of parent statement.
David Sedlák6542aed2019-08-14 10:47:43 +0200884 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200885 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200886 * @return LY_ERR values.
887 */
888static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200889yin_parse_base(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, void *dest, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200890{
Michal Vasko193dacd2022-10-13 08:43:05 +0200891 struct lysp_type *type;
David Sedlák6542aed2019-08-14 10:47:43 +0200892
Michal Vasko193dacd2022-10-13 08:43:05 +0200893 if (parent_stmt == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200894 type = (struct lysp_type *)dest;
Michal Vasko193dacd2022-10-13 08:43:05 +0200895 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200896 type->flags |= LYS_SET_BASE;
Michal Vasko193dacd2022-10-13 08:43:05 +0200897 } else if (parent_stmt == LY_STMT_IDENTITY) {
898 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest, YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200899 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100900 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200901 return LY_EINT;
902 }
903
904 return LY_SUCCESS;
905}
906
907/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200908 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200909 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200910 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100911 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200912 * @return LY_ERR values.
913 */
914static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200915yin_pasrse_reqinstance(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200916{
917 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100918 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200919 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
920 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200921
922 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100923 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
924 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 +0200925 if (strcmp(temp_val, "true") == 0) {
926 type->require_instance = 1;
927 } else if (strcmp(temp_val, "false") != 0) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200928 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200929 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100930 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200931 return LY_EVALID;
932 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100933 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200934
Michal Vasko193dacd2022-10-13 08:43:05 +0200935 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200936
937 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +0100938 LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200939
940 return LY_SUCCESS;
David Sedlákcf5569a2019-07-11 13:31:34 +0200941}
942
943/**
David Sedlákce77bf52019-07-11 16:59:31 +0200944 * @brief Parse modifier element.
945 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200946 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +0200947 * @param[in] parent Current statement parent.
David Sedlákce77bf52019-07-11 16:59:31 +0200948 * @param[in,out] pat Value to write to.
949 * @param[in,out] exts Extension instances to add to.
David Sedlákce77bf52019-07-11 16:59:31 +0200950 * @return LY_ERR values.
951 */
952static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +0200953yin_parse_modifier(struct lysp_yin_ctx *ctx, const void *parent, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200954{
955 const char *temp_val;
956 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100957 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200958 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
959 };
David Sedlákce77bf52019-07-11 16:59:31 +0200960
Michal Vasko193dacd2022-10-13 08:43:05 +0200961 assert(**pat == 0x06);
962
Michal Vaskob36053d2020-03-26 15:49:30 +0100963 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
964 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 +0200965 if (strcmp(temp_val, "invert-match") != 0) {
Michal Vaskod0625d72022-10-06 15:02:50 +0200966 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200967 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100968 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200969 return LY_EVALID;
970 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100971 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200972
973 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200974 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100975 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200976 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100977 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200978
979 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100980 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200981 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200982
Michal Vasko193dacd2022-10-13 08:43:05 +0200983 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_MODIFIER, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200984
985 return LY_SUCCESS;
David Sedlákce77bf52019-07-11 16:59:31 +0200986}
987
988/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200989 * @brief Parse a restriction element (length, range or one instance of must).
990 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200991 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200992 * @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 +0200993 * @param[in] restr Value to write to.
Michal Vasko193dacd2022-10-13 08:43:05 +0200994 * @return LY_ERR values.
David Sedlákb7296dd2019-07-11 14:58:38 +0200995 */
996static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +0200997yin_parse_restriction(struct lysp_yin_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200998{
Radek Krejcif13b87b2020-12-01 22:02:17 +0100999 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001000 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
1001 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
1002 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
1003 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
1004 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1005 };
David Sedlákb7296dd2019-07-11 14:58:38 +02001006 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +02001007 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +02001008
Michal Vasko193dacd2022-10-13 08:43:05 +02001009 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
1010
Michal Vaskob36053d2020-03-26 15:49:30 +01001011 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +02001012 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001013 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Michal Vaskob36053d2020-03-26 15:49:30 +01001014
Michal Vasko193dacd2022-10-13 08:43:05 +02001015 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr, restr_kw, NULL, &restr->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001016
1017 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001018 LY_CHECK_RET(yin_unres_exts_add(ctx, restr->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001019
1020 return LY_SUCCESS;
David Sedlákb7296dd2019-07-11 14:58:38 +02001021}
1022
1023/**
David Sedlák6542aed2019-08-14 10:47:43 +02001024 * @brief Parse range element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001025 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001026 * @param[out] type Type structure to store parsed value and flags.
David Sedlák6542aed2019-08-14 10:47:43 +02001027 * @return LY_ERR values.
1028 */
1029static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001030yin_parse_range(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +02001031{
1032 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001033 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1034 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +02001035 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +02001036
1037 return LY_SUCCESS;
1038}
1039
1040/**
1041 * @brief Parse length element.
1042 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001043 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001044 * @param[out] type Type structure to store parsed value and flags.
David Sedlák6542aed2019-08-14 10:47:43 +02001045 * @return LY_ERR values.
1046 */
1047static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001048yin_parse_length(struct lysp_yin_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +02001049{
1050 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001051 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1052 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +02001053 type->flags |= LYS_SET_LENGTH;
1054
1055 return LY_SUCCESS;
1056}
1057
1058/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001059 * @brief Parse must element.
1060 *
1061 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001062 * @param[in,out] restrs Restrictions to add to.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001063 * @return LY_ERR values.
1064 */
1065static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001066yin_parse_must(struct lysp_yin_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001067{
1068 struct lysp_restr *restr;
1069
Michal Vaskob36053d2020-03-26 15:49:30 +01001070 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1071 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001072}
1073
1074/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001075 * @brief Parse a node id into an array.
1076 *
1077 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001078 * @param[in] parent_stmt Type of parent statement.
Michal Vasko7f45cf22020-10-01 12:49:44 +02001079 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1080 * @param[in,out] exts Extension instances to add to.
Michal Vasko7f45cf22020-10-01 12:49:44 +02001081 * @return LY_ERR values.
1082 */
1083static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001084yin_parse_qname(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct yin_subelement *subinfo,
Michal Vasko7f45cf22020-10-01 12:49:44 +02001085 struct lysp_ext_instance **exts)
1086{
1087 struct lysp_qname *qname, **qnames;
1088
Michal Vasko193dacd2022-10-13 08:43:05 +02001089 switch (parent_stmt) {
Michal Vasko7f45cf22020-10-01 12:49:44 +02001090 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001091 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1092 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001093 } else {
1094 qnames = (struct lysp_qname **)subinfo->dest;
1095 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001096 }
Michal Vasko8a67eff2021-12-07 14:04:47 +01001097 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko193dacd2022-10-13 08:43:05 +02001098 return yin_parse_simple_element(ctx, qname, parent_stmt, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
Radek Išabe8a6532021-03-29 08:54:22 +02001099 case LY_STMT_UNIQUE:
1100 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
Michal Vasko193dacd2022-10-13 08:43:05 +02001101
Radek Išabe8a6532021-03-29 08:54:22 +02001102 qnames = (struct lysp_qname **)subinfo->dest;
1103 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001104 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko193dacd2022-10-13 08:43:05 +02001105 return yin_parse_simple_element(ctx, *qnames, parent_stmt, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001106 case LY_STMT_IF_FEATURE:
1107 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
Michal Vasko193dacd2022-10-13 08:43:05 +02001108
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001109 qnames = (struct lysp_qname **)subinfo->dest;
1110 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001111 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko193dacd2022-10-13 08:43:05 +02001112 return yin_parse_simple_element(ctx, *qnames, parent_stmt, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001113 default:
1114 break;
1115 }
1116
1117 LOGINT(ctx->xmlctx->ctx);
1118 return LY_EINT;
1119}
1120
1121/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001122 * @brief Parse position or value element.
1123 *
1124 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001125 * @param[in] parent_stmt Type of parent statement.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001126 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001127 * @return LY_ERR values.
1128 */
1129static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001130yin_parse_value_pos(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +02001131{
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001132 LY_ERR ret = LY_SUCCESS;
David Sedlák5545f5d2019-07-11 11:55:16 +02001133 const char *temp_val = NULL;
1134 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001135 long long int num = 0;
1136 unsigned long long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001137
Michal Vasko193dacd2022-10-13 08:43:05 +02001138 assert(parent_stmt == LY_STMT_POSITION || parent_stmt == LY_STMT_VALUE);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001139
David Sedlák5545f5d2019-07-11 11:55:16 +02001140 /* set value flag */
1141 enm->flags |= LYS_SET_VALUE;
1142
1143 /* get attribute value */
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001144 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
Michal Vasko193dacd2022-10-13 08:43:05 +02001145 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, parent_stmt), cleanup);
Michal Vasko69730152020-10-09 16:30:07 +02001146 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Michal Vasko193dacd2022-10-13 08:43:05 +02001147 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((parent_stmt == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
1148 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001149 ret = LY_EVALID;
1150 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001151 }
1152
1153 /* convert value */
1154 errno = 0;
Michal Vasko193dacd2022-10-13 08:43:05 +02001155 if (parent_stmt == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001156 num = strtoll(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001157 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001158 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001159 ret = LY_EVALID;
1160 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001161 }
1162 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001163 unum = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001164 if (unum > UINT64_C(4294967295)) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001165 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001166 ret = LY_EVALID;
1167 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001168 }
1169 }
1170 /* check if whole argument value was converted */
1171 if (*ptr != '\0') {
Michal Vasko193dacd2022-10-13 08:43:05 +02001172 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001173 ret = LY_EVALID;
1174 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001175 }
1176 if (errno == ERANGE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02001177 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001178 ret = LY_EVALID;
1179 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001180 }
1181 /* save correctly ternary operator can't be used because num and unum have different signes */
Michal Vasko193dacd2022-10-13 08:43:05 +02001182 if (parent_stmt == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001183 enm->value = num;
1184 } else {
1185 enm->value = unum;
1186 }
David Sedlák5545f5d2019-07-11 11:55:16 +02001187
1188 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001189 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001190 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1191 };
Michal Vasko69730152020-10-09 16:30:07 +02001192
Michal Vasko193dacd2022-10-13 08:43:05 +02001193 LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), enm, parent_stmt, NULL, &enm->exts), cleanup);
David Sedlák5545f5d2019-07-11 11:55:16 +02001194
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001195 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001196 LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, enm->exts), cleanup);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001197
1198cleanup:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001199 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001200 return ret;
David Sedlák5545f5d2019-07-11 11:55:16 +02001201}
1202
David Sedlák05404f62019-07-24 14:11:53 +02001203/**
1204 * @brief Parse belongs-to element.
1205 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001206 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001207 * @param[out] submod Structure of submodule that is being parsed.
1208 * @param[in,out] exts Extension instances to add to.
David Sedlák05404f62019-07-24 14:11:53 +02001209 * @return LY_ERR values
1210 */
1211static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001212yin_parse_belongs_to(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod, struct lysp_ext_instance **exts)
David Sedlák05404f62019-07-24 14:11:53 +02001213{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001214 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001215 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001216 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1217 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1218 };
David Sedlák05404f62019-07-24 14:11:53 +02001219
Michal Vaskob36053d2020-03-26 15:49:30 +01001220 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001221 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
Michal Vasko8a67eff2021-12-07 14:04:47 +01001222 if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001223 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
Michal Vasko8a67eff2021-12-07 14:04:47 +01001224 belongsto, PARSER_CUR_PMOD(ctx)->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001225 lydict_remove(ctx->xmlctx->ctx, belongsto);
1226 return LY_EVALID;
1227 }
1228 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001229
Michal Vasko193dacd2022-10-13 08:43:05 +02001230 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), submod, LY_STMT_BELONGS_TO, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001231
1232 return LY_SUCCESS;
David Sedlák05404f62019-07-24 14:11:53 +02001233}
1234
David Sedlák5545f5d2019-07-11 11:55:16 +02001235/**
David Sedlákc1771b12019-07-10 15:55:46 +02001236 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001237 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001238 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001239 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001240 * @param[in] parent Current statement parent.
1241 * @param[in] parent_stmt Type of @p parent statement.
David Sedlákb4e44562019-07-04 15:42:12 +02001242 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001243 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001244 * @return LY_ERR values.
1245 */
1246static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001247yin_parse_meta(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, const char **value,
1248 struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001249{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001250 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001251 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1252 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1253 };
Michal Vasko69730152020-10-09 16:30:07 +02001254
Michal Vasko193dacd2022-10-13 08:43:05 +02001255 assert(parent_stmt == LY_STMT_ORGANIZATION || parent_stmt == LY_STMT_CONTACT || parent_stmt == LY_STMT_DESCRIPTION ||
1256 parent_stmt == LY_STMT_REFERENCE);
1257
David Sedlákdf2a9732019-08-07 13:23:16 +02001258 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001259 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko193dacd2022-10-13 08:43:05 +02001260 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, parent_stmt));
David Sedlákb4e44562019-07-04 15:42:12 +02001261
David Sedlákdf2a9732019-08-07 13:23:16 +02001262 /* parse content */
Michal Vasko193dacd2022-10-13 08:43:05 +02001263 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, parent_stmt, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001264
1265 return LY_SUCCESS;
David Sedlákb4e44562019-07-04 15:42:12 +02001266}
1267
1268/**
David Sedlákc1771b12019-07-10 15:55:46 +02001269 * @brief Parse error-message element.
1270 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001271 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001272 * @param[in] parent Current statement parent.
David Sedlákc1771b12019-07-10 15:55:46 +02001273 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001274 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001275 * @return LY_ERR values.
1276 */
1277static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001278yin_parse_err_msg(struct lysp_yin_ctx *ctx, const void *parent, const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001279{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001280 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001281 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1282 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1283 };
David Sedlákc1771b12019-07-10 15:55:46 +02001284
David Sedlákdf2a9732019-08-07 13:23:16 +02001285 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001286 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1287 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 +02001288
Michal Vasko193dacd2022-10-13 08:43:05 +02001289 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ERROR_MESSAGE, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001290
1291 return LY_SUCCESS;
David Sedlákc1771b12019-07-10 15:55:46 +02001292}
1293
1294/**
David Sedlák6542aed2019-08-14 10:47:43 +02001295 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001296 *
1297 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001298 * @param[in] parent_stmt Type of parent statement.
1299 * @param[in,out] subinfo Information about subelement, is used to determin which function should be called and where
1300 * to store parsed value.
David Sedlák374d2b32019-07-17 15:06:55 +02001301 * @return LY_ERR values.
1302 */
1303static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001304yin_parse_type(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001305{
David Sedlák6542aed2019-08-14 10:47:43 +02001306 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001307
Michal Vasko193dacd2022-10-13 08:43:05 +02001308 if (parent_stmt == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001309 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001310 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001311 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001312 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001313 type = (struct lysp_type *)subinfo->dest;
1314 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001315
David Sedlák6542aed2019-08-14 10:47:43 +02001316 /* type as child of another type */
Michal Vasko193dacd2022-10-13 08:43:05 +02001317 if (parent_stmt == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001318 struct lysp_type *nested_type = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +02001319
Michal Vaskob36053d2020-03-26 15:49:30 +01001320 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001321 type->flags |= LYS_SET_TYPE;
1322 type = nested_type;
1323 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001324
Michal Vasko8a67eff2021-12-07 14:04:47 +01001325 type->pmod = PARSER_CUR_PMOD(ctx);
Michal Vasko5bbcc242021-02-23 09:29:13 +01001326
Radek Krejcif13b87b2020-12-01 22:02:17 +01001327 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001328 {LY_STMT_BASE, type, 0},
1329 {LY_STMT_BIT, type, 0},
1330 {LY_STMT_ENUM, type, 0},
1331 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1332 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1333 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_PATTERN, type, 0},
1335 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
Michal Vasko608b0c02021-09-23 08:26:53 +02001337 {LY_STMT_TYPE, type, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001338 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1339 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001340
1341 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1342 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
Michal Vasko193dacd2022-10-13 08:43:05 +02001343 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_TYPE, NULL, &type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001344
1345 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001346 LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001347
1348 return LY_SUCCESS;
David Sedlák374d2b32019-07-17 15:06:55 +02001349}
1350
David Sedlák1af868e2019-07-17 17:03:14 +02001351/**
1352 * @brief Parse max-elements element.
1353 *
1354 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001355 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001356 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001357 * @param[in,out] exts Extension instances to add to.
David Sedlák1af868e2019-07-17 17:03:14 +02001358 * @return LY_ERR values.
1359 */
1360static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001361yin_parse_maxelements(struct lysp_yin_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák1af868e2019-07-17 17:03:14 +02001362{
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001363 LY_ERR ret = LY_SUCCESS;
David Sedlák1af868e2019-07-17 17:03:14 +02001364 const char *temp_val = NULL;
1365 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001366 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001367 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001368 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1369 };
David Sedlák374d2b32019-07-17 15:06:55 +02001370
David Sedlák1af868e2019-07-17 17:03:14 +02001371 *flags |= LYS_SET_MAX;
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001372 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
1373 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS), cleanup);
Michal Vasko69730152020-10-09 16:30:07 +02001374 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '0') || ((temp_val[0] != 'u') && !isdigit(temp_val[0]))) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001375 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001376 ret = LY_EVALID;
1377 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001378 }
1379
1380 if (strcmp(temp_val, "unbounded")) {
1381 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001382 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001383 if (*ptr != '\0') {
Michal Vaskod0625d72022-10-06 15:02:50 +02001384 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001385 ret = LY_EVALID;
1386 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001387 }
1388 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001389 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001390 ret = LY_EVALID;
1391 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001392 }
1393 *max = num;
1394 }
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001395
Michal Vasko193dacd2022-10-13 08:43:05 +02001396 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), max, LY_STMT_MAX_ELEMENTS, NULL, exts);
1397 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001398
1399cleanup:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001400 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001401 return ret;
David Sedlák1af868e2019-07-17 17:03:14 +02001402}
David Sedlák374d2b32019-07-17 15:06:55 +02001403
1404/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001405 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001406 *
1407 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001408 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001409 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001410 * @param[in,out] exts Extension instances to add to.
David Sedlák09e18c92019-07-18 11:17:11 +02001411 * @return LY_ERR values.
1412 */
1413static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001414yin_parse_minelements(struct lysp_yin_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák09e18c92019-07-18 11:17:11 +02001415{
1416 const char *temp_val = NULL;
1417 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001418 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001419 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001420 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1421 };
David Sedlák09e18c92019-07-18 11:17:11 +02001422
1423 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001424 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1425 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 +02001426
Michal Vasko69730152020-10-09 16:30:07 +02001427 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001428 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001429 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001430 return LY_EVALID;
1431 }
1432
1433 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001434 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001435 if (ptr[0] != 0) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001436 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001437 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001438 return LY_EVALID;
1439 }
Michal Vasko69730152020-10-09 16:30:07 +02001440 if ((errno == ERANGE) || (num > UINT32_MAX)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001441 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001442 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001443 return LY_EVALID;
1444 }
1445 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001446 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vasko193dacd2022-10-13 08:43:05 +02001447 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), min, LY_STMT_MIN_ELEMENTS, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001448
1449 return LY_SUCCESS;
David Sedlák09e18c92019-07-18 11:17:11 +02001450}
1451
David Sedláka2dad212019-07-18 12:45:19 +02001452/**
1453 * @brief Parse min-elements or max-elements element.
1454 *
1455 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001456 * @param[in] parent_stmt Type of parent statement.
1457 * @param[in] cur_stmt Type of current element.
David Sedláka2dad212019-07-18 12:45:19 +02001458 * @param[in] dest Where the parsed value and flags should be stored.
David Sedláka2dad212019-07-18 12:45:19 +02001459 * @return LY_ERR values.
1460 */
David Sedlák09e18c92019-07-18 11:17:11 +02001461static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001462yin_parse_minmax(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, enum ly_stmt cur_stmt, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001463{
David Sedlák09e18c92019-07-18 11:17:11 +02001464 uint32_t *lim;
1465 uint16_t *flags;
1466 struct lysp_ext_instance **exts;
1467
Michal Vasko193dacd2022-10-13 08:43:05 +02001468 assert(cur_stmt == LY_STMT_MAX_ELEMENTS || cur_stmt == LY_STMT_MIN_ELEMENTS);
1469 assert(parent_stmt == LY_STMT_LEAF_LIST || parent_stmt == LY_STMT_REFINE || parent_stmt == LY_STMT_LIST ||
1470 parent_stmt == LY_STMT_DEVIATE);
1471
1472 if (parent_stmt == LY_STMT_LEAF_LIST) {
1473 lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001474 flags = &((struct lysp_node_leaflist *)dest)->flags;
1475 exts = &((struct lysp_node_leaflist *)dest)->exts;
Michal Vasko193dacd2022-10-13 08:43:05 +02001476 } else if (parent_stmt == LY_STMT_REFINE) {
1477 lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001478 flags = &((struct lysp_refine *)dest)->flags;
1479 exts = &((struct lysp_refine *)dest)->exts;
Michal Vasko193dacd2022-10-13 08:43:05 +02001480 } else if (parent_stmt == LY_STMT_LIST) {
1481 lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001482 flags = &((struct lysp_node_list *)dest)->flags;
1483 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001484 } else {
1485 lim = ((struct minmax_dev_meta *)dest)->lim;
1486 flags = ((struct minmax_dev_meta *)dest)->flags;
1487 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001488 }
1489
Michal Vasko193dacd2022-10-13 08:43:05 +02001490 if (cur_stmt == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001491 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001492 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001493 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001494 }
1495
1496 return LY_SUCCESS;
1497}
1498
1499/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001500 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001501 *
1502 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001503 * @param[in] parent Current statement parent.
David Sedláka2dad212019-07-18 12:45:19 +02001504 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001505 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001506 * @return LY_ERR values.
1507 */
1508static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001509yin_parse_orderedby(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001510{
1511 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001512 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001513 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1514 };
David Sedláka2dad212019-07-18 12:45:19 +02001515
Michal Vaskob36053d2020-03-26 15:49:30 +01001516 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1517 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
David Sedláka2dad212019-07-18 12:45:19 +02001518 if (strcmp(temp_val, "system") == 0) {
1519 *flags |= LYS_ORDBY_SYSTEM;
1520 } else if (strcmp(temp_val, "user") == 0) {
1521 *flags |= LYS_ORDBY_USER;
1522 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02001523 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001524 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001525 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001526 return LY_EVALID;
1527 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001528 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001529
Michal Vasko193dacd2022-10-13 08:43:05 +02001530 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ORDERED_BY, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001531
1532 return LY_SUCCESS;
David Sedláka2dad212019-07-18 12:45:19 +02001533}
1534
1535/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001536 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001537 *
1538 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001539 * @param[in] any_stmt Type of current statement, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
David Sedlákad83cf92019-08-13 12:53:53 +02001540 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001541 * @return LY_ERR values.
1542 */
1543static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001544yin_parse_any(struct lysp_yin_ctx *ctx, enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001545{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001546 struct lysp_node_anydata *any;
1547
David Sedlák8d552d62019-08-06 15:29:05 +02001548 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001549 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001550 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001551 any->parent = node_meta->parent;
1552
David Sedlákbf8a2b72019-08-14 16:48:10 +02001553 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001554 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1555 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 +02001556
Radek Krejcif13b87b2020-12-01 22:02:17 +01001557 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001558 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1559 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1560 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1561 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1562 {LY_STMT_MUST, &any->musts, 0},
1563 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1564 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1565 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1566 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1567 };
Michal Vasko69730152020-10-09 16:30:07 +02001568
Michal Vasko193dacd2022-10-13 08:43:05 +02001569 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any, any_kw, NULL, &any->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001570
1571 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001572 LY_CHECK_RET(yin_unres_exts_add(ctx, any->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001573
1574 return LY_SUCCESS;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001575}
1576
1577/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001578 * @brief parse leaf element.
1579 *
1580 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001581 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001582 * @return LY_ERR values.
1583 */
1584static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001585yin_parse_leaf(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001586{
David Sedlák203ca3a2019-07-18 15:26:25 +02001587 struct lysp_node_leaf *leaf;
1588
David Sedlák8d552d62019-08-06 15:29:05 +02001589 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001590 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001591 leaf->nodetype = LYS_LEAF;
1592 leaf->parent = node_meta->parent;
1593
David Sedlák203ca3a2019-07-18 15:26:25 +02001594 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001595 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1596 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 +02001597
1598 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001599 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001600 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1601 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1602 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1603 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1604 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1605 {LY_STMT_MUST, &leaf->musts, 0},
1606 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1607 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1608 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1609 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1610 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1611 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1612 };
Michal Vasko69730152020-10-09 16:30:07 +02001613
Michal Vasko193dacd2022-10-13 08:43:05 +02001614 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), leaf, LY_STMT_LEAF, NULL, &leaf->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001615
1616 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001617 LY_CHECK_RET(yin_unres_exts_add(ctx, leaf->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001618
1619 return LY_SUCCESS;
David Sedlák203ca3a2019-07-18 15:26:25 +02001620}
1621
1622/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001623 * @brief Parse leaf-list element.
1624 *
1625 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001626 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001627 * @return LY_ERR values.
1628 */
1629static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001630yin_parse_leaflist(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001631{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001632 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001633
Michal Vaskob36053d2020-03-26 15:49:30 +01001634 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001635
David Sedlákc3da3ef2019-07-19 12:56:08 +02001636 llist->nodetype = LYS_LEAFLIST;
1637 llist->parent = node_meta->parent;
1638
David Sedlákc3da3ef2019-07-19 12:56:08 +02001639 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001640 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1641 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 +02001642
1643 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001644 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001645 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1646 {LY_STMT_DEFAULT, &llist->dflts, 0},
1647 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1648 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1649 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1650 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1651 {LY_STMT_MUST, &llist->musts, 0},
1652 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1653 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1654 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1655 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1656 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1657 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1658 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1659 };
Michal Vasko69730152020-10-09 16:30:07 +02001660
Michal Vasko193dacd2022-10-13 08:43:05 +02001661 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), llist, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001662
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001663 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001664 LY_CHECK_RET(yin_unres_exts_add(ctx, llist->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001665
David Sedlákbf8a2b72019-08-14 16:48:10 +02001666 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001667 if ((llist->min) && (llist->dflts)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001668 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001669 return LY_EVALID;
1670 }
Michal Vasko69730152020-10-09 16:30:07 +02001671 if (llist->max && (llist->min > llist->max)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001672 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001673 return LY_EVALID;
1674 }
1675
1676 return LY_SUCCESS;
1677}
1678
1679/**
David Sedlák04e17b22019-07-19 15:29:48 +02001680 * @brief Parse typedef element.
1681 *
1682 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001683 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001684 * @return LY_ERR values.
1685 */
1686static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001687yin_parse_typedef(struct lysp_yin_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001688{
1689 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001690 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001691
Michal Vaskob36053d2020-03-26 15:49:30 +01001692 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001693
1694 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001695 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1696 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 +02001697
1698 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001699 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001700 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1701 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1702 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1703 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1704 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1705 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1706 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1707 };
Michal Vasko69730152020-10-09 16:30:07 +02001708
Michal Vasko193dacd2022-10-13 08:43:05 +02001709 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), tpdf, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001710
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001711 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001712 LY_CHECK_RET(yin_unres_exts_add(ctx, tpdf->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001713
David Sedlák04e17b22019-07-19 15:29:48 +02001714 /* store data for collision check */
aPiecek75b83a02021-06-29 10:34:38 +02001715 if (typedef_meta->parent) {
aPiecek8d4e75d2021-06-24 14:47:06 +02001716 assert(ctx->main_ctx);
1717 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001718 }
1719
1720 return LY_SUCCESS;
1721}
1722
1723/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001724 * @brief Parse refine element.
1725 *
1726 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001727 * @param[in,out] refines Refines to add to.
David Sedlákd2d676a2019-07-22 11:28:19 +02001728 * @return LY_ERR values.
1729 */
1730static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001731yin_parse_refine(struct lysp_yin_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001732{
1733 struct lysp_refine *rf;
1734
1735 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001736 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001737
1738 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001739 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1740 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1741 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001742
1743 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001744 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001745 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001746 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001747 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001748 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001749 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1750 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1751 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1752 {LY_STMT_MUST, &rf->musts, 0},
1753 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1754 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1755 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1756 };
Michal Vasko69730152020-10-09 16:30:07 +02001757
Michal Vasko193dacd2022-10-13 08:43:05 +02001758 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rf, LY_STMT_REFINE, NULL, &rf->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001759
1760 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001761 LY_CHECK_RET(yin_unres_exts_add(ctx, rf->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001762
1763 return LY_SUCCESS;
David Sedlákd2d676a2019-07-22 11:28:19 +02001764}
1765
1766/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001767 * @brief Parse uses element.
1768 *
1769 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001770 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001771 * @return LY_ERR values.
1772 */
1773static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001774yin_parse_uses(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001775{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001776 struct lysp_node_uses *uses;
1777
David Sedlák8d552d62019-08-06 15:29:05 +02001778 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001779 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001780 uses->nodetype = LYS_USES;
1781 uses->parent = node_meta->parent;
1782
David Sedlák0d6de5a2019-07-22 13:25:44 +02001783 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001784 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1785 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 +02001786
1787 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001788 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001789 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001790 {LY_STMT_AUGMENT, &augments, 0},
1791 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1792 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1793 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1794 {LY_STMT_REFINE, &uses->refines, 0},
1795 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1796 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1797 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1798 };
Michal Vasko69730152020-10-09 16:30:07 +02001799
Michal Vasko193dacd2022-10-13 08:43:05 +02001800 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), uses, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001801
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001802 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001803 LY_CHECK_RET(yin_unres_exts_add(ctx, uses->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001804
David Sedlák0d6de5a2019-07-22 13:25:44 +02001805 return LY_SUCCESS;
1806}
1807
1808/**
David Sedlákaa854b02019-07-22 14:17:10 +02001809 * @brief Parse revision element.
1810 *
1811 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001812 * @param[in,out] revs Parsed revisions to add to.
David Sedlákaa854b02019-07-22 14:17:10 +02001813 * @return LY_ERR values.
1814 */
1815static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001816yin_parse_revision(struct lysp_yin_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001817{
1818 struct lysp_revision *rev;
1819 const char *temp_date = NULL;
1820
1821 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001822 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001823
1824 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001825 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1826 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 +02001827 /* check value */
Michal Vaskod0625d72022-10-06 15:02:50 +02001828 if (lysp_check_date((struct lysp_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001829 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001830 return LY_EVALID;
1831 }
Radek Krejci36642162021-01-12 16:49:22 +01001832 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001833 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001834
1835 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001836 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001837 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1838 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1839 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1840 };
Michal Vasko69730152020-10-09 16:30:07 +02001841
Michal Vasko193dacd2022-10-13 08:43:05 +02001842 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION, NULL, &rev->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001843
1844 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001845 LY_CHECK_RET(yin_unres_exts_add(ctx, rev->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001846
1847 return LY_SUCCESS;
David Sedlákaa854b02019-07-22 14:17:10 +02001848}
1849
David Sedlák5e13dea2019-07-22 16:06:45 +02001850/**
1851 * @brief Parse include element.
1852 *
1853 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001854 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
David Sedlák5e13dea2019-07-22 16:06:45 +02001855 * @return LY_ERR values.
1856 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001857static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001858yin_parse_include(struct lysp_yin_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001859{
1860 struct lysp_include *inc;
1861
1862 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001863 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001864
1865 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001866 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1867 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 +02001868
1869 /* submodules share the namespace with the module names, so there must not be
1870 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001871 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02001872 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001873 return LY_EVALID;
1874 }
1875
1876 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001877 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001878 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1879 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1880 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1881 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1882 };
Michal Vasko69730152020-10-09 16:30:07 +02001883
Michal Vasko193dacd2022-10-13 08:43:05 +02001884 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), inc, LY_STMT_INCLUDE, NULL, &inc->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001885
1886 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01001887 LY_CHECK_RET(yin_unres_exts_add(ctx, inc->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001888
1889 return LY_SUCCESS;
David Sedlák0c2bab92019-07-22 15:33:19 +02001890}
1891
David Sedlákaa854b02019-07-22 14:17:10 +02001892/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001893 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001894 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001895 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001896 * @param[in,out] rev Array to store the parsed value in.
1897 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001898 * @return LY_ERR values.
1899 */
1900static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001901yin_parse_revision_date(struct lysp_yin_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001902{
1903 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001904 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001905 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1906 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001907
Michal Vaskob36053d2020-03-26 15:49:30 +01001908 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1909 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
Michal Vaskod0625d72022-10-06 15:02:50 +02001910 LY_CHECK_ERR_RET(lysp_check_date((struct lysp_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskoe180ed02021-02-05 16:31:20 +01001911 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001912
1913 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001914 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001915
Michal Vasko193dacd2022-10-13 08:43:05 +02001916 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION_DATE, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001917
1918 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001919}
1920
1921/**
1922 * @brief Parse config element.
1923 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001924 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001925 * @param[in,out] flags Flags to add to.
1926 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001927 * @return LY_ERR values.
1928 */
1929static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02001930yin_parse_config(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001931{
1932 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001933 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001934 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1935 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001936
Michal Vaskob36053d2020-03-26 15:49:30 +01001937 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1938 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
David Sedlákdfbbb442019-08-06 16:33:21 +02001939 if (strcmp(temp_val, "true") == 0) {
1940 *flags |= LYS_CONFIG_W;
1941 } else if (strcmp(temp_val, "false") == 0) {
1942 *flags |= LYS_CONFIG_R;
1943 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02001944 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001945 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001946 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001947 return LY_EVALID;
1948 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001949 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001950
Michal Vasko193dacd2022-10-13 08:43:05 +02001951 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_CONFIG, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001952
1953 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001954}
1955
1956/**
1957 * @brief Parse yang-version element.
1958 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001959 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02001960 * @param[in] parent Current statement parent.
David Sedlákdfbbb442019-08-06 16:33:21 +02001961 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001962 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001963 * @return LY_ERR values.
1964 */
1965static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02001966yin_parse_yangversion(struct lysp_yin_ctx *ctx, const void *parent, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001967{
1968 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001969 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001970 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1971 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001972
Michal Vaskob36053d2020-03-26 15:49:30 +01001973 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1974 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 +02001975 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001976 *version = LYS_VERSION_1_0;
1977 } else if (strcmp(temp_version, "1.1") == 0) {
1978 *version = LYS_VERSION_1_1;
1979 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02001980 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001981 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001982 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001983 return LY_EVALID;
1984 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001985 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001986
Michal Vasko193dacd2022-10-13 08:43:05 +02001987 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YANG_VERSION, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001988
1989 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001990}
1991
1992/**
1993 * @brief Parse import element.
1994 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001995 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001996 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001997 * @return LY_ERR values.
1998 */
1999static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002000yin_parse_import(struct lysp_yin_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02002001{
2002 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02002003
David Sedlákdfbbb442019-08-06 16:33:21 +02002004 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01002005 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02002006
Radek Krejcif13b87b2020-12-01 22:02:17 +01002007 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002008 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2009 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2010 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2011 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2012 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2013 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002014
2015 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002016 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2017 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
Michal Vasko193dacd2022-10-13 08:43:05 +02002018 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), imp, LY_STMT_IMPORT, NULL, &imp->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002019
2020 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002021 LY_CHECK_RET(yin_unres_exts_add(ctx, imp->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002022
David Sedlákdfbbb442019-08-06 16:33:21 +02002023 /* check prefix validity */
Michal Vaskod0625d72022-10-06 15:02:50 +02002024 LY_CHECK_RET(lysp_check_prefix((struct lysp_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02002025
2026 return LY_SUCCESS;
2027}
2028
2029/**
2030 * @brief Parse mandatory element.
2031 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002032 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002033 * @param[in,out] flags Flags to add to.
2034 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002035 * @return LY_ERR values.
2036 */
2037static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002038yin_parse_mandatory(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002039{
2040 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002041 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002042 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2043 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002044
Michal Vaskob36053d2020-03-26 15:49:30 +01002045 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2046 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 +02002047 if (strcmp(temp_val, "true") == 0) {
2048 *flags |= LYS_MAND_TRUE;
2049 } else if (strcmp(temp_val, "false") == 0) {
2050 *flags |= LYS_MAND_FALSE;
2051 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02002052 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002053 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002054 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002055 return LY_EVALID;
2056 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002057 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002058
Michal Vasko193dacd2022-10-13 08:43:05 +02002059 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_MANDATORY, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002060
2061 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002062}
2063
2064/**
2065 * @brief Parse status element.
2066 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002067 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002068 * @param[in,out] flags Flags to add to.
2069 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002070 * @return LY_ERR values.
2071 */
2072static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002073yin_parse_status(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002074{
2075 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002076 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002077 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2078 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002079
Michal Vaskob36053d2020-03-26 15:49:30 +01002080 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2081 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 +02002082 if (strcmp(value, "current") == 0) {
2083 *flags |= LYS_STATUS_CURR;
2084 } else if (strcmp(value, "deprecated") == 0) {
2085 *flags |= LYS_STATUS_DEPRC;
2086 } else if (strcmp(value, "obsolete") == 0) {
2087 *flags |= LYS_STATUS_OBSLT;
2088 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02002089 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002090 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002091 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02002092 return LY_EVALID;
2093 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002094 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02002095
Michal Vasko193dacd2022-10-13 08:43:05 +02002096 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_STATUS, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002097
2098 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002099}
2100
2101/**
2102 * @brief Parse when element.
2103 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002104 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002105 * @param[out] when_p When pointer to parse to.
Michal Vasko193dacd2022-10-13 08:43:05 +02002106 * @return LY_ERR values.
David Sedlákdfbbb442019-08-06 16:33:21 +02002107 */
2108static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002109yin_parse_when(struct lysp_yin_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02002110{
2111 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02002112 LY_ERR ret = LY_SUCCESS;
2113
David Sedlákdfbbb442019-08-06 16:33:21 +02002114 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01002115 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02002116
2117 ret = lyxml_ctx_next(ctx->xmlctx);
2118 LY_CHECK_ERR_RET(ret, free(when), ret);
2119
Michal Vaskob36053d2020-03-26 15:49:30 +01002120 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02002121 LY_CHECK_ERR_RET(ret, free(when), ret);
2122
David Sedlákdfbbb442019-08-06 16:33:21 +02002123 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002124 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002125 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2126 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2127 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2128 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002129
Michal Vasko193dacd2022-10-13 08:43:05 +02002130 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), when, LY_STMT_WHEN, NULL, &when->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002131
2132 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002133 LY_CHECK_RET(yin_unres_exts_add(ctx, when->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002134
2135 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002136}
2137
2138/**
2139 * @brief Parse yin-elemenet element.
2140 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002141 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02002142 * @param[in] parent Current statement parent.
David Sedlákdfbbb442019-08-06 16:33:21 +02002143 * @param[in,out] flags Flags to add to.
Michal Vasko193dacd2022-10-13 08:43:05 +02002144 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002145 * @return LY_ERR values.
2146 */
2147static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002148yin_parse_yin_element(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002149{
2150 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002151 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002152 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2153 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002154
Michal Vaskob36053d2020-03-26 15:49:30 +01002155 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2156 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 +02002157 if (strcmp(temp_val, "true") == 0) {
2158 *flags |= LYS_YINELEM_TRUE;
2159 } else if (strcmp(temp_val, "false") == 0) {
2160 *flags |= LYS_YINELEM_FALSE;
2161 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02002162 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002163 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002164 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002165 return LY_EVALID;
2166 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002167 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002168
Michal Vasko193dacd2022-10-13 08:43:05 +02002169 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YIN_ELEMENT, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002170
2171 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002172}
2173
2174/**
2175 * @brief Parse argument element.
2176 *
Michal Vasko193dacd2022-10-13 08:43:05 +02002177 * @param[in,out] ctx YIN parser context for logging and to store current state.
2178 * @param[in] parent Current statement parent.
2179 * @param[in,out] arg_meta Meta information about destination of parsed data.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002180 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002181 * @return LY_ERR values.
2182 */
2183static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02002184yin_parse_argument(struct lysp_yin_ctx *ctx, const void *parent, struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002185{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002186 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002187 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2188 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2189 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002190
Michal Vaskob36053d2020-03-26 15:49:30 +01002191 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2192 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 +02002193
Michal Vasko193dacd2022-10-13 08:43:05 +02002194 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ARGUMENT, NULL, exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002195
2196 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002197}
2198
2199/**
2200 * @brief Parse the extension statement.
2201 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002202 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002203 * @param[in,out] extensions Extensions to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002204 * @return LY_ERR values.
2205 */
2206static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002207yin_parse_extension(struct lysp_yin_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002208{
2209 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002210
Michal Vaskob36053d2020-03-26 15:49:30 +01002211 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2212 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2213 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 +02002214
Radek Krejci9f87b0c2021-03-05 14:45:26 +01002215 struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002216 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002217 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2218 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2219 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2220 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2221 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2222 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002223
Michal Vasko193dacd2022-10-13 08:43:05 +02002224 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), ex, LY_STMT_EXTENSION, NULL, &ex->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002225
2226 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002227 LY_CHECK_RET(yin_unres_exts_add(ctx, ex->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002228
2229 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002230}
2231
2232/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002233 * @brief Parse feature element.
2234 *
2235 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002236 * @param[in,out] features Features to add to.
David Sedlák5e13dea2019-07-22 16:06:45 +02002237 * @return LY_ERR values.
2238 */
2239static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002240yin_parse_feature(struct lysp_yin_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002241{
2242 struct lysp_feature *feat;
2243
2244 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002245 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002246
2247 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002248 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2249 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 +02002250
2251 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002252 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002253 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2254 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2255 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2256 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2257 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2258 };
Michal Vasko69730152020-10-09 16:30:07 +02002259
Michal Vasko193dacd2022-10-13 08:43:05 +02002260 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), feat, LY_STMT_FEATURE, NULL, &feat->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002261
2262 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002263 LY_CHECK_RET(yin_unres_exts_add(ctx, feat->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002264
2265 return LY_SUCCESS;
David Sedlák5e13dea2019-07-22 16:06:45 +02002266}
2267
2268/**
David Sedlák28794f22019-07-22 16:45:00 +02002269 * @brief Parse identity element.
2270 *
2271 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002272 * @param[in,out] identities Identities to add to.
David Sedlák28794f22019-07-22 16:45:00 +02002273 * @return LY_ERR values.
2274 */
2275static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002276yin_parse_identity(struct lysp_yin_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002277{
2278 struct lysp_ident *ident;
2279
2280 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002281 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002282
2283 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002284 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2285 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 +02002286
2287 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002288 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002289 {LY_STMT_BASE, &ident->bases, 0},
2290 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2291 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2292 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2293 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2294 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2295 };
Michal Vasko69730152020-10-09 16:30:07 +02002296
Michal Vasko193dacd2022-10-13 08:43:05 +02002297 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), ident, LY_STMT_IDENTITY, NULL, &ident->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002298
2299 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002300 LY_CHECK_RET(yin_unres_exts_add(ctx, ident->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002301
2302 return LY_SUCCESS;
David Sedlák28794f22019-07-22 16:45:00 +02002303}
2304
2305/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002306 * @brief Parse list element.
2307 *
2308 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002309 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002310 * @return LY_ERR values.
2311 */
2312static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002313yin_parse_list(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002314{
David Sedlákaf536aa2019-07-23 13:42:23 +02002315 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002316 LY_ERR ret = LY_SUCCESS;
2317 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002318 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002319
Michal Vaskob36053d2020-03-26 15:49:30 +01002320 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002321 list->nodetype = LYS_LIST;
2322 list->parent = node_meta->parent;
2323
David Sedlákaf536aa2019-07-23 13:42:23 +02002324 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002325 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2326 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 +02002327
2328 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002329 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002330 LY_STMT_ACTION, &list->actions, 0,
2331 LY_STMT_ANYDATA, &list->child, 0,
2332 LY_STMT_ANYXML, &list->child, 0,
2333 LY_STMT_CHOICE, &list->child, 0,
2334 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2335 LY_STMT_CONTAINER, &list->child, 0,
2336 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2337 LY_STMT_GROUPING, &list->groupings, 0,
2338 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2339 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2340 LY_STMT_LEAF, &list->child, 0,
2341 LY_STMT_LEAF_LIST, &list->child, 0,
2342 LY_STMT_LIST, &list->child, 0,
2343 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2344 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2345 LY_STMT_MUST, &list->musts, 0,
2346 LY_STMT_NOTIFICATION, &list->notifs, 0,
2347 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2348 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2349 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_TYPEDEF, &list->typedefs, 0,
2351 LY_STMT_UNIQUE, &list->uniques, 0,
2352 LY_STMT_USES, &list->child, 0,
2353 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2354 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002355 ret = yin_parse_content(ctx, subelems, subelems_size, list, LY_STMT_LIST, NULL, &list->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002356 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002357 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002358
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002359 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002360 LY_CHECK_RET(yin_unres_exts_add(ctx, list->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002361
Michal Vasko69730152020-10-09 16:30:07 +02002362 if (list->max && (list->min > list->max)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02002363 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002364 return LY_EVALID;
2365 }
2366
2367 return LY_SUCCESS;
2368}
2369
2370/**
David Sedlák031b9e72019-07-23 15:19:37 +02002371 * @brief Parse notification element.
2372 *
2373 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002374 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002375 * @return LY_ERR values.
2376 */
2377static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002378yin_parse_notification(struct lysp_yin_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002379{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002380 struct lysp_node_notif *notif;
2381 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002382 LY_ERR ret = LY_SUCCESS;
2383 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002384 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002385
2386 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002387 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002388 notif->nodetype = LYS_NOTIF;
2389 notif->parent = notif_meta->parent;
2390
2391 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002392 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2393 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
David Sedlák031b9e72019-07-23 15:19:37 +02002394
2395 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002396 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002397 LY_STMT_ANYDATA, &notif->child, 0,
2398 LY_STMT_ANYXML, &notif->child, 0,
2399 LY_STMT_CHOICE, &notif->child, 0,
2400 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002401 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2402 LY_STMT_GROUPING, &notif->groupings, 0,
2403 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002404 LY_STMT_LEAF, &notif->child, 0,
2405 LY_STMT_LEAF_LIST, &notif->child, 0,
2406 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002407 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2408 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2409 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2410 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002411 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002412 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002413
Michal Vasko193dacd2022-10-13 08:43:05 +02002414 ret = yin_parse_content(ctx, subelems, subelems_size, notif, LY_STMT_NOTIFICATION, NULL, &notif->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002415 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002416 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002417
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002418 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002419 LY_CHECK_RET(yin_unres_exts_add(ctx, notif->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002420
David Sedlák031b9e72019-07-23 15:19:37 +02002421 return LY_SUCCESS;
2422}
2423
2424/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002425 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002426 *
2427 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002428 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002429 * @return LY_ERR values.
2430 */
2431static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002432yin_parse_grouping(struct lysp_yin_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002433{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002434 struct lysp_node_grp *grp;
2435 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002436 LY_ERR ret = LY_SUCCESS;
2437 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002438 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002439
2440 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002441 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002442 grp->nodetype = LYS_GROUPING;
2443 grp->parent = gr_meta->parent;
2444
2445 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002446 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2447 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 +02002448
2449 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002450 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002451 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002452 LY_STMT_ANYDATA, &grp->child, 0,
2453 LY_STMT_ANYXML, &grp->child, 0,
2454 LY_STMT_CHOICE, &grp->child, 0,
2455 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002456 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2457 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002458 LY_STMT_LEAF, &grp->child, 0,
2459 LY_STMT_LEAF_LIST, &grp->child, 0,
2460 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002461 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2462 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2463 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2464 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002465 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002466 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002467 ret = yin_parse_content(ctx, subelems, subelems_size, grp, LY_STMT_GROUPING, NULL, &grp->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002468 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002469
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002470 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002471 LY_CHECK_RET(yin_unres_exts_add(ctx, grp->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002472
aPiecek63e080d2021-06-29 13:53:28 +02002473 /* store data for collision check */
2474 if (!ret && grp->parent) {
2475 assert(ctx->main_ctx);
2476 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, grp->parent, 0, NULL));
2477 }
2478
Radek Krejci2a9fc652021-01-22 17:44:34 +01002479 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002480}
2481
2482/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002483 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002484 *
2485 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002486 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002487 * @return LY_ERR values.
2488 */
2489static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002490yin_parse_container(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002491{
David Sedlákf111bcb2019-07-23 17:15:51 +02002492 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002493 LY_ERR ret = LY_SUCCESS;
2494 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002495 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002496
2497 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002498 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002499 cont->nodetype = LYS_CONTAINER;
2500 cont->parent = node_meta->parent;
2501
David Sedlákf111bcb2019-07-23 17:15:51 +02002502 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002503 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2504 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 +02002505
2506 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002507 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002508 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2509 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2510 LY_STMT_ANYXML, &cont->child, 0,
2511 LY_STMT_CHOICE, &cont->child, 0,
2512 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2513 LY_STMT_CONTAINER, &cont->child, 0,
2514 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2515 LY_STMT_GROUPING, &cont->groupings, 0,
2516 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2517 LY_STMT_LEAF, &cont->child, 0,
2518 LY_STMT_LEAF_LIST, &cont->child, 0,
2519 LY_STMT_LIST, &cont->child, 0,
2520 LY_STMT_MUST, &cont->musts, 0,
2521 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2522 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2523 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2524 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2525 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2526 LY_STMT_USES, &cont->child, 0,
2527 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2528 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002529 ret = yin_parse_content(ctx, subelems, subelems_size, cont, LY_STMT_CONTAINER, NULL, &cont->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002530 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002531 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02002532
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002533 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002534 LY_CHECK_RET(yin_unres_exts_add(ctx, cont->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002535
2536 return LY_SUCCESS;
David Sedlákf111bcb2019-07-23 17:15:51 +02002537}
2538
2539/**
David Sedlák5379d392019-07-24 10:42:03 +02002540 * @brief Parse case element.
2541 *
2542 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002543 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002544 * @return LY_ERR values.
2545 */
2546static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002547yin_parse_case(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002548{
David Sedlák5379d392019-07-24 10:42:03 +02002549 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002550 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002551 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002552 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002553
2554 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002555 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002556 cas->nodetype = LYS_CASE;
2557 cas->parent = node_meta->parent;
2558
David Sedlák5379d392019-07-24 10:42:03 +02002559 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002560 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2561 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 +02002562
2563 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002564 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002565 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2566 LY_STMT_ANYXML, &cas->child, 0,
2567 LY_STMT_CHOICE, &cas->child, 0,
2568 LY_STMT_CONTAINER, &cas->child, 0,
2569 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2570 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2571 LY_STMT_LEAF, &cas->child, 0,
2572 LY_STMT_LEAF_LIST, &cas->child, 0,
2573 LY_STMT_LIST, &cas->child, 0,
2574 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2575 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2576 LY_STMT_USES, &cas->child, 0,
2577 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2578 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002579 ret = yin_parse_content(ctx, subelems, subelems_size, cas, LY_STMT_CASE, NULL, &cas->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002580 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002581 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02002582
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002583 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002584 LY_CHECK_RET(yin_unres_exts_add(ctx, cas->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002585
2586 return LY_SUCCESS;
David Sedlák5379d392019-07-24 10:42:03 +02002587}
2588
2589/**
David Sedlák05404f62019-07-24 14:11:53 +02002590 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002591 *
2592 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002593 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002594 * @return LY_ERR values.
2595 */
2596LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002597yin_parse_choice(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002598{
David Sedlák81497a32019-08-13 16:56:26 +02002599 LY_ERR ret = LY_SUCCESS;
2600 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002601 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002602 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002603
2604 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002605 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002606
David Sedlákb7abcfa2019-07-24 12:33:35 +02002607 choice->nodetype = LYS_CHOICE;
2608 choice->parent = node_meta->parent;
2609
David Sedlákb7abcfa2019-07-24 12:33:35 +02002610 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002611 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2612 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 +02002613
2614 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002615 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002616 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2617 LY_STMT_ANYXML, &choice->child, 0,
2618 LY_STMT_CASE, &choice->child, 0,
2619 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2620 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2621 LY_STMT_CONTAINER, &choice->child, 0,
2622 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2623 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2624 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2625 LY_STMT_LEAF, &choice->child, 0,
2626 LY_STMT_LEAF_LIST, &choice->child, 0,
2627 LY_STMT_LIST, &choice->child, 0,
2628 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2629 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2630 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2631 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2632 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002633 ret = yin_parse_content(ctx, subelems, subelems_size, choice, LY_STMT_CHOICE, NULL, &choice->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002634 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002635 LY_CHECK_RET(ret);
2636
2637 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002638 LY_CHECK_RET(yin_unres_exts_add(ctx, choice->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002639
David Sedlák81497a32019-08-13 16:56:26 +02002640 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002641}
2642
2643/**
David Sedlák05404f62019-07-24 14:11:53 +02002644 * @brief Parse input or output element.
2645 *
2646 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002647 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002648 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
David Sedlák05404f62019-07-24 14:11:53 +02002649 * @return LY_ERR values.
2650 */
2651static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002652yin_parse_inout(struct lysp_yin_ctx *ctx, enum ly_stmt inout_kw, struct inout_meta *inout_meta)
David Sedlák05404f62019-07-24 14:11:53 +02002653{
David Sedlák81497a32019-08-13 16:56:26 +02002654 LY_ERR ret = LY_SUCCESS;
2655 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002656 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002657
David Sedlák05404f62019-07-24 14:11:53 +02002658 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002659 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 +02002660 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002661 inout_meta->inout_p->parent = inout_meta->parent;
2662
2663 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002664 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2665 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 +02002666
2667 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002668 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002669 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2670 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2671 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2672 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002673 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002674 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2675 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2676 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002677 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2678 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002679 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002680 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002681 ret = yin_parse_content(ctx, subelems, subelems_size, inout_meta->inout_p, inout_kw, NULL, &inout_meta->inout_p->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002682 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002683 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002684
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002685 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002686 LY_CHECK_RET(yin_unres_exts_add(ctx, inout_meta->inout_p->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002687
Radek Krejci01180ac2021-01-27 08:48:22 +01002688 if (!inout_meta->inout_p->child) {
Michal Vasko193dacd2022-10-13 08:43:05 +02002689 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(inout_kw));
Michal Vaskob83af8a2020-01-06 09:49:22 +01002690 return LY_EVALID;
2691 }
2692
David Sedlák05404f62019-07-24 14:11:53 +02002693 return LY_SUCCESS;
2694}
2695
David Sedlák992fb7c2019-07-24 16:51:01 +02002696/**
2697 * @brief Parse action element.
2698 *
2699 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002700 * @param[in] act_meta Meta information about parent node and actions to add to.
David Sedlák992fb7c2019-07-24 16:51:01 +02002701 * @return LY_ERR values.
2702 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002703static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002704yin_parse_action(struct lysp_yin_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002705{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002706 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002707 LY_ERR ret = LY_SUCCESS;
2708 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002709 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002710 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002711
2712 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002713 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002714 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002715 act->parent = act_meta->parent;
2716
2717 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002718 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002719 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002720
2721 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002722 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002723 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2724 LY_STMT_GROUPING, &act->groupings, 0,
2725 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2726 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2727 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2728 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2729 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2730 LY_STMT_TYPEDEF, &act->typedefs, 0,
2731 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002732 ret = (yin_parse_content(ctx, subelems, subelems_size, act, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002733 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002734 LY_CHECK_RET(ret);
2735
Michal Vasko7f45cf22020-10-01 12:49:44 +02002736 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2737 if (!act->input.nodetype) {
2738 act->input.nodetype = LYS_INPUT;
2739 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002740 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002741 }
2742 if (!act->output.nodetype) {
2743 act->output.nodetype = LYS_OUTPUT;
2744 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002745 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002746 }
2747
Michal Vasko4929d5f2022-11-08 13:21:02 +01002748 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2749 LY_CHECK_RET(yin_unres_exts_add(ctx, act->exts));
2750
David Sedlák85d0eca2019-07-24 15:15:21 +02002751 return LY_SUCCESS;
2752}
2753
David Sedlák05404f62019-07-24 14:11:53 +02002754/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002755 * @brief Parse augment element.
2756 *
2757 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002758 * @param[in] aug_meta Meta information about parent node and augments to add to.
David Sedlák992fb7c2019-07-24 16:51:01 +02002759 * @return LY_ERR values.
2760 */
2761static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002762yin_parse_augment(struct lysp_yin_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002763{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002764 struct lysp_node_augment *aug;
2765 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002766 LY_ERR ret = LY_SUCCESS;
2767 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002768 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002769
2770 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002771 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002772 aug->nodetype = LYS_AUGMENT;
2773 aug->parent = aug_meta->parent;
2774
2775 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002776 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2777 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
Michal Vaskod0625d72022-10-06 15:02:50 +02002778 CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002779
2780 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002781 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002782 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2783 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2784 LY_STMT_ANYXML, &aug->child, 0,
2785 LY_STMT_CASE, &aug->child, 0,
2786 LY_STMT_CHOICE, &aug->child, 0,
2787 LY_STMT_CONTAINER, &aug->child, 0,
2788 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002789 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002790 LY_STMT_LEAF, &aug->child, 0,
2791 LY_STMT_LEAF_LIST, &aug->child, 0,
2792 LY_STMT_LIST, &aug->child, 0,
2793 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2794 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2795 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2796 LY_STMT_USES, &aug->child, 0,
2797 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2798 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vasko193dacd2022-10-13 08:43:05 +02002799 ret = yin_parse_content(ctx, subelems, subelems_size, aug, LY_STMT_AUGMENT, NULL, &aug->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002800 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002801 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002802
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002803 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002804 LY_CHECK_RET(yin_unres_exts_add(ctx, aug->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002805
2806 return LY_SUCCESS;
David Sedlák992fb7c2019-07-24 16:51:01 +02002807}
2808
David Sedlák8b754462019-07-25 16:22:13 +02002809/**
2810 * @brief Parse deviate element.
2811 *
2812 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002813 * @param[in] deviates Deviates to add to.
David Sedlák8b754462019-07-25 16:22:13 +02002814 * @return LY_ERR values.
2815 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002816static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002817yin_parse_deviate(struct lysp_yin_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002818{
2819 LY_ERR ret = LY_SUCCESS;
2820 uint8_t dev_mod;
2821 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002822 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002823 struct lysp_deviate_add *d_add = NULL;
2824 struct lysp_deviate_rpl *d_rpl = NULL;
2825 struct lysp_deviate_del *d_del = NULL;
2826
2827 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002828 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2829 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 +02002830
2831 if (strcmp(temp_val, "not-supported") == 0) {
2832 dev_mod = LYS_DEV_NOT_SUPPORTED;
2833 } else if (strcmp(temp_val, "add") == 0) {
2834 dev_mod = LYS_DEV_ADD;
2835 } else if (strcmp(temp_val, "replace") == 0) {
2836 dev_mod = LYS_DEV_REPLACE;
2837 } else if (strcmp(temp_val, "delete") == 0) {
2838 dev_mod = LYS_DEV_DELETE;
2839 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02002840 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002841 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002842 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002843 return LY_EVALID;
2844 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002845 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002846
2847 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2848 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002849 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002850 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002851 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2852 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002853
Michal Vasko193dacd2022-10-13 08:43:05 +02002854 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002855
2856 } else if (dev_mod == LYS_DEV_ADD) {
2857 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002858 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002859 d = (struct lysp_deviate *)d_add;
2860 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2861 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002862 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002863 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002864 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002865 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2866 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2867 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2868 {LY_STMT_MUST, &d_add->musts, 0},
2869 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2870 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2871 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2872 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002873
Michal Vasko193dacd2022-10-13 08:43:05 +02002874 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002875
2876 } else if (dev_mod == LYS_DEV_REPLACE) {
2877 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002878 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002879 d = (struct lysp_deviate *)d_rpl;
2880 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2881 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002882 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002883 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002884 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002885 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2886 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2887 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2888 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2889 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2890 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2891 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002892
Michal Vasko193dacd2022-10-13 08:43:05 +02002893 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002894
2895 } else {
2896 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002897 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002898 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002899 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002900 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002901 {LY_STMT_MUST, &d_del->musts, 0},
2902 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2903 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2904 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2905 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002906
Michal Vasko193dacd2022-10-13 08:43:05 +02002907 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002908 }
2909 LY_CHECK_GOTO(ret, cleanup);
2910
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002911 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002912 LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, d->exts), cleanup);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002913
David Sedlák4ffcec82019-07-25 15:10:21 +02002914 d->mod = dev_mod;
2915 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002916 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002917
2918 return ret;
2919
2920cleanup:
2921 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002922 return ret;
2923}
2924
David Sedlák992fb7c2019-07-24 16:51:01 +02002925/**
David Sedlák8b754462019-07-25 16:22:13 +02002926 * @brief Parse deviation element.
2927 *
2928 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002929 * @param[in] deviations Deviations to add to.
David Sedlák8b754462019-07-25 16:22:13 +02002930 * @return LY_ERR values.
2931 */
2932static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002933yin_parse_deviation(struct lysp_yin_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002934{
Michal Vasko12ef5362022-09-16 15:13:58 +02002935 LY_ERR ret = LY_SUCCESS;
2936 struct lysp_deviation *dev = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02002937 struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
David Sedlák8b754462019-07-25 16:22:13 +02002938
2939 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002940 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002941
2942 /* parse argument */
Michal Vasko12ef5362022-09-16 15:13:58 +02002943 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2944 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION), cleanup);
Michal Vaskod0625d72022-10-06 15:02:50 +02002945 CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002946 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002947 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2948 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2949 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2950 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2951 };
Michal Vasko69730152020-10-09 16:30:07 +02002952
Michal Vasko193dacd2022-10-13 08:43:05 +02002953 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), dev, LY_STMT_DEVIATION, NULL, &dev->exts);
2954 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko12ef5362022-09-16 15:13:58 +02002955
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002956 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01002957 LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, dev->exts), cleanup);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002958
Michal Vasko12ef5362022-09-16 15:13:58 +02002959cleanup:
2960 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02002961 lysp_deviation_free(&fctx, dev);
Michal Vasko12ef5362022-09-16 15:13:58 +02002962 LY_ARRAY_DECREMENT_FREE(*deviations);
2963 }
2964 return ret;
David Sedlák8b754462019-07-25 16:22:13 +02002965}
2966
2967/**
David Sedlákc5b20842019-08-13 10:18:31 +02002968 * @brief map keyword to keyword-group.
2969 *
2970 * @param[in] ctx YIN parser context used for logging.
2971 * @param[in] kw Keyword that is child of module or submodule.
2972 * @param[out] group Group of keyword.
David Sedlákc5b20842019-08-13 10:18:31 +02002973 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2974 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002975static LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02002976kw2kw_group(struct lysp_yin_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002977{
2978 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002979 /* module header */
2980 case LY_STMT_NONE:
2981 case LY_STMT_NAMESPACE:
2982 case LY_STMT_PREFIX:
2983 case LY_STMT_BELONGS_TO:
2984 case LY_STMT_YANG_VERSION:
2985 *group = Y_MOD_MODULE_HEADER;
2986 break;
2987 /* linkage */
2988 case LY_STMT_INCLUDE:
2989 case LY_STMT_IMPORT:
2990 *group = Y_MOD_LINKAGE;
2991 break;
2992 /* meta */
2993 case LY_STMT_ORGANIZATION:
2994 case LY_STMT_CONTACT:
2995 case LY_STMT_DESCRIPTION:
2996 case LY_STMT_REFERENCE:
2997 *group = Y_MOD_META;
2998 break;
2999 /* revision */
3000 case LY_STMT_REVISION:
3001 *group = Y_MOD_REVISION;
3002 break;
3003 /* body */
3004 case LY_STMT_ANYDATA:
3005 case LY_STMT_ANYXML:
3006 case LY_STMT_AUGMENT:
3007 case LY_STMT_CHOICE:
3008 case LY_STMT_CONTAINER:
3009 case LY_STMT_DEVIATION:
3010 case LY_STMT_EXTENSION:
3011 case LY_STMT_FEATURE:
3012 case LY_STMT_GROUPING:
3013 case LY_STMT_IDENTITY:
3014 case LY_STMT_LEAF:
3015 case LY_STMT_LEAF_LIST:
3016 case LY_STMT_LIST:
3017 case LY_STMT_NOTIFICATION:
3018 case LY_STMT_RPC:
3019 case LY_STMT_TYPEDEF:
3020 case LY_STMT_USES:
3021 case LY_STMT_EXTENSION_INSTANCE:
3022 *group = Y_MOD_BODY;
3023 break;
3024 default:
3025 LOGINT(ctx->xmlctx->ctx);
3026 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02003027 }
3028
3029 return LY_SUCCESS;
3030}
3031
David Sedlákc5b20842019-08-13 10:18:31 +02003032/**
3033 * @brief Check if relative order of two keywords is valid.
3034 *
3035 * @param[in] ctx YIN parser context used for logging.
Michal Vasko193dacd2022-10-13 08:43:05 +02003036 * @param[in] cur_stmt Type of current statement.
3037 * @param[in] next_stmt Type of next statement.
3038 * @param[in] parent_stmt Type of parent statement, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
David Sedlákc5b20842019-08-13 10:18:31 +02003039 * because relative order is required only in module and submodule sub-elements, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +02003040 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02003041 */
David Sedláke6cd89e2019-08-07 12:46:02 +02003042static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02003043yin_check_relative_order(struct lysp_yin_ctx *ctx, enum ly_stmt cur_stmt, enum ly_stmt next_stmt, enum ly_stmt parent_stmt)
David Sedláke6cd89e2019-08-07 12:46:02 +02003044{
David Sedláke6cd89e2019-08-07 12:46:02 +02003045 enum yang_module_stmt gr, next_gr;
3046
Michal Vasko193dacd2022-10-13 08:43:05 +02003047 assert(parent_stmt == LY_STMT_MODULE || parent_stmt == LY_STMT_SUBMODULE);
3048
3049 if (cur_stmt == LY_STMT_EXTENSION_INSTANCE) {
Michal Vaskoc78293f2021-12-16 15:40:33 +01003050 /* no order defined */
3051 return LY_SUCCESS;
3052 }
3053
Michal Vasko193dacd2022-10-13 08:43:05 +02003054 LY_CHECK_RET(kw2kw_group(ctx, cur_stmt, &gr));
3055 LY_CHECK_RET(kw2kw_group(ctx, next_stmt, &next_gr));
David Sedláke6cd89e2019-08-07 12:46:02 +02003056
3057 if (gr > next_gr) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003058 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INORDER_YIN, lyplg_ext_stmt2str(parent_stmt), lyplg_ext_stmt2str(next_stmt),
3059 lyplg_ext_stmt2str(cur_stmt));
David Sedláke6cd89e2019-08-07 12:46:02 +02003060 return LY_EVALID;
3061 }
3062
3063 return LY_SUCCESS;
3064}
3065
David Sedlákc5dd0942019-09-13 10:23:59 +02003066/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003067 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3068 *
3069 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02003070 * @param[in] parent_stmt Type of parent statement.
Michal Vaskoafac7822020-10-20 14:22:26 +02003071 * @param[out] arg Value to write to.
Michal Vaskoafac7822020-10-20 14:22:26 +02003072 * @return LY_ERR values.
3073 */
3074static LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02003075yin_parse_extension_instance_arg(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, const char **arg)
Michal Vaskoafac7822020-10-20 14:22:26 +02003076{
3077 enum ly_stmt child;
3078
3079 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3080
Michal Vasko193dacd2022-10-13 08:43:05 +02003081 switch (parent_stmt) {
Michal Vaskoafac7822020-10-20 14:22:26 +02003082 case LY_STMT_ACTION:
3083 case LY_STMT_ANYDATA:
3084 case LY_STMT_ANYXML:
3085 case LY_STMT_ARGUMENT:
3086 case LY_STMT_BASE:
3087 case LY_STMT_BIT:
3088 case LY_STMT_CASE:
3089 case LY_STMT_CHOICE:
3090 case LY_STMT_CONTAINER:
3091 case LY_STMT_ENUM:
3092 case LY_STMT_EXTENSION:
3093 case LY_STMT_FEATURE:
3094 case LY_STMT_GROUPING:
3095 case LY_STMT_IDENTITY:
3096 case LY_STMT_IF_FEATURE:
3097 case LY_STMT_LEAF:
3098 case LY_STMT_LEAF_LIST:
3099 case LY_STMT_LIST:
3100 case LY_STMT_MODULE:
3101 case LY_STMT_NOTIFICATION:
3102 case LY_STMT_RPC:
3103 case LY_STMT_SUBMODULE:
3104 case LY_STMT_TYPE:
3105 case LY_STMT_TYPEDEF:
3106 case LY_STMT_UNITS:
3107 case LY_STMT_USES:
Michal Vasko193dacd2022-10-13 08:43:05 +02003108 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003109 break;
3110 case LY_STMT_AUGMENT:
3111 case LY_STMT_DEVIATION:
3112 case LY_STMT_REFINE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003113 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003114 break;
3115 case LY_STMT_CONFIG:
3116 case LY_STMT_DEFAULT:
3117 case LY_STMT_DEVIATE:
3118 case LY_STMT_ERROR_APP_TAG:
3119 case LY_STMT_FRACTION_DIGITS:
3120 case LY_STMT_KEY:
3121 case LY_STMT_LENGTH:
3122 case LY_STMT_MANDATORY:
3123 case LY_STMT_MAX_ELEMENTS:
3124 case LY_STMT_MIN_ELEMENTS:
3125 case LY_STMT_MODIFIER:
3126 case LY_STMT_ORDERED_BY:
3127 case LY_STMT_PATH:
3128 case LY_STMT_PATTERN:
3129 case LY_STMT_POSITION:
3130 case LY_STMT_PREFIX:
3131 case LY_STMT_PRESENCE:
3132 case LY_STMT_RANGE:
3133 case LY_STMT_REQUIRE_INSTANCE:
3134 case LY_STMT_STATUS:
3135 case LY_STMT_VALUE:
3136 case LY_STMT_YANG_VERSION:
3137 case LY_STMT_YIN_ELEMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003138 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003139 break;
3140 case LY_STMT_IMPORT:
3141 case LY_STMT_INCLUDE:
3142 case LY_STMT_BELONGS_TO:
Michal Vasko193dacd2022-10-13 08:43:05 +02003143 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003144 break;
3145 case LY_STMT_INPUT:
3146 case LY_STMT_OUTPUT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003147 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003148 break;
3149 case LY_STMT_MUST:
3150 case LY_STMT_WHEN:
Michal Vasko193dacd2022-10-13 08:43:05 +02003151 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003152 break;
3153 case LY_STMT_NAMESPACE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003154 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003155 break;
3156 case LY_STMT_REVISION:
3157 case LY_STMT_REVISION_DATE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003158 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003159 break;
3160 case LY_STMT_UNIQUE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003161 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003162 break;
3163 /* argument is mapped to yin element */
3164 case LY_STMT_CONTACT:
3165 case LY_STMT_DESCRIPTION:
3166 case LY_STMT_ORGANIZATION:
3167 case LY_STMT_REFERENCE:
3168 case LY_STMT_ERROR_MESSAGE:
3169 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vasko193dacd2022-10-13 08:43:05 +02003170 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003171
3172 /* no content */
3173 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3174 if (ctx->xmlctx->ws_only) {
3175 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3176 }
3177 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003178 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko193dacd2022-10-13 08:43:05 +02003179 parent_stmt == LY_STMT_ERROR_MESSAGE ? "value" : "text", lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003180 return LY_EVALID;
3181 }
3182
3183 /* parse child element */
Michal Vasko193dacd2022-10-13 08:43:05 +02003184 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3185 ctx->xmlctx->prefix_len, parent_stmt);
3186 if (((parent_stmt == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3187 ((parent_stmt != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003188 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
Michal Vasko193dacd2022-10-13 08:43:05 +02003189 lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003190 return LY_EVALID;
3191 }
3192 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3193
Michal Vasko193dacd2022-10-13 08:43:05 +02003194 /* no attributes expected */
Michal Vaskoafac7822020-10-20 14:22:26 +02003195 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3196 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3197 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3198 }
3199
3200 /* load and save content */
3201 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3202 LY_CHECK_RET(!*arg, LY_EMEM);
3203
3204 /* load closing tag of subelement */
3205 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoafac7822020-10-20 14:22:26 +02003206 break;
3207 default:
3208 LOGINT(ctx->xmlctx->ctx);
3209 return LY_EINT;
3210 }
3211
3212 return LY_SUCCESS;
3213}
3214
3215/**
3216 * @brief Parse yin element into generic structure.
3217 *
3218 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02003219 * @param[in] parent_stmt Type of parent statement.
Michal Vaskoafac7822020-10-20 14:22:26 +02003220 * @param[out] element Where the element structure should be stored.
Michal Vaskoafac7822020-10-20 14:22:26 +02003221 * @return LY_ERR values.
3222 */
3223LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02003224yin_parse_element_generic(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct lysp_stmt **element)
Michal Vaskoafac7822020-10-20 14:22:26 +02003225{
3226 LY_ERR ret = LY_SUCCESS;
3227 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003228 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003229
3230 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3231
3232 /* allocate new structure for element */
3233 *element = calloc(1, sizeof(**element));
3234 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003235
3236 /* store identifier */
3237 if (ctx->xmlctx->prefix_len) {
3238 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3239 ctx->xmlctx->name) == -1) {
3240 LOGMEM(ctx->xmlctx->ctx);
3241 ret = LY_EMEM;
3242 goto cleanup;
3243 }
3244 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3245
3246 /* store prefix data for the statement */
Radek Krejci8df109d2021-04-23 12:19:08 +02003247 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 +01003248 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3249 } else {
3250 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3251 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003252
3253 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko193dacd2022-10-13 08:43:05 +02003254 ctx->xmlctx->prefix_len, parent_stmt);
Michal Vaskoafac7822020-10-20 14:22:26 +02003255
3256 last = (*element)->child;
3257 if ((*element)->kw == LY_STMT_NONE) {
3258 /* unrecognized element */
Michal Vaskod0625d72022-10-06 15:02:50 +02003259 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
Michal Vasko193dacd2022-10-13 08:43:05 +02003260 lyplg_ext_stmt2str(parent_stmt));
Michal Vaskoafac7822020-10-20 14:22:26 +02003261 ret = LY_EVALID;
3262 goto cleanup;
3263 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3264 /* element is known yang keyword, which means argument can be parsed correctly. */
3265 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3266 LY_CHECK_GOTO(ret, cleanup);
3267 } else {
3268 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3269
3270 /* load attributes in generic way, save all attributes in linked list */
3271 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3272 new = calloc(1, sizeof(*last));
3273 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3274 if (!(*element)->child) {
3275 /* save first */
3276 (*element)->child = new;
3277 } else {
3278 last->next = new;
3279 }
3280 last = new;
3281
3282 last->flags |= LYS_YIN_ATTR;
3283 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3284 last->kw = LY_STMT_NONE;
3285 /* attributes with prefix are ignored */
3286 if (!ctx->xmlctx->prefix) {
3287 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3288
3289 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3290 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3291 } else {
3292 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3293 }
3294 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3295 }
3296 }
3297
3298 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3299 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3300 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3301 /* parse subelements */
3302 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3303 LY_CHECK_GOTO(ret, cleanup);
3304 if (!(*element)->child) {
3305 /* save first */
3306 (*element)->child = new;
3307 } else {
3308 last->next = new;
3309 }
3310 last = new;
3311
3312 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3313 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3314 }
3315 } else {
3316 /* save element content */
3317 if (ctx->xmlctx->value_len) {
3318 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3319 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003320
3321 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003322 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 +01003323 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003324 }
3325
3326 /* read closing tag */
3327 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3328 }
3329
3330cleanup:
3331 return ret;
3332}
3333
3334/**
3335 * @brief Parse instance of extension.
3336 *
3337 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vasko193dacd2022-10-13 08:43:05 +02003338 * @param[in] parent Current statement parent.
3339 * @param[in] parent_stmt Type of @p parent statement.
3340 * @param[in] parent_stmt_index In case of several @p parent_stmt, index of the relevant @p parent statement.
Michal Vaskoafac7822020-10-20 14:22:26 +02003341 * @param[in,out] exts Extension instance to add to.
Michal Vaskoafac7822020-10-20 14:22:26 +02003342 * @return LY_ERR values.
3343 */
3344LY_ERR
Michal Vasko193dacd2022-10-13 08:43:05 +02003345yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt,
3346 LY_ARRAY_COUNT_TYPE parent_stmt_index, struct lysp_ext_instance **exts)
Michal Vaskoafac7822020-10-20 14:22:26 +02003347{
3348 struct lysp_ext_instance *e;
3349 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003350 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003351
3352 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003353 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003354
3355 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3356
Michal Vaskofc2cd072021-02-24 13:17:17 +01003357 if (!ctx->xmlctx->prefix_len) {
3358 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3359 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3360 return LY_EVALID;
3361 }
3362
3363 /* store prefixed name */
3364 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3365 ctx->xmlctx->name) == -1) {
3366 LOGMEM(ctx->xmlctx->ctx);
3367 return LY_EMEM;
3368 }
3369 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3370
3371 /* store prefix data for the name */
Radek Krejci8df109d2021-04-23 12:19:08 +02003372 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 +01003373 &e->format, &e->prefix_data));
3374
Michal Vasko193dacd2022-10-13 08:43:05 +02003375 e->parent = (void *)parent;
3376 e->parent_stmt = parent_stmt;
3377 e->parent_stmt_index = parent_stmt_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003378
Michal Vaskoafac7822020-10-20 14:22:26 +02003379 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3380
3381 /* store attributes as subelements */
3382 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3383 if (!ctx->xmlctx->prefix) {
3384 new_subelem = calloc(1, sizeof(*new_subelem));
3385 if (!e->child) {
3386 e->child = new_subelem;
3387 } else {
3388 last_subelem->next = new_subelem;
3389 }
3390 last_subelem = new_subelem;
3391
3392 last_subelem->flags |= LYS_YIN_ATTR;
3393 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3394 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3395 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3396
Michal Vaskofc2cd072021-02-24 13:17:17 +01003397 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3398 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003399 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3400 } else {
3401 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3402 }
3403
3404 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3405 }
3406
3407 /* parse subelements */
3408 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3409 if (ctx->xmlctx->ws_only) {
3410 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3411 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3412 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3413 if (!e->child) {
3414 e->child = new_subelem;
3415 } else {
3416 last_subelem->next = new_subelem;
3417 }
3418 last_subelem = new_subelem;
3419
3420 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3421 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3422 }
3423 } else if (ctx->xmlctx->value_len) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003424 /* invalid text content */
3425 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \".*s\".", ext_name,
3426 (int)ctx->xmlctx->value_len, ctx->xmlctx->value);
3427 return LY_EVALID;
Michal Vaskoafac7822020-10-20 14:22:26 +02003428 }
3429
aPiecek60d9d672021-04-27 15:49:57 +02003430 e->parsed = NULL;
3431
Michal Vaskoafac7822020-10-20 14:22:26 +02003432 return LY_SUCCESS;
3433}
3434
3435/**
3436 * @brief Generic function for content parsing
3437 *
3438 * @param[in,out] ctx Yin parser context for logging and to store current state.
3439 * @param[in] subelem_info array of valid subelement types and meta information
3440 * @param[in] subelem_info_size Size of subelem_info array.
Michal Vasko193dacd2022-10-13 08:43:05 +02003441 * @param[in] parent Current statement parent.
3442 * @param[in] parent_stmt Type of @p parent statement.
Michal Vaskoafac7822020-10-20 14:22:26 +02003443 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3444 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
Michal Vaskoafac7822020-10-20 14:22:26 +02003445 * @return LY_ERR values.
3446 */
David Sedlákd6e56892019-07-01 15:40:24 +02003447LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003448yin_parse_content(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Michal Vasko193dacd2022-10-13 08:43:05 +02003449 const void *parent, enum ly_stmt parent_stmt, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003450{
3451 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003452 enum LYXML_PARSER_STATUS next_status;
Michal Vasko193dacd2022-10-13 08:43:05 +02003453 enum ly_stmt cur_stmt = LY_STMT_NONE, last_stmt = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003454 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003455
Michal Vaskob36053d2020-03-26 15:49:30 +01003456 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003457
Michal Vaskob36053d2020-03-26 15:49:30 +01003458 if (ctx->xmlctx->ws_only) {
3459 /* check whether there are any children */
3460 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3461 } else {
3462 /* we want to parse the value */
3463 next_status = LYXML_ELEM_CLOSE;
3464 }
3465
3466 if (next_status == LYXML_ELEMENT) {
3467 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3468
3469 /* current element has subelements as content */
3470 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3471 /* match keyword */
Michal Vasko193dacd2022-10-13 08:43:05 +02003472 last_stmt = cur_stmt;
3473 cur_stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3474 ctx->xmlctx->prefix_len, parent_stmt);
Michal Vaskob36053d2020-03-26 15:49:30 +01003475
3476 /* check if this element can be child of current element */
Michal Vasko193dacd2022-10-13 08:43:05 +02003477 subelem = get_record(cur_stmt, subelem_info_size, subelem_info);
Michal Vaskob36053d2020-03-26 15:49:30 +01003478 if (!subelem) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003479 if ((parent_stmt == LY_STMT_DEVIATE) && isdevsub(cur_stmt)) {
3480 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INDEV_YIN, lyplg_ext_stmt2str(cur_stmt));
Michal Vaskob36053d2020-03-26 15:49:30 +01003481 } else {
Michal Vaskod0625d72022-10-06 15:02:50 +02003482 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko193dacd2022-10-13 08:43:05 +02003483 ctx->xmlctx->name, lyplg_ext_stmt2str(parent_stmt));
Michal Vaskob36053d2020-03-26 15:49:30 +01003484 }
3485 ret = LY_EVALID;
3486 goto cleanup;
3487 }
3488
3489 /* relative order is required only in module and submodule sub-elements */
Michal Vasko193dacd2022-10-13 08:43:05 +02003490 if ((parent_stmt == LY_STMT_MODULE) || (parent_stmt == LY_STMT_SUBMODULE)) {
3491 ret = yin_check_relative_order(ctx, last_stmt, cur_stmt, parent_stmt);
Michal Vaskob36053d2020-03-26 15:49:30 +01003492 LY_CHECK_GOTO(ret, cleanup);
3493 }
3494
3495 /* flag check */
3496 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3497 /* subelement uniquenes */
Michal Vasko193dacd2022-10-13 08:43:05 +02003498 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, lyplg_ext_stmt2str(cur_stmt), lyplg_ext_stmt2str(parent_stmt));
Michal Vaskob36053d2020-03-26 15:49:30 +01003499 return LY_EVALID;
3500 }
3501 if (subelem->flags & YIN_SUBELEM_FIRST) {
3502 /* subelement is supposed to be defined as first subelement */
Michal Vasko193dacd2022-10-13 08:43:05 +02003503 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, parent_stmt, subelem);
Michal Vaskob36053d2020-03-26 15:49:30 +01003504 LY_CHECK_GOTO(ret, cleanup);
3505 }
3506 if (subelem->flags & YIN_SUBELEM_VER2) {
3507 /* subelement is supported only in version 1.1 or higher */
Michal Vasko8a67eff2021-12-07 14:04:47 +01003508 if (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003509 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INSUBELEM2, lyplg_ext_stmt2str(cur_stmt), lyplg_ext_stmt2str(parent_stmt));
David Sedlákd6e56892019-07-01 15:40:24 +02003510 ret = LY_EVALID;
3511 goto cleanup;
3512 }
David Sedlákd6e56892019-07-01 15:40:24 +02003513 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003514 /* note that element was parsed for easy uniqueness check in next iterations */
3515 subelem->flags |= YIN_SUBELEM_PARSED;
3516
Michal Vasko193dacd2022-10-13 08:43:05 +02003517 switch (cur_stmt) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003518 /* call responsible function */
3519 case LY_STMT_EXTENSION_INSTANCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003520 ret = yin_parse_extension_instance(ctx, parent, parent_stmt,
Michal Vasko69730152020-10-09 16:30:07 +02003521 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003522 break;
3523 case LY_STMT_ACTION:
3524 case LY_STMT_RPC:
3525 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3526 break;
3527 case LY_STMT_ANYDATA:
3528 case LY_STMT_ANYXML:
Michal Vasko193dacd2022-10-13 08:43:05 +02003529 ret = yin_parse_any(ctx, cur_stmt, (struct tree_node_meta *)subelem->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01003530 break;
3531 case LY_STMT_ARGUMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003532 ret = yin_parse_argument(ctx, parent, (struct yin_argument_meta *)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003533 break;
3534 case LY_STMT_AUGMENT:
3535 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3536 break;
3537 case LY_STMT_BASE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003538 ret = yin_parse_base(ctx, parent_stmt, subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003539 break;
3540 case LY_STMT_BELONGS_TO:
3541 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3542 break;
3543 case LY_STMT_BIT:
3544 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3545 break;
3546 case LY_STMT_CASE:
3547 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3548 break;
3549 case LY_STMT_CHOICE:
3550 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3551 break;
3552 case LY_STMT_CONFIG:
3553 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3554 break;
3555 case LY_STMT_CONTACT:
3556 case LY_STMT_DESCRIPTION:
3557 case LY_STMT_ORGANIZATION:
3558 case LY_STMT_REFERENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003559 ret = yin_parse_meta(ctx, parent, cur_stmt, (const char **)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003560 break;
3561 case LY_STMT_CONTAINER:
3562 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3563 break;
3564 case LY_STMT_DEFAULT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003565 ret = yin_parse_qname(ctx, cur_stmt, subelem, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003566 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003567 case LY_STMT_ERROR_APP_TAG:
3568 case LY_STMT_KEY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003569 ret = yin_parse_simple_elem(ctx, parent, cur_stmt, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3570 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003571 case LY_STMT_PRESENCE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003572 ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003573 break;
3574 case LY_STMT_DEVIATE:
3575 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3576 break;
3577 case LY_STMT_DEVIATION:
3578 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3579 break;
3580 case LY_STMT_ENUM:
3581 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3582 break;
3583 case LY_STMT_ERROR_MESSAGE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003584 ret = yin_parse_err_msg(ctx, parent, (const char **)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003585 break;
3586 case LY_STMT_EXTENSION:
3587 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3588 break;
3589 case LY_STMT_FEATURE:
3590 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3591 break;
3592 case LY_STMT_FRACTION_DIGITS:
3593 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3594 break;
3595 case LY_STMT_GROUPING:
3596 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3597 break;
3598 case LY_STMT_IDENTITY:
3599 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3600 break;
Radek Išabe8a6532021-03-29 08:54:22 +02003601 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003602 case LY_STMT_IF_FEATURE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003603 ret = yin_parse_qname(ctx, cur_stmt, subelem, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02003604 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003605 case LY_STMT_UNITS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003606 ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003607 break;
3608 case LY_STMT_IMPORT:
3609 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3610 break;
3611 case LY_STMT_INCLUDE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003612 if ((parent_stmt == LY_STMT_SUBMODULE) && (PARSER_CUR_PMOD(ctx)->version == LYS_VERSION_1_1)) {
3613 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in "
3614 "submodules (%s) are not necessary.", ((struct lysp_submodule *)PARSER_CUR_PMOD(ctx))->name);
Radek Krejcieeee95c2021-01-19 10:57:22 +01003615 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003616 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3617 break;
3618 case LY_STMT_INPUT:
3619 case LY_STMT_OUTPUT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003620 ret = yin_parse_inout(ctx, cur_stmt, (struct inout_meta *)subelem->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01003621 break;
3622 case LY_STMT_LEAF:
3623 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3624 break;
3625 case LY_STMT_LEAF_LIST:
3626 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3627 break;
3628 case LY_STMT_LENGTH:
3629 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3630 break;
3631 case LY_STMT_LIST:
3632 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3633 break;
3634 case LY_STMT_MANDATORY:
3635 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3636 break;
3637 case LY_STMT_MAX_ELEMENTS:
3638 case LY_STMT_MIN_ELEMENTS:
Michal Vasko193dacd2022-10-13 08:43:05 +02003639 ret = yin_parse_minmax(ctx, parent_stmt, cur_stmt, subelem->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01003640 break;
3641 case LY_STMT_MODIFIER:
Michal Vasko193dacd2022-10-13 08:43:05 +02003642 ret = yin_parse_modifier(ctx, parent, (const char **)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003643 break;
3644 case LY_STMT_MUST:
3645 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3646 break;
3647 case LY_STMT_NAMESPACE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003648 ret = yin_parse_simple_elem(ctx, parent, cur_stmt, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003649 break;
3650 case LY_STMT_NOTIFICATION:
3651 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3652 break;
3653 case LY_STMT_ORDERED_BY:
Michal Vasko193dacd2022-10-13 08:43:05 +02003654 ret = yin_parse_orderedby(ctx, parent, (uint16_t *)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003655 break;
3656 case LY_STMT_PATH:
Michal Vasko193dacd2022-10-13 08:43:05 +02003657 ret = yin_parse_path(ctx, (struct lysp_type *)subelem->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01003658 break;
3659 case LY_STMT_PATTERN:
3660 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3661 break;
3662 case LY_STMT_VALUE:
3663 case LY_STMT_POSITION:
Michal Vasko193dacd2022-10-13 08:43:05 +02003664 ret = yin_parse_value_pos(ctx, cur_stmt, (struct lysp_type_enum *)subelem->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01003665 break;
3666 case LY_STMT_PREFIX:
Michal Vasko193dacd2022-10-13 08:43:05 +02003667 ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_VALUE,
3668 Y_IDENTIF_ARG, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003669 break;
3670 case LY_STMT_RANGE:
3671 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3672 break;
3673 case LY_STMT_REFINE:
3674 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3675 break;
3676 case LY_STMT_REQUIRE_INSTANCE:
3677 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3678 break;
3679 case LY_STMT_REVISION:
3680 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3681 break;
3682 case LY_STMT_REVISION_DATE:
3683 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3684 break;
3685 case LY_STMT_STATUS:
3686 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3687 break;
3688 case LY_STMT_TYPE:
Michal Vasko193dacd2022-10-13 08:43:05 +02003689 ret = yin_parse_type(ctx, parent_stmt, subelem);
Michal Vaskob36053d2020-03-26 15:49:30 +01003690 break;
3691 case LY_STMT_TYPEDEF:
3692 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3693 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003694 case LY_STMT_USES:
3695 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3696 break;
3697 case LY_STMT_WHEN:
3698 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3699 break;
3700 case LY_STMT_YANG_VERSION:
Michal Vasko193dacd2022-10-13 08:43:05 +02003701 ret = yin_parse_yangversion(ctx, parent, (uint8_t *)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003702 break;
3703 case LY_STMT_YIN_ELEMENT:
Michal Vasko193dacd2022-10-13 08:43:05 +02003704 ret = yin_parse_yin_element(ctx, parent, (uint16_t *)subelem->dest, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003705 break;
3706 case LY_STMT_ARG_TEXT:
3707 case LY_STMT_ARG_VALUE:
3708 /* TODO what to do with content/attributes? */
3709 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3710 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3711 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3712 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3713 }
Michal Vasko193dacd2022-10-13 08:43:05 +02003714 ret = yin_parse_content(ctx, NULL, 0, parent, cur_stmt, (const char **)subelem->dest, NULL);
Michal Vaskob36053d2020-03-26 15:49:30 +01003715 break;
3716 default:
3717 LOGINT(ctx->xmlctx->ctx);
3718 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003719 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003720 LY_CHECK_GOTO(ret, cleanup);
3721 subelem = NULL;
3722
3723 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003724 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003725 } else {
3726 LY_CHECK_RET(ret);
3727 /* elements with text or none content */
3728 /* save text content, if text_content isn't set, it's just ignored */
3729 /* no resources are allocated in this branch, no need to use cleanup label */
3730 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3731 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003732 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 +01003733 LY_CHECK_RET(!*text_content, LY_EMEM);
3734 }
3735
3736 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003737 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003738
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003739 /* mandatory subelements are checked only after whole element was succesfully parsed */
Michal Vasko193dacd2022-10-13 08:43:05 +02003740 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, parent_stmt));
David Sedlákd6e56892019-07-01 15:40:24 +02003741
3742cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003743 return ret;
3744}
3745
David Sedlákaa98bba2019-09-12 11:52:14 +02003746/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003747 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003748 *
3749 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003750 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003751 * @return LY_ERR values.
3752 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003753LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003754yin_parse_mod(struct lysp_yin_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003755{
David Sedlák81497a32019-08-13 16:56:26 +02003756 LY_ERR ret = LY_SUCCESS;
3757 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003758 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003759 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003760
Michal Vaskoc3781c32020-10-06 14:04:08 +02003761 mod->is_submod = 0;
3762
Michal Vaskob36053d2020-03-26 15:49:30 +01003763 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3764 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 +01003765 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003766 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3767 LY_STMT_ANYXML, &mod->data, 0,
3768 LY_STMT_AUGMENT, &mod->augments, 0,
3769 LY_STMT_CHOICE, &mod->data, 0,
3770 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3771 LY_STMT_CONTAINER, &mod->data, 0,
3772 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3773 LY_STMT_DEVIATION, &mod->deviations, 0,
3774 LY_STMT_EXTENSION, &mod->extensions, 0,
3775 LY_STMT_FEATURE, &mod->features, 0,
3776 LY_STMT_GROUPING, &mod->groupings, 0,
3777 LY_STMT_IDENTITY, &mod->identities, 0,
3778 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3779 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3780 LY_STMT_LEAF, &mod->data, 0,
3781 LY_STMT_LEAF_LIST, &mod->data, 0,
3782 LY_STMT_LIST, &mod->data, 0,
3783 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3784 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3785 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3786 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3787 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3788 LY_STMT_REVISION, &mod->revs, 0,
3789 LY_STMT_RPC, &mod->rpcs, 0,
3790 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3791 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003792 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003793 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003794
Michal Vasko193dacd2022-10-13 08:43:05 +02003795 ret = yin_parse_content(ctx, subelems, subelems_size, mod, LY_STMT_MODULE, NULL, &mod->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01003796 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003797 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003798
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003799 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01003800 LY_CHECK_RET(yin_unres_exts_add(ctx, mod->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003801
David Sedláked809f12019-09-13 10:15:11 +02003802 /* submodules share the namespace with the module names, so there must not be
3803 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003804 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003805 if (dup) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003806 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003807 return LY_EVALID;
3808 }
3809
3810 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003811}
3812
Michal Vaskoafac7822020-10-20 14:22:26 +02003813/**
3814 * @brief Parse submodule element.
3815 *
3816 * @param[in,out] ctx Yin parser context for logging and to store current state.
3817 * @param[in] mod_attrs Attributes of submodule element.
3818 * @param[out] submod Parsed submodule structure.
Michal Vaskoafac7822020-10-20 14:22:26 +02003819 * @return LY_ERR values.
3820 */
David Sedlák3b4db242018-10-19 16:11:01 +02003821LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003822yin_parse_submod(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003823{
David Sedlák81497a32019-08-13 16:56:26 +02003824 LY_ERR ret = LY_SUCCESS;
3825 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003826 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003827 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003828
Michal Vaskoc3781c32020-10-06 14:04:08 +02003829 submod->is_submod = 1;
3830
Michal Vaskob36053d2020-03-26 15:49:30 +01003831 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3832 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 +01003833 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003834 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3835 LY_STMT_ANYXML, &submod->data, 0,
3836 LY_STMT_AUGMENT, &submod->augments, 0,
3837 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3838 LY_STMT_CHOICE, &submod->data, 0,
3839 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3840 LY_STMT_CONTAINER, &submod->data, 0,
3841 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3842 LY_STMT_DEVIATION, &submod->deviations, 0,
3843 LY_STMT_EXTENSION, &submod->extensions, 0,
3844 LY_STMT_FEATURE, &submod->features, 0,
3845 LY_STMT_GROUPING, &submod->groupings, 0,
3846 LY_STMT_IDENTITY, &submod->identities, 0,
3847 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3848 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3849 LY_STMT_LEAF, &submod->data, 0,
3850 LY_STMT_LEAF_LIST, &submod->data, 0,
3851 LY_STMT_LIST, &submod->data, 0,
3852 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3853 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3854 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3855 LY_STMT_REVISION, &submod->revs, 0,
3856 LY_STMT_RPC, &submod->rpcs, 0,
3857 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3858 LY_STMT_USES, &submod->data, 0,
3859 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3860 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003861
Michal Vasko193dacd2022-10-13 08:43:05 +02003862 ret = yin_parse_content(ctx, subelems, subelems_size, submod, LY_STMT_SUBMODULE, NULL, &submod->exts);
Radek Krejcif13b87b2020-12-01 22:02:17 +01003863 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003864 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003865
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003866 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
Michal Vasko4929d5f2022-11-08 13:21:02 +01003867 LY_CHECK_RET(yin_unres_exts_add(ctx, submod->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003868
David Sedláked809f12019-09-13 10:15:11 +02003869 /* submodules share the namespace with the module names, so there must not be
3870 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003871 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003872 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003873 LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003874 return LY_EVALID;
3875 }
3876
3877 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003878}
3879
3880LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003881yin_parse_submodule(struct lysp_yin_ctx **yin_ctx, struct ly_ctx *ctx, struct lysp_ctx *main_ctx,
Radek Krejci0f969882020-08-21 16:56:47 +02003882 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003883{
Radek Krejcid6b76452019-09-03 17:03:03 +02003884 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003885 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003886 struct lysp_submodule *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02003887 struct lysf_ctx fctx = {.ctx = ctx};
David Sedlák8985a142019-07-31 16:43:06 +02003888
aPiecek56be92a2021-07-01 07:18:10 +02003889 assert(yin_ctx && ctx && main_ctx && in && submod);
3890
David Sedlák8985a142019-07-31 16:43:06 +02003891 /* create context */
3892 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003893 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003894 (*yin_ctx)->format = LYS_IN_YIN;
aPiecek56be92a2021-07-01 07:18:10 +02003895 (*yin_ctx)->main_ctx = main_ctx;
Michal Vasko63f3d842020-07-08 10:10:14 +02003896 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003897
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003898 mod_p = calloc(1, sizeof *mod_p);
3899 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01003900 mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003901 mod_p->parsing = 1;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003902
3903 /* use main context parsed mods adding the current one */
3904 (*yin_ctx)->parsed_mods = main_ctx->parsed_mods;
3905 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003906
David Sedlák8985a142019-07-31 16:43:06 +02003907 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003908 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 +02003909 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003910 if (kw == LY_STMT_MODULE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003911 LOGERR(ctx, LY_EDENIED, "Input data contains module when a submodule is expected.");
David Sedlák8985a142019-07-31 16:43:06 +02003912 ret = LY_EINVAL;
3913 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003914 } else if (kw != LY_STMT_SUBMODULE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003915 LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, lyplg_ext_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003916 ret = LY_EVALID;
3917 goto cleanup;
3918 }
3919
Michal Vaskob36053d2020-03-26 15:49:30 +01003920 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003921 LY_CHECK_GOTO(ret, cleanup);
3922
David Sedlákbf8a2b72019-08-14 16:48:10 +02003923 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003924 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003925 if (in->current[0] == '\n') {
3926 LY_IN_NEW_LINE(in);
3927 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003928 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003929 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003930 if (in->current[0]) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003931 LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003932 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003933 ret = LY_EVALID;
3934 goto cleanup;
3935 }
3936
David Sedlák8985a142019-07-31 16:43:06 +02003937 mod_p->parsing = 0;
3938 *submod = mod_p;
3939
3940cleanup:
Michal Vasko193dacd2022-10-13 08:43:05 +02003941 LOG_LOCBACK(0, 0, 0, 1);
David Sedlák8985a142019-07-31 16:43:06 +02003942 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02003943 lysp_module_free(&fctx, (struct lysp_module *)mod_p);
Michal Vaskod0625d72022-10-06 15:02:50 +02003944 lysp_yin_ctx_free(*yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003945 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003946 }
David Sedlák8985a142019-07-31 16:43:06 +02003947 return ret;
3948}
3949
3950LY_ERR
Michal Vaskod0625d72022-10-06 15:02:50 +02003951yin_parse_module(struct lysp_yin_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003952{
David Sedláke4889912018-11-02 09:52:40 +01003953 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003954 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003955 struct lysp_module *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02003956 struct lysf_ctx fctx = {.ctx = mod->ctx};
David Sedlák3b4db242018-10-19 16:11:01 +02003957
David Sedlák8985a142019-07-31 16:43:06 +02003958 /* create context */
3959 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003960 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003961 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003962 LY_CHECK_ERR_RET(ly_set_new(&(*yin_ctx)->parsed_mods), free(*yin_ctx); LOGMEM(mod->ctx), LY_EMEM);
Michal Vasko63f3d842020-07-08 10:10:14 +02003963 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
Michal Vaskod0625d72022-10-06 15:02:50 +02003964 (*yin_ctx)->main_ctx = (struct lysp_ctx *)(*yin_ctx);
David Sedlákda8ffa32019-07-08 14:17:10 +02003965
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003966 mod_p = calloc(1, sizeof *mod_p);
3967 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3968 mod_p->mod = mod;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003969 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003970
David Sedlák8985a142019-07-31 16:43:06 +02003971 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003972 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 +02003973 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003974 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003975 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 +01003976 ret = LY_EINVAL;
3977 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003978 } else if (kw != LY_STMT_MODULE) {
Michal Vasko193dacd2022-10-13 08:43:05 +02003979 LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, lyplg_ext_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003980 ret = LY_EVALID;
3981 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003982 }
3983
David Sedlák00250342019-06-21 14:19:39 +02003984 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003985 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003986 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003987
David Sedlákbf8a2b72019-08-14 16:48:10 +02003988 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003989 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003990 if (in->current[0] == '\n') {
3991 LY_IN_NEW_LINE(in);
3992 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003993 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003994 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003995 if (in->current[0]) {
Michal Vaskod0625d72022-10-06 15:02:50 +02003996 LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003997 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003998 ret = LY_EVALID;
3999 goto cleanup;
4000 }
4001
David Sedlák3017da42019-02-15 09:48:04 +01004002 mod->parsed = mod_p;
4003
4004cleanup:
Michal Vasko193dacd2022-10-13 08:43:05 +02004005 LOG_LOCBACK(0, 0, 0, 1);
4006 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004007 lysp_module_free(&fctx, mod_p);
Michal Vaskod0625d72022-10-06 15:02:50 +02004008 lysp_yin_ctx_free(*yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02004009 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01004010 }
David Sedlák2e411422018-12-17 02:35:39 +01004011 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02004012}