blob: 964fdd99d6b032749cbf575b45d6cc1533820cef [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 */
107 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
108 uint16_t flags; /**< describes constraints of subelement can be set to YIN_SUBELEM_MANDATORY, YIN_SUBELEM_UNIQUE, YIN_SUBELEM_FIRST, YIN_SUBELEM_VER2, and YIN_SUBELEM_DEFAULT_TEXT */
109};
110
111/* Meta information passed to yin_parse_argument function,
112 holds information about where content of argument element will be stored. */
113struct yin_argument_meta {
114 uint16_t *flags; /**< Argument flags */
115 const char **argument; /**< Argument value */
116};
117
118/**
119 * @brief Meta information passed to functions working with tree_schema,
120 * that require additional information about parent node.
121 */
122struct tree_node_meta {
123 struct lysp_node *parent; /**< parent node */
124 struct lysp_node **nodes; /**< linked list of siblings */
125};
126
127/**
128 * @brief Meta information passed to yin_parse_import function.
129 */
130struct import_meta {
131 const char *prefix; /**< module prefix. */
132 struct lysp_import **imports; /**< imports to add to. */
133};
134
135/**
136 * @brief Meta information passed to yin_parse_include function.
137 */
138struct include_meta {
139 const char *name; /**< Module/submodule name. */
140 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
141};
142
143/**
144 * @brief Meta information passed to yin_parse_inout function.
145 */
146struct inout_meta {
147 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100148 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200149};
150
151/**
152 * @brief Meta information passed to yin_parse_minmax function.
153 */
154struct minmax_dev_meta {
155 uint32_t *lim; /**< min/max value to write to. */
156 uint16_t *flags; /**< min/max flags to write to. */
157 struct lysp_ext_instance **exts; /**< extension instances to add to. */
158};
159
160LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
161 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
162
163/**
164 * @brief Match yang keyword from yin data.
165 *
166 * @param[in,out] ctx Yin parser context for logging and to store current state.
167 * @param[in] name Start of keyword name
168 * @param[in] name_len Lenght of keyword name.
169 * @param[in] prefix Start of keyword prefix.
170 * @param[in] prefix_len Lenght of prefix.
171 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
172 *
173 * @return yang_keyword values.
174 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200175enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100176yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200177 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200178{
David Sedlák8f7a1172019-06-20 14:42:18 +0200179 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200180 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200181 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200182 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200183
Michal Vasko69730152020-10-09 16:30:07 +0200184 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200185 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200186 }
187
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200188 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200189 if (ns) {
190 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200191 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200192 }
193 } else {
194 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200195 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200196 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200197
Michal Vasko63f3d842020-07-08 10:10:14 +0200198 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
199 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100200 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200201 name = in->current;
202 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200203
204 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200205 /* 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 +0200206 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200207 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200208 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200209 return kw;
210 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200211 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200212 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200213 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200214 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200215 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200216 }
217}
218
Michal Vaskoafac7822020-10-20 14:22:26 +0200219/**
220 * @brief Match argument name.
221 *
222 * @param[in] name String representing name.
223 * @param[in] len Lenght of the name.
224 *
225 * @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.
340 *
341 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
342 */
David Sedlák81497a32019-08-13 16:56:26 +0200343static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100344subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200345 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200346{
347 va_list ap;
348
349 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200350 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200351
352 va_start(ap, result);
353 for (size_t i = 0; i < count; ++i) {
354 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200355 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200356 /* DEST */
357 if (IS_NODE_ELEM((*result)[i].type)) {
358 struct tree_node_meta *node_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200359
David Sedlák81497a32019-08-13 16:56:26 +0200360 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200361 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200362 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200363 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200364 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200365 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200366 struct import_meta *imp_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200367
David Sedlák81497a32019-08-13 16:56:26 +0200368 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200369 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200370 imp_meta->prefix = va_arg(ap, const char *);
371 imp_meta->imports = va_arg(ap, struct lysp_import **);
372 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200373 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200374 struct include_meta *inc_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200375
David Sedlák81497a32019-08-13 16:56:26 +0200376 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200377 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200378 inc_meta->name = va_arg(ap, const char *);
379 inc_meta->includes = va_arg(ap, struct lysp_include **);
380 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200381 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200382 struct inout_meta *inout_meta = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +0200383
David Sedlák81497a32019-08-13 16:56:26 +0200384 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200385 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200386 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100387 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200388 (*result)[i].dest = inout_meta;
389 } else {
390 (*result)[i].dest = va_arg(ap, void *);
391 }
392 /* FLAGS */
393 (*result)[i].flags = va_arg(ap, int);
394 }
395 va_end(ap);
396
397 return LY_SUCCESS;
398
David Sedlákbf8a2b72019-08-14 16:48:10 +0200399mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200400 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100401 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200402 return LY_EMEM;
403}
404
Michal Vaskoafac7822020-10-20 14:22:26 +0200405/**
406 * @brief Check that val is valid UTF8 character sequence of val_type.
407 * Doesn't check empty string, only character validity.
408 *
409 * @param[in] ctx Yin parser context for logging.
410 * @param[in] val_type Type of the input string to select method of checking character validity.
411 *
412 * @return LY_ERR values.
413 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200414LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100415yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200416{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200417 uint8_t prefix = 0;
418 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100419 size_t utf8_char_len, already_read = 0;
420 const char *val;
421
422 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
423
424 val = ctx->xmlctx->value;
425 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200426 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200427 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200428
429 switch (val_type) {
430 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200431 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, NULL));
David Sedlák4a650532019-07-10 11:55:18 +0200432 break;
433 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200434 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, &prefix));
David Sedlák4a650532019-07-10 11:55:18 +0200435 break;
436 case Y_STR_ARG:
437 case Y_MAYBE_STR_ARG:
438 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
439 break;
440 }
Radek Iša2eac74c2021-03-15 15:53:08 +0100441
442 already_read += utf8_char_len;
443 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200444 }
445
Radek Iša42cc0b72021-03-15 16:51:31 +0100446 if ((already_read == 0) &&
447 ((val_type == Y_PREF_IDENTIF_ARG) || (val_type == Y_IDENTIF_ARG))) {
448 /* Empty identifier or prefix*/
449 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Empty identifier is not allowed.");
450 return LY_EVALID;
451 }
452
David Sedlák4a650532019-07-10 11:55:18 +0200453 return LY_SUCCESS;
454}
455
David Sedlákb4e44562019-07-04 15:42:12 +0200456/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100457 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200458 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200459 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200460 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
461 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200462 * @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 +0200463 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200464 * @param[in] current_element Identification of current element, used for logging.
465 *
466 * @return LY_ERR values.
467 */
468static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100469yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200470 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200471{
David Sedlákc5b20842019-08-13 10:18:31 +0200472 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200473 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200474
David Sedlák1bccdfa2019-06-17 15:55:27 +0200475 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100476 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200477 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100478 if (!ctx->xmlctx->prefix) {
479 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200480 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100481 /* skip it */
482 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200483 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200484 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200485 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200486 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100487
488 /* go to value */
489 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
490 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200491 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 +0200492 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200493 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100494 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200495 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200496 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200497 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100498 } else {
499 /* skip it */
500 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200501 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100502
503 /* next attribute */
504 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200505 }
506
David Sedlák292763b2019-07-09 11:10:53 +0200507 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200508 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100509 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200510 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200511 return LY_EVALID;
512 }
513
514 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200515}
516
David Sedlákd6e56892019-07-01 15:40:24 +0200517/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200518 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200519 *
520 * @param[in] type Type of wanted record.
521 * @param[in] array_size Size of array.
522 * @param[in] array Searched array.
523 *
524 * @return Pointer to desired record on success, NULL if element is not in the array.
525 */
David Sedlákb4e44562019-07-04 15:42:12 +0200526static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200527get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200528{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200529 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200530 if (array[u].type == type) {
531 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200532 }
533 }
David Sedlákd6e56892019-07-01 15:40:24 +0200534 return NULL;
535}
536
David Sedlákbba38e52019-07-09 15:20:01 +0200537/**
538 * @brief Helper function to check mandatory constraint of subelement.
539 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200540 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200541 * @param[in] subelem_info Array of information about subelements.
542 * @param[in] subelem_info_size Size of subelem_info array.
543 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
544 *
545 * @return LY_ERR values.
546 */
547static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100548yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200549 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200550{
David Sedlákb0faad82019-07-04 14:28:59 +0200551 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200552 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200553 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200554 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200555 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200556 return LY_EVALID;
557 }
558 }
559
560 return LY_SUCCESS;
561}
562
David Sedlákbba38e52019-07-09 15:20:01 +0200563/**
564 * @brief Helper function to check "first" constraint of subelement.
565 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200566 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200567 * @param[in] subelem_info Array of information about subelements.
568 * @param[in] subelem_info_size Size of subelem_info array.
569 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200570 * @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 +0200571 *
572 * @return LY_ERR values.
573 */
574static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100575yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200576 signed char subelem_info_size, enum ly_stmt current_element,
577 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200578{
David Sedlákb0faad82019-07-04 14:28:59 +0200579 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200580 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200581 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200582 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200583 return LY_EVALID;
584 }
585 }
586
587 return LY_SUCCESS;
588}
589
David Sedlákbba38e52019-07-09 15:20:01 +0200590/**
David Sedlákb4e44562019-07-04 15:42:12 +0200591 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
592 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200593 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200594 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200595 * @param[in] kw Type of current element.
596 * @param[out] value Where value of attribute should be stored.
597 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200598 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200599 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200600 * @return LY_ERR values.
601 */
David Sedlákb4e44562019-07-04 15:42:12 +0200602static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100603yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200604 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200605{
Michal Vaskob36053d2020-03-26 15:49:30 +0100606 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
607 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100608 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200609 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
610 };
David Sedlákb4e44562019-07-04 15:42:12 +0200611
Radek Krejcif13b87b2020-12-01 22:02:17 +0100612 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200613}
614
615/**
David Sedlák6542aed2019-08-14 10:47:43 +0200616 * @brief Parse path element.
617 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200618 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200619 * @param[in] kw Type of current element.
620 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200621 * @return LY_ERR values.
622 */
623static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100624yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200625{
Michal Vasko004d3152020-06-11 19:59:22 +0200626 LY_ERR ret;
627 const char *str_path;
628
629 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
Michal Vaskoed725d72021-06-23 12:03:45 +0200630 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
Michal Vasko69730152020-10-09 16:30:07 +0200631 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200632 lydict_remove(ctx->xmlctx->ctx, str_path);
633 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200634 type->flags |= LYS_SET_PATH;
635
636 return LY_SUCCESS;
637}
638
639/**
David Sedlákd3983112019-07-12 11:20:56 +0200640 * @brief Parse pattern element.
641 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200642 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200643 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200644 * @return LY_ERR values.
645 */
646static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100647yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200648{
649 const char *real_value = NULL;
650 char *saved_value = NULL;
651 struct lysp_restr *restr;
652
Michal Vaskob36053d2020-03-26 15:49:30 +0100653 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
654 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
655 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 +0200656 size_t len = strlen(real_value);
657
658 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100659 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200660 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100661 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100662 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200663 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200664 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100665 restr->arg.mod = PARSER_CUR_PMOD(ctx);
David Sedlákd3983112019-07-12 11:20:56 +0200666 type->flags |= LYS_SET_PATTERN;
667
Radek Krejcif13b87b2020-12-01 22:02:17 +0100668 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200669 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
670 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
671 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
672 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
673 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
674 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
675 };
Michal Vasko69730152020-10-09 16:30:07 +0200676
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200677 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts));
678
679 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
680 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, restr->exts, 1, NULL));
681
682 return LY_SUCCESS;
David Sedlákd3983112019-07-12 11:20:56 +0200683}
684
David Sedlákc5b20842019-08-13 10:18:31 +0200685/**
686 * @brief Parse fraction-digits element.
687 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200688 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200689 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200690 * @return LY_ERR values.
691 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200692static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100693yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200694{
695 const char *temp_val = NULL;
696 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200697 unsigned long long int num;
David Sedlákf75d55e2019-07-12 16:52:50 +0200698
Michal Vaskob36053d2020-03-26 15:49:30 +0100699 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
700 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 +0200701
Michal Vasko69730152020-10-09 16:30:07 +0200702 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200703 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100704 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200705 return LY_EVALID;
706 }
707
708 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +0200709 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200710 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200711 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100712 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200713 return LY_EVALID;
714 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100715 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200716 LOGVAL_PARSER((struct lys_parser_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 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100720 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200721 type->fraction_digits = num;
722 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100723 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200724 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
725 };
Michal Vasko69730152020-10-09 16:30:07 +0200726
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200727 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts));
728
729 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
730 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, type->exts, 1, NULL));
731
732 return LY_SUCCESS;
David Sedlákf75d55e2019-07-12 16:52:50 +0200733}
734
David Sedlák07869a52019-07-12 14:28:19 +0200735/**
David Sedlák43801c92019-08-05 15:58:54 +0200736 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200737 *
738 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200739 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200740 * @return LY_ERR values.
741 */
David Sedlákca36c422019-07-12 12:47:55 +0200742static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100743yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200744{
David Sedlák07869a52019-07-12 14:28:19 +0200745 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200746
Michal Vaskob36053d2020-03-26 15:49:30 +0100747 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200748 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100749 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
750 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
David Sedlák43801c92019-08-05 15:58:54 +0200751 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100752 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200753 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200754
Radek Krejcif13b87b2020-12-01 22:02:17 +0100755 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200756 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
757 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
758 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
759 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
760 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
761 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
762 };
Michal Vasko69730152020-10-09 16:30:07 +0200763
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200764 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts));
765
766 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
767 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, en->exts, 1, NULL));
768
769 return LY_SUCCESS;
David Sedlák43801c92019-08-05 15:58:54 +0200770}
771
772/**
773 * @brief Parse bit element.
774 *
775 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200776 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200777 * @return LY_ERR values.
778 */
779static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100780yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200781{
782 struct lysp_type_enum *en;
783
Michal Vaskob36053d2020-03-26 15:49:30 +0100784 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200785 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100786 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
787 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
Radek Iša8b640882021-03-12 17:59:34 +0100788 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->bits, name, "bit", en->name);
David Sedlák43801c92019-08-05 15:58:54 +0200789
Radek Krejcif13b87b2020-12-01 22:02:17 +0100790 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200791 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
792 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
793 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
794 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
795 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
796 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
797 };
Michal Vasko69730152020-10-09 16:30:07 +0200798
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200799 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts));
800
801 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
802 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, en->exts, 1, NULL));
803
804 return LY_SUCCESS;
David Sedlákca36c422019-07-12 12:47:55 +0200805}
806
David Sedlákd3983112019-07-12 11:20:56 +0200807/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200808 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
809 * more instances, such as base or if-feature.
810 *
811 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200812 * @param[in] kw Type of current element.
813 * @param[out] values Parsed values to add to.
814 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200815 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200816 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200817 * @return LY_ERR values.
818 */
819static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100820yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
Radek Krejci0f969882020-08-21 16:56:47 +0200821 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200822{
823 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200824
Michal Vaskob36053d2020-03-26 15:49:30 +0100825 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200826 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100827 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200828 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
829 };
David Sedlák968ac342019-07-11 15:17:59 +0200830
Michal Vaskob36053d2020-03-26 15:49:30 +0100831 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
832 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200833
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200834 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts));
835
836 return LY_SUCCESS;
David Sedlák5f8191e2019-07-08 16:35:52 +0200837}
838
839/**
David Sedlák6542aed2019-08-14 10:47:43 +0200840 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
841 *
842 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200843 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200844 * @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 +0200845 * @param[in] arg_type Expected type of attribute.
846 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200847 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200848 * @return LY_ERR values.
849 */
850static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100851yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200852 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200853{
854 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100855 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200856 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200857 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100858 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200859 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200860 }
861
862 return LY_SUCCESS;
863}
864
865/**
866 * @brief Parse base element.
867 *
868 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200869 * @param[in] parent Identification of parent element.
870 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200871 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200872 * @return LY_ERR values.
873 */
874static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100875yin_parse_base(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, void *dest, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200876{
877 struct lysp_type *type = NULL;
878
Radek Krejcid6b76452019-09-03 17:03:03 +0200879 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200880 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100881 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200882 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200883 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200884 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100885 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200886 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200887 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100888 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200889 return LY_EINT;
890 }
891
892 return LY_SUCCESS;
893}
894
895/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200896 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200897 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200898 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100899 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200900 * @return LY_ERR values.
901 */
902static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100903yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200904{
905 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100906 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200907 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
908 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200909
910 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100911 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
912 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 +0200913 if (strcmp(temp_val, "true") == 0) {
914 type->require_instance = 1;
915 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200916 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200917 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100918 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200919 return LY_EVALID;
920 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100921 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200922
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200923 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts));
924
925 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
926 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, type->exts, 1, NULL));
927
928 return LY_SUCCESS;
David Sedlákcf5569a2019-07-11 13:31:34 +0200929}
930
931/**
David Sedlákce77bf52019-07-11 16:59:31 +0200932 * @brief Parse modifier element.
933 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200934 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200935 * @param[in,out] pat Value to write to.
936 * @param[in,out] exts Extension instances to add to.
937 *
938 * @return LY_ERR values.
939 */
940static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100941yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200942{
David Sedlákd3983112019-07-12 11:20:56 +0200943 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200944 const char *temp_val;
945 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100946 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200947 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
948 };
David Sedlákce77bf52019-07-11 16:59:31 +0200949
Michal Vaskob36053d2020-03-26 15:49:30 +0100950 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
951 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 +0200952 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200953 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200954 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100955 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200956 return LY_EVALID;
957 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100958 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200959
960 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200961 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100962 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200963 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100964 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200965
966 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100967 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200968 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200969
Michal Vaskoc0c64ae2022-10-06 10:15:23 +0200970 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts));
971
972 return LY_SUCCESS;
David Sedlákce77bf52019-07-11 16:59:31 +0200973}
974
975/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200976 * @brief Parse a restriction element (length, range or one instance of must).
977 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200978 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200979 * @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 +0200980 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200981 */
982static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100983yin_parse_restriction(struct lys_yin_parser_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
David Sedlákb7296dd2019-07-11 14:58:38 +0200984{
Radek Krejcid6b76452019-09-03 17:03:03 +0200985 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100986 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200987 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
988 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
989 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
990 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
991 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
992 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200993 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200994 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200995
Michal Vaskob36053d2020-03-26 15:49:30 +0100996 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200997 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko8a67eff2021-12-07 14:04:47 +0100998 restr->arg.mod = PARSER_CUR_PMOD(ctx);
Michal Vaskob36053d2020-03-26 15:49:30 +0100999
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001000 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts));
1001
1002 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1003 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, restr->exts, 1, NULL));
1004
1005 return LY_SUCCESS;
David Sedlákb7296dd2019-07-11 14:58:38 +02001006}
1007
1008/**
David Sedlák6542aed2019-08-14 10:47:43 +02001009 * @brief Parse range element.
1010 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001011 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001012 * @param[out] type Type structure to store parsed value and flags.
1013 *
1014 * @return LY_ERR values.
1015 */
1016static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001017yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +02001018{
1019 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +01001020 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1021 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +02001022 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +02001023
1024 return LY_SUCCESS;
1025}
1026
1027/**
1028 * @brief Parse length element.
1029 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001030 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001031 * @param[out] type Type structure to store parsed value and flags.
1032 *
1033 * @return LY_ERR values.
1034 */
1035static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001036yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +02001037{
1038 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +01001039 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1040 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +02001041 type->flags |= LYS_SET_LENGTH;
1042
1043 return LY_SUCCESS;
1044}
1045
1046/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001047 * @brief Parse must element.
1048 *
1049 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001050 * @param[in,out] restrs Restrictions to add to.
1051 *
1052 * @return LY_ERR values.
1053 */
1054static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001055yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001056{
1057 struct lysp_restr *restr;
1058
Michal Vaskob36053d2020-03-26 15:49:30 +01001059 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1060 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001061}
1062
1063/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001064 * @brief Parse a node id into an array.
1065 *
1066 * @param[in,out] ctx YIN parser context for logging and to store current state.
1067 * @param[in] kw Type of current element.
1068 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1069 * @param[in,out] exts Extension instances to add to.
1070 *
1071 * @return LY_ERR values.
1072 */
1073static LY_ERR
1074yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1075 struct lysp_ext_instance **exts)
1076{
1077 struct lysp_qname *qname, **qnames;
1078
1079 switch (kw) {
1080 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001081 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1082 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001083 } else {
1084 qnames = (struct lysp_qname **)subinfo->dest;
1085 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001086 }
Michal Vasko8a67eff2021-12-07 14:04:47 +01001087 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001088 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
Radek Išabe8a6532021-03-29 08:54:22 +02001089 case LY_STMT_UNIQUE:
1090 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1091 qnames = (struct lysp_qname **)subinfo->dest;
1092 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001093 qname->mod = PARSER_CUR_PMOD(ctx);
Radek Išabe8a6532021-03-29 08:54:22 +02001094 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001095 case LY_STMT_IF_FEATURE:
1096 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1097 qnames = (struct lysp_qname **)subinfo->dest;
1098 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko8a67eff2021-12-07 14:04:47 +01001099 qname->mod = PARSER_CUR_PMOD(ctx);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001100 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001101 default:
1102 break;
1103 }
1104
1105 LOGINT(ctx->xmlctx->ctx);
1106 return LY_EINT;
1107}
1108
1109/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001110 * @brief Parse position or value element.
1111 *
1112 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001113 * @param[in] kw Type of current element, can be set to LY_STMT_POSITION or LY_STMT_VALUE.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001114 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001115 *
1116 * @return LY_ERR values.
1117 */
1118static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001119yin_parse_value_pos(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type_enum *enm)
David Sedlák5545f5d2019-07-11 11:55:16 +02001120{
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001121 LY_ERR ret = LY_SUCCESS;
David Sedlák5545f5d2019-07-11 11:55:16 +02001122 const char *temp_val = NULL;
1123 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001124 long long int num = 0;
1125 unsigned long long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001126
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001127 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
1128
David Sedlák5545f5d2019-07-11 11:55:16 +02001129 /* set value flag */
1130 enm->flags |= LYS_SET_VALUE;
1131
1132 /* get attribute value */
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001133 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
1134 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw), cleanup);
Michal Vasko69730152020-10-09 16:30:07 +02001135 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001136 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001137 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001138 ret = LY_EVALID;
1139 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001140 }
1141
1142 /* convert value */
1143 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001144 if (kw == LY_STMT_VALUE) {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001145 num = strtoll(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001146 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001147 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001148 ret = LY_EVALID;
1149 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001150 }
1151 } else {
Michal Vasko73d77ab2021-07-23 12:45:55 +02001152 unum = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001153 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001154 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001155 ret = LY_EVALID;
1156 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001157 }
1158 }
1159 /* check if whole argument value was converted */
1160 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001161 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001162 ret = LY_EVALID;
1163 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001164 }
1165 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001166 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", ly_stmt2str(kw));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001167 ret = LY_EVALID;
1168 goto cleanup;
David Sedlák5545f5d2019-07-11 11:55:16 +02001169 }
1170 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001171 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001172 enm->value = num;
1173 } else {
1174 enm->value = unum;
1175 }
David Sedlák5545f5d2019-07-11 11:55:16 +02001176
1177 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001178 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001179 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1180 };
Michal Vasko69730152020-10-09 16:30:07 +02001181
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001182 LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts), cleanup);
David Sedlák5545f5d2019-07-11 11:55:16 +02001183
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001184 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1185 LY_CHECK_GOTO(ret = ly_set_add(&ctx->ext_inst, enm->exts, 1, NULL), cleanup);
1186
1187cleanup:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001188 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001189 return ret;
David Sedlák5545f5d2019-07-11 11:55:16 +02001190}
1191
David Sedlák05404f62019-07-24 14:11:53 +02001192/**
1193 * @brief Parse belongs-to element.
1194 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001195 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001196 * @param[out] submod Structure of submodule that is being parsed.
1197 * @param[in,out] exts Extension instances to add to.
1198 *
1199 * @return LY_ERR values
1200 */
1201static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001202yin_parse_belongs_to(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod, struct lysp_ext_instance **exts)
David Sedlák05404f62019-07-24 14:11:53 +02001203{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001204 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001205 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001206 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1207 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1208 };
David Sedlák05404f62019-07-24 14:11:53 +02001209
Michal Vaskob36053d2020-03-26 15:49:30 +01001210 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001211 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 +01001212 if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001213 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 +01001214 belongsto, PARSER_CUR_PMOD(ctx)->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001215 lydict_remove(ctx->xmlctx->ctx, belongsto);
1216 return LY_EVALID;
1217 }
1218 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001219
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001220 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts));
1221
1222 return LY_SUCCESS;
David Sedlák05404f62019-07-24 14:11:53 +02001223}
1224
David Sedlák5545f5d2019-07-11 11:55:16 +02001225/**
David Sedlákc1771b12019-07-10 15:55:46 +02001226 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001227 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001228 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001229 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001230 * @param[in] elem_type Type of element can be set to LY_STMT_ORGANIZATION or LY_STMT_CONTACT or LY_STMT_DESCRIPTION or LY_STMT_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +02001231 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001232 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001233 *
1234 * @return LY_ERR values.
1235 */
1236static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001237yin_parse_meta(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +02001238{
Radek Krejcid6b76452019-09-03 17:03:03 +02001239 assert(elem_type == LY_STMT_ORGANIZATION || elem_type == LY_STMT_CONTACT || elem_type == LY_STMT_DESCRIPTION || elem_type == LY_STMT_REFERENCE);
David Sedlákb4e44562019-07-04 15:42:12 +02001240
Radek Krejcif13b87b2020-12-01 22:02:17 +01001241 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001242 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1243 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1244 };
Michal Vasko69730152020-10-09 16:30:07 +02001245
David Sedlákdf2a9732019-08-07 13:23:16 +02001246 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001247 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1248 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, elem_type));
David Sedlákb4e44562019-07-04 15:42:12 +02001249
David Sedlákdf2a9732019-08-07 13:23:16 +02001250 /* parse content */
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001251 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts));
1252
1253 return LY_SUCCESS;
David Sedlákb4e44562019-07-04 15:42:12 +02001254}
1255
1256/**
David Sedlákc1771b12019-07-10 15:55:46 +02001257 * @brief Parse error-message element.
1258 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001259 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001260 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001261 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001262 *
1263 * @return LY_ERR values.
1264 */
1265static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001266yin_parse_err_msg(struct lys_yin_parser_ctx *ctx, const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +02001267{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001268 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001269 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1270 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1271 };
David Sedlákc1771b12019-07-10 15:55:46 +02001272
David Sedlákdf2a9732019-08-07 13:23:16 +02001273 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001274 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1275 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 +02001276
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001277 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts));
1278
1279 return LY_SUCCESS;
David Sedlákc1771b12019-07-10 15:55:46 +02001280}
1281
1282/**
David Sedlák6542aed2019-08-14 10:47:43 +02001283 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001284 *
1285 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001286 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001287 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001288 *
1289 * @return LY_ERR values.
1290 */
1291static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001292yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001293{
David Sedlák6542aed2019-08-14 10:47:43 +02001294 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001295
Radek Krejcid6b76452019-09-03 17:03:03 +02001296 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001297 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001298 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001299 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001300 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001301 type = (struct lysp_type *)subinfo->dest;
1302 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001303
David Sedlák6542aed2019-08-14 10:47:43 +02001304 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001305 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001306 struct lysp_type *nested_type = NULL;
Michal Vasko26bbb272022-08-02 14:54:33 +02001307
Michal Vaskob36053d2020-03-26 15:49:30 +01001308 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001309 type->flags |= LYS_SET_TYPE;
1310 type = nested_type;
1311 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001312
Michal Vasko8a67eff2021-12-07 14:04:47 +01001313 type->pmod = PARSER_CUR_PMOD(ctx);
Michal Vasko5bbcc242021-02-23 09:29:13 +01001314
Radek Krejcif13b87b2020-12-01 22:02:17 +01001315 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001316 {LY_STMT_BASE, type, 0},
1317 {LY_STMT_BIT, type, 0},
1318 {LY_STMT_ENUM, type, 0},
1319 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1320 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1321 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1322 {LY_STMT_PATTERN, type, 0},
1323 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1324 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
Michal Vasko608b0c02021-09-23 08:26:53 +02001325 {LY_STMT_TYPE, type, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001326 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1327 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001328
1329 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1330 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001331 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts));
1332
1333 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1334 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, type->exts, 1, NULL));
1335
1336 return LY_SUCCESS;
David Sedlák374d2b32019-07-17 15:06:55 +02001337}
1338
David Sedlák1af868e2019-07-17 17:03:14 +02001339/**
1340 * @brief Parse max-elements element.
1341 *
1342 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001343 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001344 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001345 * @param[in,out] exts Extension instances to add to.
1346 *
1347 * @return LY_ERR values.
1348 */
1349static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001350yin_parse_maxelements(struct lys_yin_parser_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák1af868e2019-07-17 17:03:14 +02001351{
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001352 LY_ERR ret = LY_SUCCESS;
David Sedlák1af868e2019-07-17 17:03:14 +02001353 const char *temp_val = NULL;
1354 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001355 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001356 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001357 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1358 };
David Sedlák374d2b32019-07-17 15:06:55 +02001359
David Sedlák1af868e2019-07-17 17:03:14 +02001360 *flags |= LYS_SET_MAX;
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001361 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
1362 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 +02001363 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '0') || ((temp_val[0] != 'u') && !isdigit(temp_val[0]))) {
David Sedlák1538a842019-08-08 15:38:51 +02001364 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001365 ret = LY_EVALID;
1366 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001367 }
1368
1369 if (strcmp(temp_val, "unbounded")) {
1370 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001371 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001372 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001373 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001374 ret = LY_EVALID;
1375 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001376 }
1377 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001378 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001379 ret = LY_EVALID;
1380 goto cleanup;
David Sedlák1af868e2019-07-17 17:03:14 +02001381 }
1382 *max = num;
1383 }
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001384
1385 LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts), cleanup);
1386
1387cleanup:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001388 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001389 return ret;
David Sedlák1af868e2019-07-17 17:03:14 +02001390}
David Sedlák374d2b32019-07-17 15:06:55 +02001391
1392/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001393 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001394 *
1395 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001396 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001397 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001398 * @param[in,out] exts Extension instances to add to.
1399 *
1400 * @return LY_ERR values.
1401 */
1402static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001403yin_parse_minelements(struct lys_yin_parser_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák09e18c92019-07-18 11:17:11 +02001404{
1405 const char *temp_val = NULL;
1406 char *ptr;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001407 unsigned long long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001408 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001409 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1410 };
David Sedlák09e18c92019-07-18 11:17:11 +02001411
1412 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001413 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1414 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 +02001415
Michal Vasko69730152020-10-09 16:30:07 +02001416 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001417 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001418 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001419 return LY_EVALID;
1420 }
1421
1422 errno = 0;
Michal Vasko73d77ab2021-07-23 12:45:55 +02001423 num = strtoull(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001424 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001425 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001426 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001427 return LY_EVALID;
1428 }
Michal Vasko69730152020-10-09 16:30:07 +02001429 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001430 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001431 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001432 return LY_EVALID;
1433 }
1434 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001435 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001436 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts));
1437
1438 return LY_SUCCESS;
David Sedlák09e18c92019-07-18 11:17:11 +02001439}
1440
David Sedláka2dad212019-07-18 12:45:19 +02001441/**
1442 * @brief Parse min-elements or max-elements element.
1443 *
1444 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001445 * @param[in] parent Identification of parent element.
1446 * @param[in] current Identification of current element.
1447 * @param[in] dest Where the parsed value and flags should be stored.
1448 *
1449 * @return LY_ERR values.
1450 */
David Sedlák09e18c92019-07-18 11:17:11 +02001451static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001452yin_parse_minmax(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, enum ly_stmt current, void *dest)
David Sedlák09e18c92019-07-18 11:17:11 +02001453{
Radek Krejcid6b76452019-09-03 17:03:03 +02001454 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1455 assert(parent == LY_STMT_LEAF_LIST || parent == LY_STMT_REFINE || parent == LY_STMT_LIST || parent == LY_STMT_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001456 uint32_t *lim;
1457 uint16_t *flags;
1458 struct lysp_ext_instance **exts;
1459
Radek Krejcid6b76452019-09-03 17:03:03 +02001460 if (parent == LY_STMT_LEAF_LIST) {
1461 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001462 flags = &((struct lysp_node_leaflist *)dest)->flags;
1463 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001464 } else if (parent == LY_STMT_REFINE) {
1465 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001466 flags = &((struct lysp_refine *)dest)->flags;
1467 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001468 } else if (parent == LY_STMT_LIST) {
1469 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001470 flags = &((struct lysp_node_list *)dest)->flags;
1471 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001472 } else {
1473 lim = ((struct minmax_dev_meta *)dest)->lim;
1474 flags = ((struct minmax_dev_meta *)dest)->flags;
1475 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001476 }
1477
Radek Krejcid6b76452019-09-03 17:03:03 +02001478 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001479 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001480 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001481 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001482 }
1483
1484 return LY_SUCCESS;
1485}
1486
1487/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001488 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001489 *
1490 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001491 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001492 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001493 *
1494 * @return LY_ERR values.
1495 */
1496static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001497yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001498{
1499 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001500 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001501 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1502 };
David Sedláka2dad212019-07-18 12:45:19 +02001503
Michal Vaskob36053d2020-03-26 15:49:30 +01001504 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1505 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 +02001506 if (strcmp(temp_val, "system") == 0) {
1507 *flags |= LYS_ORDBY_SYSTEM;
1508 } else if (strcmp(temp_val, "user") == 0) {
1509 *flags |= LYS_ORDBY_USER;
1510 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001511 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001512 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001513 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001514 return LY_EVALID;
1515 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001516 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001517
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001518 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts));
1519
1520 return LY_SUCCESS;
David Sedláka2dad212019-07-18 12:45:19 +02001521}
1522
1523/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001524 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001525 *
1526 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001527 * @param[in] any_kw Identification of current element, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
David Sedlákad83cf92019-08-13 12:53:53 +02001528 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001529 *
1530 * @return LY_ERR values.
1531 */
1532static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001533yin_parse_any(struct lys_yin_parser_ctx *ctx, enum ly_stmt any_kw, struct tree_node_meta *node_meta)
David Sedlák8a83bbb2019-07-18 14:46:00 +02001534{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001535 struct lysp_node_anydata *any;
1536
David Sedlák8d552d62019-08-06 15:29:05 +02001537 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001538 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001539 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001540 any->parent = node_meta->parent;
1541
David Sedlákbf8a2b72019-08-14 16:48:10 +02001542 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001543 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1544 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 +02001545
Radek Krejcif13b87b2020-12-01 22:02:17 +01001546 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001547 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1548 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1550 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1551 {LY_STMT_MUST, &any->musts, 0},
1552 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1553 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1554 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1555 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1556 };
Michal Vasko69730152020-10-09 16:30:07 +02001557
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001558 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts));
1559
1560 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1561 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, any->exts, 1, NULL));
1562
1563 return LY_SUCCESS;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001564}
1565
1566/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001567 * @brief parse leaf element.
1568 *
1569 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001570 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001571 *
1572 * @return LY_ERR values.
1573 */
1574static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001575yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001576{
David Sedlák203ca3a2019-07-18 15:26:25 +02001577 struct lysp_node_leaf *leaf;
1578
David Sedlák8d552d62019-08-06 15:29:05 +02001579 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001580 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001581 leaf->nodetype = LYS_LEAF;
1582 leaf->parent = node_meta->parent;
1583
David Sedlák203ca3a2019-07-18 15:26:25 +02001584 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001585 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1586 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 +02001587
1588 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001589 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001590 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1591 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1592 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1593 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1594 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_MUST, &leaf->musts, 0},
1596 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1597 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1598 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1599 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1600 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1601 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1602 };
Michal Vasko69730152020-10-09 16:30:07 +02001603
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001604 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts));
1605
1606 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1607 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, leaf->exts, 1, NULL));
1608
1609 return LY_SUCCESS;
David Sedlák203ca3a2019-07-18 15:26:25 +02001610}
1611
1612/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001613 * @brief Parse leaf-list element.
1614 *
1615 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001616 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001617 *
1618 * @return LY_ERR values.
1619 */
1620static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001621yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001622{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001623 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001624
Michal Vaskob36053d2020-03-26 15:49:30 +01001625 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001626
David Sedlákc3da3ef2019-07-19 12:56:08 +02001627 llist->nodetype = LYS_LEAFLIST;
1628 llist->parent = node_meta->parent;
1629
David Sedlákc3da3ef2019-07-19 12:56:08 +02001630 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001631 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1632 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 +02001633
1634 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001635 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001636 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1637 {LY_STMT_DEFAULT, &llist->dflts, 0},
1638 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1639 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1640 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1641 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1642 {LY_STMT_MUST, &llist->musts, 0},
1643 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1644 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1645 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1646 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1647 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1648 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1649 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1650 };
Michal Vasko69730152020-10-09 16:30:07 +02001651
Radek Krejcif13b87b2020-12-01 22:02:17 +01001652 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001653
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001654 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1655 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, llist->exts, 1, NULL));
1656
David Sedlákbf8a2b72019-08-14 16:48:10 +02001657 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001658 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001659 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001660 return LY_EVALID;
1661 }
Michal Vasko69730152020-10-09 16:30:07 +02001662 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001663 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001664 return LY_EVALID;
1665 }
1666
1667 return LY_SUCCESS;
1668}
1669
1670/**
David Sedlák04e17b22019-07-19 15:29:48 +02001671 * @brief Parse typedef element.
1672 *
1673 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001674 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001675 *
1676 * @return LY_ERR values.
1677 */
1678static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001679yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001680{
1681 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001682 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001683
Michal Vaskob36053d2020-03-26 15:49:30 +01001684 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001685
1686 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001687 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1688 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 +02001689
1690 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001691 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001692 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1693 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1694 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1695 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1696 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1697 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1698 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1699 };
Michal Vasko69730152020-10-09 16:30:07 +02001700
Radek Krejcif13b87b2020-12-01 22:02:17 +01001701 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001702
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001703 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1704 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, tpdf->exts, 1, NULL));
1705
David Sedlák04e17b22019-07-19 15:29:48 +02001706 /* store data for collision check */
aPiecek75b83a02021-06-29 10:34:38 +02001707 if (typedef_meta->parent) {
aPiecek8d4e75d2021-06-24 14:47:06 +02001708 assert(ctx->main_ctx);
1709 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001710 }
1711
1712 return LY_SUCCESS;
1713}
1714
1715/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001716 * @brief Parse refine element.
1717 *
1718 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001719 * @param[in,out] refines Refines to add to.
1720 *
1721 * @return LY_ERR values.
1722 */
1723static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001724yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001725{
1726 struct lysp_refine *rf;
1727
1728 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001729 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001730
1731 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001732 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1733 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1734 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001735
1736 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001737 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001738 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001739 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001740 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001741 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001742 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1743 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1744 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1745 {LY_STMT_MUST, &rf->musts, 0},
1746 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1747 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1748 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1749 };
Michal Vasko69730152020-10-09 16:30:07 +02001750
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001751 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts));
1752
1753 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1754 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, rf->exts, 1, NULL));
1755
1756 return LY_SUCCESS;
David Sedlákd2d676a2019-07-22 11:28:19 +02001757}
1758
1759/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001760 * @brief Parse uses element.
1761 *
1762 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001763 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001764 *
1765 * @return LY_ERR values.
1766 */
1767static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001768yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001769{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001770 struct lysp_node_uses *uses;
1771
David Sedlák8d552d62019-08-06 15:29:05 +02001772 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001773 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001774 uses->nodetype = LYS_USES;
1775 uses->parent = node_meta->parent;
1776
David Sedlák0d6de5a2019-07-22 13:25:44 +02001777 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001778 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1779 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 +02001780
1781 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001782 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001783 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001784 {LY_STMT_AUGMENT, &augments, 0},
1785 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1786 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1787 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1788 {LY_STMT_REFINE, &uses->refines, 0},
1789 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1790 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1791 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1792 };
Michal Vasko69730152020-10-09 16:30:07 +02001793
Radek Krejcif13b87b2020-12-01 22:02:17 +01001794 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001795
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001796 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1797 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, uses->exts, 1, NULL));
1798
David Sedlák0d6de5a2019-07-22 13:25:44 +02001799 return LY_SUCCESS;
1800}
1801
1802/**
David Sedlákaa854b02019-07-22 14:17:10 +02001803 * @brief Parse revision element.
1804 *
1805 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001806 * @param[in,out] revs Parsed revisions to add to.
1807 *
1808 * @return LY_ERR values.
1809 */
1810static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001811yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001812{
1813 struct lysp_revision *rev;
1814 const char *temp_date = NULL;
1815
1816 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001817 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001818
1819 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001820 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1821 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 +02001822 /* check value */
1823 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001824 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001825 return LY_EVALID;
1826 }
Radek Krejci36642162021-01-12 16:49:22 +01001827 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001828 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001829
1830 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001831 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001832 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1833 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1834 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1835 };
Michal Vasko69730152020-10-09 16:30:07 +02001836
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001837 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts));
1838
1839 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1840 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, rev->exts, 1, NULL));
1841
1842 return LY_SUCCESS;
David Sedlákaa854b02019-07-22 14:17:10 +02001843}
1844
David Sedlák5e13dea2019-07-22 16:06:45 +02001845/**
1846 * @brief Parse include element.
1847 *
1848 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001849 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1850 *
1851 * @return LY_ERR values.
1852 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001853static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001854yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001855{
1856 struct lysp_include *inc;
1857
1858 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001859 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001860
1861 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001862 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1863 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 +02001864
1865 /* submodules share the namespace with the module names, so there must not be
1866 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001867 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001868 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001869 return LY_EVALID;
1870 }
1871
1872 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001873 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001874 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1875 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1876 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1877 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1878 };
Michal Vasko69730152020-10-09 16:30:07 +02001879
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001880 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts));
1881
1882 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1883 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, inc->exts, 1, NULL));
1884
1885 return LY_SUCCESS;
David Sedlák0c2bab92019-07-22 15:33:19 +02001886}
1887
David Sedlákaa854b02019-07-22 14:17:10 +02001888/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001889 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001890 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001891 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001892 * @param[in,out] rev Array to store the parsed value in.
1893 * @param[in,out] exts Extension instances to add to.
1894 *
1895 * @return LY_ERR values.
1896 */
1897static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001898yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001899{
1900 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001901 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001902 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1903 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001904
Michal Vaskob36053d2020-03-26 15:49:30 +01001905 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1906 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
David Sedlákdfbbb442019-08-06 16:33:21 +02001907 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskoe180ed02021-02-05 16:31:20 +01001908 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001909
1910 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001911 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001912
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001913 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts));
1914
1915 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001916}
1917
1918/**
1919 * @brief Parse config element.
1920 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001921 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001922 * @param[in,out] flags Flags to add to.
1923 * @param[in,out] exts Extension instances to add to.
1924 *
1925 * @return LY_ERR values.
1926 */
1927static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001928yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001929{
1930 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001931 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001932 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1933 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001934
Michal Vaskob36053d2020-03-26 15:49:30 +01001935 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1936 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 +02001937 if (strcmp(temp_val, "true") == 0) {
1938 *flags |= LYS_CONFIG_W;
1939 } else if (strcmp(temp_val, "false") == 0) {
1940 *flags |= LYS_CONFIG_R;
1941 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001942 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001943 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001944 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001945 return LY_EVALID;
1946 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001947 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001948
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001949 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts));
1950
1951 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001952}
1953
1954/**
1955 * @brief Parse yang-version element.
1956 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001957 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001958 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001959 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001960 *
1961 * @return LY_ERR values.
1962 */
1963static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001964yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001965{
1966 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001967 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001968 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1969 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001970
Michal Vaskob36053d2020-03-26 15:49:30 +01001971 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1972 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
Radek Krejci96e48da2020-09-04 13:18:06 +02001973 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001974 *version = LYS_VERSION_1_0;
1975 } else if (strcmp(temp_version, "1.1") == 0) {
1976 *version = LYS_VERSION_1_1;
1977 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001978 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001979 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001980 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001981 return LY_EVALID;
1982 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001983 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001984
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02001985 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts));
1986
1987 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02001988}
1989
1990/**
1991 * @brief Parse import element.
1992 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001993 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001994 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1995 *
1996 * @return LY_ERR values.
1997 */
1998static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001999yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02002000{
2001 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02002002
David Sedlákdfbbb442019-08-06 16:33:21 +02002003 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01002004 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02002005
Radek Krejcif13b87b2020-12-01 22:02:17 +01002006 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002007 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2008 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2009 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2010 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2011 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2012 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002013
2014 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002015 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2016 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002017 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IMPORT, NULL, &imp->exts));
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002018
2019 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2020 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, imp->exts, 1, NULL));
2021
David Sedlákdfbbb442019-08-06 16:33:21 +02002022 /* check prefix validity */
2023 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
2024
2025 return LY_SUCCESS;
2026}
2027
2028/**
2029 * @brief Parse mandatory element.
2030 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002031 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002032 * @param[in,out] flags Flags to add to.
2033 * @param[in,out] exts Extension instances to add to.
2034 *
2035 * @return LY_ERR values.
2036 */
2037static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002038yin_parse_mandatory(struct lys_yin_parser_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 {
David Sedlák26ea1432019-08-14 13:42:23 +02002052 LOGVAL_PARSER((struct lys_parser_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 Vaskoc0c64ae2022-10-06 10:15:23 +02002059 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts));
2060
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.
2070 *
2071 * @return LY_ERR values.
2072 */
2073static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002074yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002075{
2076 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002077 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002078 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2079 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002080
Michal Vaskob36053d2020-03-26 15:49:30 +01002081 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2082 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 +02002083 if (strcmp(value, "current") == 0) {
2084 *flags |= LYS_STATUS_CURR;
2085 } else if (strcmp(value, "deprecated") == 0) {
2086 *flags |= LYS_STATUS_DEPRC;
2087 } else if (strcmp(value, "obsolete") == 0) {
2088 *flags |= LYS_STATUS_OBSLT;
2089 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002090 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002091 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002092 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02002093 return LY_EVALID;
2094 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002095 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02002096
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002097 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts));
2098
2099 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002100}
2101
2102/**
2103 * @brief Parse when element.
2104 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002105 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002106 * @param[out] when_p When pointer to parse to.
2107 */
2108static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002109yin_parse_when(struct lys_yin_parser_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 Vaskoc0c64ae2022-10-06 10:15:23 +02002130 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts));
2131
2132 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2133 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, when->exts, 1, NULL));
2134
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.
David Sedlákdfbbb442019-08-06 16:33:21 +02002142 * @param[in,out] data Data to read from, always moved to currently handled position.
2143 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002144 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002145 *
2146 * @return LY_ERR values.
2147 */
2148static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002149yin_parse_yin_element(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002150{
2151 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002152 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002153 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2154 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002155
Michal Vaskob36053d2020-03-26 15:49:30 +01002156 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2157 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 +02002158 if (strcmp(temp_val, "true") == 0) {
2159 *flags |= LYS_YINELEM_TRUE;
2160 } else if (strcmp(temp_val, "false") == 0) {
2161 *flags |= LYS_YINELEM_FALSE;
2162 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002163 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002164 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002165 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002166 return LY_EVALID;
2167 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002168 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002169
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002170 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts));
2171
2172 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002173}
2174
2175/**
2176 * @brief Parse argument element.
2177 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002178 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002179 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2180 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002181 *
2182 * @return LY_ERR values.
2183 */
2184static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002185yin_parse_argument(struct lys_yin_parser_ctx *ctx, struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02002186{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002187 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002188 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2189 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2190 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002191
Michal Vaskob36053d2020-03-26 15:49:30 +01002192 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2193 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 +02002194
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002195 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts));
2196
2197 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002198}
2199
2200/**
2201 * @brief Parse the extension statement.
2202 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002203 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002204 * @param[in,out] extensions Extensions to add to.
2205 *
2206 * @return LY_ERR values.
2207 */
2208static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002209yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002210{
2211 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002212
Michal Vaskob36053d2020-03-26 15:49:30 +01002213 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2214 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2215 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 +02002216
Radek Krejci9f87b0c2021-03-05 14:45:26 +01002217 struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002218 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002219 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2220 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2221 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2222 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2223 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2224 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002225
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002226 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts));
2227
2228 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2229 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, ex->exts, 1, NULL));
2230
2231 return LY_SUCCESS;
David Sedlákdfbbb442019-08-06 16:33:21 +02002232}
2233
2234/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002235 * @brief Parse feature element.
2236 *
2237 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002238 * @param[in,out] features Features to add to.
2239 *
2240 * @return LY_ERR values.
2241 */
2242static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002243yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002244{
2245 struct lysp_feature *feat;
2246
2247 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002248 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002249
2250 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002251 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2252 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 +02002253
2254 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002255 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002256 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2257 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2258 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2259 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2260 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2261 };
Michal Vasko69730152020-10-09 16:30:07 +02002262
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002263 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts));
2264
2265 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2266 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, feat->exts, 1, NULL));
2267
2268 return LY_SUCCESS;
David Sedlák5e13dea2019-07-22 16:06:45 +02002269}
2270
2271/**
David Sedlák28794f22019-07-22 16:45:00 +02002272 * @brief Parse identity element.
2273 *
2274 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002275 * @param[in,out] identities Identities to add to.
2276 *
2277 * @return LY_ERR values.
2278 */
2279static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002280yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002281{
2282 struct lysp_ident *ident;
2283
2284 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002285 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002286
2287 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002288 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2289 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 +02002290
2291 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002292 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002293 {LY_STMT_BASE, &ident->bases, 0},
2294 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2295 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2296 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2297 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2298 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2299 };
Michal Vasko69730152020-10-09 16:30:07 +02002300
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002301 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts));
2302
2303 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2304 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, ident->exts, 1, NULL));
2305
2306 return LY_SUCCESS;
David Sedlák28794f22019-07-22 16:45:00 +02002307}
2308
2309/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002310 * @brief Parse list element.
2311 *
2312 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002313 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002314 *
2315 * @return LY_ERR values.
2316 */
2317static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002318yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002319{
David Sedlákaf536aa2019-07-23 13:42:23 +02002320 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002321 LY_ERR ret = LY_SUCCESS;
2322 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002323 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002324
Michal Vaskob36053d2020-03-26 15:49:30 +01002325 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002326 list->nodetype = LYS_LIST;
2327 list->parent = node_meta->parent;
2328
David Sedlákaf536aa2019-07-23 13:42:23 +02002329 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002330 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2331 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 +02002332
2333 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002334 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002335 LY_STMT_ACTION, &list->actions, 0,
2336 LY_STMT_ANYDATA, &list->child, 0,
2337 LY_STMT_ANYXML, &list->child, 0,
2338 LY_STMT_CHOICE, &list->child, 0,
2339 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2340 LY_STMT_CONTAINER, &list->child, 0,
2341 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2342 LY_STMT_GROUPING, &list->groupings, 0,
2343 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2344 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2345 LY_STMT_LEAF, &list->child, 0,
2346 LY_STMT_LEAF_LIST, &list->child, 0,
2347 LY_STMT_LIST, &list->child, 0,
2348 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2349 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_MUST, &list->musts, 0,
2351 LY_STMT_NOTIFICATION, &list->notifs, 0,
2352 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2353 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2354 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2355 LY_STMT_TYPEDEF, &list->typedefs, 0,
2356 LY_STMT_UNIQUE, &list->uniques, 0,
2357 LY_STMT_USES, &list->child, 0,
2358 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002360 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2361 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002362 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002363
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002364 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2365 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, list->exts, 1, NULL));
2366
Michal Vasko69730152020-10-09 16:30:07 +02002367 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002368 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002369 return LY_EVALID;
2370 }
2371
2372 return LY_SUCCESS;
2373}
2374
2375/**
David Sedlák031b9e72019-07-23 15:19:37 +02002376 * @brief Parse notification element.
2377 *
2378 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002379 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002380 *
2381 * @return LY_ERR values.
2382 */
2383static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002384yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002385{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002386 struct lysp_node_notif *notif;
2387 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002388 LY_ERR ret = LY_SUCCESS;
2389 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002390 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002391
2392 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002393 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002394 notif->nodetype = LYS_NOTIF;
2395 notif->parent = notif_meta->parent;
2396
2397 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002398 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2399 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 +02002400
2401 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002402 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002403 LY_STMT_ANYDATA, &notif->child, 0,
2404 LY_STMT_ANYXML, &notif->child, 0,
2405 LY_STMT_CHOICE, &notif->child, 0,
2406 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002407 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2408 LY_STMT_GROUPING, &notif->groupings, 0,
2409 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002410 LY_STMT_LEAF, &notif->child, 0,
2411 LY_STMT_LEAF_LIST, &notif->child, 0,
2412 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002413 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2414 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2415 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2416 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002417 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002418 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002419
Radek Krejcif13b87b2020-12-01 22:02:17 +01002420 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2421 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002422 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002423
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002424 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2425 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, notif->exts, 1, NULL));
2426
David Sedlák031b9e72019-07-23 15:19:37 +02002427 return LY_SUCCESS;
2428}
2429
2430/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002431 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002432 *
2433 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002434 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002435 *
2436 * @return LY_ERR values.
2437 */
2438static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002439yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002440{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002441 struct lysp_node_grp *grp;
2442 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002443 LY_ERR ret = LY_SUCCESS;
2444 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002445 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002446
2447 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002448 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002449 grp->nodetype = LYS_GROUPING;
2450 grp->parent = gr_meta->parent;
2451
2452 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002453 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2454 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 +02002455
2456 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002457 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002458 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002459 LY_STMT_ANYDATA, &grp->child, 0,
2460 LY_STMT_ANYXML, &grp->child, 0,
2461 LY_STMT_CHOICE, &grp->child, 0,
2462 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002463 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2464 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002465 LY_STMT_LEAF, &grp->child, 0,
2466 LY_STMT_LEAF_LIST, &grp->child, 0,
2467 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002468 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2469 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2470 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2471 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002472 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002473 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002474 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2475 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002476
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002477 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2478 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, grp->exts, 1, NULL));
2479
aPiecek63e080d2021-06-29 13:53:28 +02002480 /* store data for collision check */
2481 if (!ret && grp->parent) {
2482 assert(ctx->main_ctx);
2483 LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, grp->parent, 0, NULL));
2484 }
2485
Radek Krejci2a9fc652021-01-22 17:44:34 +01002486 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002487}
2488
2489/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002490 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002491 *
2492 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002493 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002494 *
2495 * @return LY_ERR values.
2496 */
2497static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002498yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002499{
David Sedlákf111bcb2019-07-23 17:15:51 +02002500 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002501 LY_ERR ret = LY_SUCCESS;
2502 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002503 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002504
2505 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002506 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002507 cont->nodetype = LYS_CONTAINER;
2508 cont->parent = node_meta->parent;
2509
David Sedlákf111bcb2019-07-23 17:15:51 +02002510 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002511 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2512 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 +02002513
2514 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002515 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002516 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2517 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2518 LY_STMT_ANYXML, &cont->child, 0,
2519 LY_STMT_CHOICE, &cont->child, 0,
2520 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2521 LY_STMT_CONTAINER, &cont->child, 0,
2522 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2523 LY_STMT_GROUPING, &cont->groupings, 0,
2524 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2525 LY_STMT_LEAF, &cont->child, 0,
2526 LY_STMT_LEAF_LIST, &cont->child, 0,
2527 LY_STMT_LIST, &cont->child, 0,
2528 LY_STMT_MUST, &cont->musts, 0,
2529 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2530 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2531 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2532 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2533 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2534 LY_STMT_USES, &cont->child, 0,
2535 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2536 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002537 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2538 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002539 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02002540
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002541 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2542 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, cont->exts, 1, NULL));
2543
2544 return LY_SUCCESS;
David Sedlákf111bcb2019-07-23 17:15:51 +02002545}
2546
2547/**
David Sedlák5379d392019-07-24 10:42:03 +02002548 * @brief Parse case element.
2549 *
2550 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002551 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002552 *
2553 * @return LY_ERR values.
2554 */
2555static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002556yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002557{
David Sedlák5379d392019-07-24 10:42:03 +02002558 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002559 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002560 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002561 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002562
2563 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002564 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002565 cas->nodetype = LYS_CASE;
2566 cas->parent = node_meta->parent;
2567
David Sedlák5379d392019-07-24 10:42:03 +02002568 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002569 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2570 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 +02002571
2572 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002573 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002574 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2575 LY_STMT_ANYXML, &cas->child, 0,
2576 LY_STMT_CHOICE, &cas->child, 0,
2577 LY_STMT_CONTAINER, &cas->child, 0,
2578 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2579 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2580 LY_STMT_LEAF, &cas->child, 0,
2581 LY_STMT_LEAF_LIST, &cas->child, 0,
2582 LY_STMT_LIST, &cas->child, 0,
2583 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2584 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2585 LY_STMT_USES, &cas->child, 0,
2586 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2587 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002588 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2589 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002590 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02002591
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002592 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2593 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, cas->exts, 1, NULL));
2594
2595 return LY_SUCCESS;
David Sedlák5379d392019-07-24 10:42:03 +02002596}
2597
2598/**
David Sedlák05404f62019-07-24 14:11:53 +02002599 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002600 *
2601 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002602 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002603 *
2604 * @return LY_ERR values.
2605 */
2606LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002607yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002608{
David Sedlák81497a32019-08-13 16:56:26 +02002609 LY_ERR ret = LY_SUCCESS;
2610 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002611 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002612 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002613
2614 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002615 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002616
David Sedlákb7abcfa2019-07-24 12:33:35 +02002617 choice->nodetype = LYS_CHOICE;
2618 choice->parent = node_meta->parent;
2619
David Sedlákb7abcfa2019-07-24 12:33:35 +02002620 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002621 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2622 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 +02002623
2624 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002625 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002626 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2627 LY_STMT_ANYXML, &choice->child, 0,
2628 LY_STMT_CASE, &choice->child, 0,
2629 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2630 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2631 LY_STMT_CONTAINER, &choice->child, 0,
2632 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2633 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2634 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2635 LY_STMT_LEAF, &choice->child, 0,
2636 LY_STMT_LEAF_LIST, &choice->child, 0,
2637 LY_STMT_LIST, &choice->child, 0,
2638 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2639 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2640 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2641 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2642 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002643 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2644 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002645 LY_CHECK_RET(ret);
2646
2647 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2648 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, choice->exts, 1, NULL));
2649
David Sedlák81497a32019-08-13 16:56:26 +02002650 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002651}
2652
2653/**
David Sedlák05404f62019-07-24 14:11:53 +02002654 * @brief Parse input or output element.
2655 *
2656 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002657 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002658 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2659 *
2660 * @return LY_ERR values.
2661 */
2662static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002663yin_parse_inout(struct lys_yin_parser_ctx *ctx, enum ly_stmt inout_kw, struct inout_meta *inout_meta)
David Sedlák05404f62019-07-24 14:11:53 +02002664{
David Sedlák81497a32019-08-13 16:56:26 +02002665 LY_ERR ret = LY_SUCCESS;
2666 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002667 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002668
David Sedlák05404f62019-07-24 14:11:53 +02002669 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002670 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 +02002671 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002672 inout_meta->inout_p->parent = inout_meta->parent;
2673
2674 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002675 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2676 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 +02002677
2678 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002679 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002680 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2681 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2682 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2683 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002684 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002685 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2686 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2687 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002688 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2689 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002690 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002691 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002692 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2693 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002694 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002695
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002696 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2697 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, inout_meta->inout_p->exts, 1, NULL));
2698
Radek Krejci01180ac2021-01-27 08:48:22 +01002699 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002700 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2701 return LY_EVALID;
2702 }
2703
David Sedlák05404f62019-07-24 14:11:53 +02002704 return LY_SUCCESS;
2705}
2706
David Sedlák992fb7c2019-07-24 16:51:01 +02002707/**
2708 * @brief Parse action element.
2709 *
2710 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002711 * @param[in] act_meta Meta information about parent node and actions to add to.
2712 *
2713 * @return LY_ERR values.
2714 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002715static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002716yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002717{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002718 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002719 LY_ERR ret = LY_SUCCESS;
2720 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002721 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002722 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002723
2724 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002725 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002726 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002727 act->parent = act_meta->parent;
2728
2729 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002730 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002731 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002732
2733 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002734 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002735 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2736 LY_STMT_GROUPING, &act->groupings, 0,
2737 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2738 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2739 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2740 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2741 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2742 LY_STMT_TYPEDEF, &act->typedefs, 0,
2743 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002744 ret = (yin_parse_content(ctx, subelems, subelems_size, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002745 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002746 LY_CHECK_RET(ret);
2747
Michal Vasko7f45cf22020-10-01 12:49:44 +02002748 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2749 if (!act->input.nodetype) {
2750 act->input.nodetype = LYS_INPUT;
2751 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002752 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002753 }
2754 if (!act->output.nodetype) {
2755 act->output.nodetype = LYS_OUTPUT;
2756 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002757 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002758 }
2759
David Sedlák85d0eca2019-07-24 15:15:21 +02002760 return LY_SUCCESS;
2761}
2762
David Sedlák05404f62019-07-24 14:11:53 +02002763/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002764 * @brief Parse augment element.
2765 *
2766 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002767 * @param[in] aug_meta Meta information about parent node and augments to add to.
2768 *
2769 * @return LY_ERR values.
2770 */
2771static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002772yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002773{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002774 struct lysp_node_augment *aug;
2775 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002776 LY_ERR ret = LY_SUCCESS;
2777 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002778 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002779
2780 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002781 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002782 aug->nodetype = LYS_AUGMENT;
2783 aug->parent = aug_meta->parent;
2784
2785 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002786 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2787 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2788 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002789
2790 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002791 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002792 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2793 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2794 LY_STMT_ANYXML, &aug->child, 0,
2795 LY_STMT_CASE, &aug->child, 0,
2796 LY_STMT_CHOICE, &aug->child, 0,
2797 LY_STMT_CONTAINER, &aug->child, 0,
2798 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002799 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002800 LY_STMT_LEAF, &aug->child, 0,
2801 LY_STMT_LEAF_LIST, &aug->child, 0,
2802 LY_STMT_LIST, &aug->child, 0,
2803 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2804 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2805 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2806 LY_STMT_USES, &aug->child, 0,
2807 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2808 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002809 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2810 subelems_deallocator(subelems_size, subelems);
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002811 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002812
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002813 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2814 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, aug->exts, 1, NULL));
2815
2816 return LY_SUCCESS;
David Sedlák992fb7c2019-07-24 16:51:01 +02002817}
2818
David Sedlák8b754462019-07-25 16:22:13 +02002819/**
2820 * @brief Parse deviate element.
2821 *
2822 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002823 * @param[in] deviates Deviates to add to.
2824 *
2825 * @return LY_ERR values.
2826 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002827static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002828yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002829{
2830 LY_ERR ret = LY_SUCCESS;
2831 uint8_t dev_mod;
2832 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002833 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002834 struct lysp_deviate_add *d_add = NULL;
2835 struct lysp_deviate_rpl *d_rpl = NULL;
2836 struct lysp_deviate_del *d_del = NULL;
2837
2838 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002839 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2840 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 +02002841
2842 if (strcmp(temp_val, "not-supported") == 0) {
2843 dev_mod = LYS_DEV_NOT_SUPPORTED;
2844 } else if (strcmp(temp_val, "add") == 0) {
2845 dev_mod = LYS_DEV_ADD;
2846 } else if (strcmp(temp_val, "replace") == 0) {
2847 dev_mod = LYS_DEV_REPLACE;
2848 } else if (strcmp(temp_val, "delete") == 0) {
2849 dev_mod = LYS_DEV_DELETE;
2850 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002851 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002852 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002853 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002854 return LY_EVALID;
2855 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002856 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002857
2858 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2859 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002860 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002861 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002862 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2863 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002864
Radek Krejcif13b87b2020-12-01 22:02:17 +01002865 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002866
2867 } else if (dev_mod == LYS_DEV_ADD) {
2868 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002869 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002870 d = (struct lysp_deviate *)d_add;
2871 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2872 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002873 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002874 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002875 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002876 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2877 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2878 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2879 {LY_STMT_MUST, &d_add->musts, 0},
2880 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2881 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2882 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2883 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002884
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002885 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002886
2887 } else if (dev_mod == LYS_DEV_REPLACE) {
2888 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002889 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002890 d = (struct lysp_deviate *)d_rpl;
2891 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2892 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002893 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002894 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002895 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002896 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2897 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2898 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2899 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2900 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2901 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2902 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002903
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002904 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002905
2906 } else {
2907 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002908 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002909 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002910 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002911 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002912 {LY_STMT_MUST, &d_del->musts, 0},
2913 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2914 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2915 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2916 };
Michal Vasko26bbb272022-08-02 14:54:33 +02002917
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002918 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002919 }
2920 LY_CHECK_GOTO(ret, cleanup);
2921
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002922 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2923 LY_CHECK_GOTO(ret = ly_set_add(&ctx->ext_inst, d->exts, 1, NULL), cleanup);
2924
David Sedlák4ffcec82019-07-25 15:10:21 +02002925 d->mod = dev_mod;
2926 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002927 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002928
2929 return ret;
2930
2931cleanup:
2932 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002933 return ret;
2934}
2935
David Sedlák992fb7c2019-07-24 16:51:01 +02002936/**
David Sedlák8b754462019-07-25 16:22:13 +02002937 * @brief Parse deviation element.
2938 *
2939 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002940 * @param[in] deviations Deviations to add to.
David Sedlák8b754462019-07-25 16:22:13 +02002941 * @return LY_ERR values.
2942 */
2943static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002944yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002945{
Michal Vasko12ef5362022-09-16 15:13:58 +02002946 LY_ERR ret = LY_SUCCESS;
2947 struct lysp_deviation *dev = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02002948 struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
David Sedlák8b754462019-07-25 16:22:13 +02002949
2950 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002951 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002952
2953 /* parse argument */
Michal Vasko12ef5362022-09-16 15:13:58 +02002954 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2955 LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION), cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01002956 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002957 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002958 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2959 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2960 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2961 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2962 };
Michal Vasko69730152020-10-09 16:30:07 +02002963
Michal Vasko12ef5362022-09-16 15:13:58 +02002964 LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts), cleanup);
2965
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02002966 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2967 LY_CHECK_GOTO(ret = ly_set_add(&ctx->ext_inst, dev->exts, 1, NULL), cleanup);
2968
Michal Vasko12ef5362022-09-16 15:13:58 +02002969cleanup:
2970 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02002971 lysp_deviation_free(&fctx, dev);
Michal Vasko12ef5362022-09-16 15:13:58 +02002972 LY_ARRAY_DECREMENT_FREE(*deviations);
2973 }
2974 return ret;
David Sedlák8b754462019-07-25 16:22:13 +02002975}
2976
2977/**
David Sedlákc5b20842019-08-13 10:18:31 +02002978 * @brief map keyword to keyword-group.
2979 *
2980 * @param[in] ctx YIN parser context used for logging.
2981 * @param[in] kw Keyword that is child of module or submodule.
2982 * @param[out] group Group of keyword.
David Sedlákc5b20842019-08-13 10:18:31 +02002983 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2984 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002985static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002986kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002987{
2988 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002989 /* module header */
2990 case LY_STMT_NONE:
2991 case LY_STMT_NAMESPACE:
2992 case LY_STMT_PREFIX:
2993 case LY_STMT_BELONGS_TO:
2994 case LY_STMT_YANG_VERSION:
2995 *group = Y_MOD_MODULE_HEADER;
2996 break;
2997 /* linkage */
2998 case LY_STMT_INCLUDE:
2999 case LY_STMT_IMPORT:
3000 *group = Y_MOD_LINKAGE;
3001 break;
3002 /* meta */
3003 case LY_STMT_ORGANIZATION:
3004 case LY_STMT_CONTACT:
3005 case LY_STMT_DESCRIPTION:
3006 case LY_STMT_REFERENCE:
3007 *group = Y_MOD_META;
3008 break;
3009 /* revision */
3010 case LY_STMT_REVISION:
3011 *group = Y_MOD_REVISION;
3012 break;
3013 /* body */
3014 case LY_STMT_ANYDATA:
3015 case LY_STMT_ANYXML:
3016 case LY_STMT_AUGMENT:
3017 case LY_STMT_CHOICE:
3018 case LY_STMT_CONTAINER:
3019 case LY_STMT_DEVIATION:
3020 case LY_STMT_EXTENSION:
3021 case LY_STMT_FEATURE:
3022 case LY_STMT_GROUPING:
3023 case LY_STMT_IDENTITY:
3024 case LY_STMT_LEAF:
3025 case LY_STMT_LEAF_LIST:
3026 case LY_STMT_LIST:
3027 case LY_STMT_NOTIFICATION:
3028 case LY_STMT_RPC:
3029 case LY_STMT_TYPEDEF:
3030 case LY_STMT_USES:
3031 case LY_STMT_EXTENSION_INSTANCE:
3032 *group = Y_MOD_BODY;
3033 break;
3034 default:
3035 LOGINT(ctx->xmlctx->ctx);
3036 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02003037 }
3038
3039 return LY_SUCCESS;
3040}
3041
David Sedlákc5b20842019-08-13 10:18:31 +02003042/**
3043 * @brief Check if relative order of two keywords is valid.
3044 *
3045 * @param[in] ctx YIN parser context used for logging.
3046 * @param[in] kw Current keyword.
3047 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02003048 * @param[in] parrent Identification of parrent element, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
David Sedlákc5b20842019-08-13 10:18:31 +02003049 * because relative order is required only in module and submodule sub-elements, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +02003050 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02003051 */
David Sedláke6cd89e2019-08-07 12:46:02 +02003052static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003053yin_check_relative_order(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum ly_stmt next_kw, enum ly_stmt parrent)
David Sedláke6cd89e2019-08-07 12:46:02 +02003054{
Radek Krejcid6b76452019-09-03 17:03:03 +02003055 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02003056 enum yang_module_stmt gr, next_gr;
3057
Michal Vaskoc78293f2021-12-16 15:40:33 +01003058 if (kw == LY_STMT_EXTENSION_INSTANCE) {
3059 /* no order defined */
3060 return LY_SUCCESS;
3061 }
3062
David Sedláke6cd89e2019-08-07 12:46:02 +02003063 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
3064 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
3065
3066 if (gr > next_gr) {
3067 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
3068 return LY_EVALID;
3069 }
3070
3071 return LY_SUCCESS;
3072}
3073
David Sedlákc5dd0942019-09-13 10:23:59 +02003074/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003075 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3076 *
3077 * @param[in,out] ctx Yin parser context for logging and to store current state.
3078 * @param[in] elem_type Type of element that is currently being parsed.
3079 * @param[out] arg Value to write to.
Michal Vaskoafac7822020-10-20 14:22:26 +02003080 * @return LY_ERR values.
3081 */
3082static LY_ERR
3083yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
3084{
3085 enum ly_stmt child;
3086
3087 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3088
3089 switch (elem_type) {
3090 case LY_STMT_ACTION:
3091 case LY_STMT_ANYDATA:
3092 case LY_STMT_ANYXML:
3093 case LY_STMT_ARGUMENT:
3094 case LY_STMT_BASE:
3095 case LY_STMT_BIT:
3096 case LY_STMT_CASE:
3097 case LY_STMT_CHOICE:
3098 case LY_STMT_CONTAINER:
3099 case LY_STMT_ENUM:
3100 case LY_STMT_EXTENSION:
3101 case LY_STMT_FEATURE:
3102 case LY_STMT_GROUPING:
3103 case LY_STMT_IDENTITY:
3104 case LY_STMT_IF_FEATURE:
3105 case LY_STMT_LEAF:
3106 case LY_STMT_LEAF_LIST:
3107 case LY_STMT_LIST:
3108 case LY_STMT_MODULE:
3109 case LY_STMT_NOTIFICATION:
3110 case LY_STMT_RPC:
3111 case LY_STMT_SUBMODULE:
3112 case LY_STMT_TYPE:
3113 case LY_STMT_TYPEDEF:
3114 case LY_STMT_UNITS:
3115 case LY_STMT_USES:
3116 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
3117 break;
3118 case LY_STMT_AUGMENT:
3119 case LY_STMT_DEVIATION:
3120 case LY_STMT_REFINE:
3121 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
3122 break;
3123 case LY_STMT_CONFIG:
3124 case LY_STMT_DEFAULT:
3125 case LY_STMT_DEVIATE:
3126 case LY_STMT_ERROR_APP_TAG:
3127 case LY_STMT_FRACTION_DIGITS:
3128 case LY_STMT_KEY:
3129 case LY_STMT_LENGTH:
3130 case LY_STMT_MANDATORY:
3131 case LY_STMT_MAX_ELEMENTS:
3132 case LY_STMT_MIN_ELEMENTS:
3133 case LY_STMT_MODIFIER:
3134 case LY_STMT_ORDERED_BY:
3135 case LY_STMT_PATH:
3136 case LY_STMT_PATTERN:
3137 case LY_STMT_POSITION:
3138 case LY_STMT_PREFIX:
3139 case LY_STMT_PRESENCE:
3140 case LY_STMT_RANGE:
3141 case LY_STMT_REQUIRE_INSTANCE:
3142 case LY_STMT_STATUS:
3143 case LY_STMT_VALUE:
3144 case LY_STMT_YANG_VERSION:
3145 case LY_STMT_YIN_ELEMENT:
3146 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
3147 break;
3148 case LY_STMT_IMPORT:
3149 case LY_STMT_INCLUDE:
3150 case LY_STMT_BELONGS_TO:
3151 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
3152 break;
3153 case LY_STMT_INPUT:
3154 case LY_STMT_OUTPUT:
3155 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3156 break;
3157 case LY_STMT_MUST:
3158 case LY_STMT_WHEN:
3159 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
3160 break;
3161 case LY_STMT_NAMESPACE:
3162 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
3163 break;
3164 case LY_STMT_REVISION:
3165 case LY_STMT_REVISION_DATE:
3166 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
3167 break;
3168 case LY_STMT_UNIQUE:
3169 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
3170 break;
3171 /* argument is mapped to yin element */
3172 case LY_STMT_CONTACT:
3173 case LY_STMT_DESCRIPTION:
3174 case LY_STMT_ORGANIZATION:
3175 case LY_STMT_REFERENCE:
3176 case LY_STMT_ERROR_MESSAGE:
3177 /* there shouldn't be any attribute, argument is supposed to be first subelement */
3178 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3179
3180 /* no content */
3181 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3182 if (ctx->xmlctx->ws_only) {
3183 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3184 }
3185 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3186 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3187 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
3188 return LY_EVALID;
3189 }
3190
3191 /* parse child element */
3192 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3193 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3194 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
3195 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3196 ly_stmt2str(elem_type));
3197 return LY_EVALID;
3198 }
3199 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3200
3201 /* no attributes expected? TODO */
3202 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3203 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3204 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3205 }
3206
3207 /* load and save content */
3208 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3209 LY_CHECK_RET(!*arg, LY_EMEM);
3210
3211 /* load closing tag of subelement */
3212 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3213
3214 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3215 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3216 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3217 }*/
3218 break;
3219 default:
3220 LOGINT(ctx->xmlctx->ctx);
3221 return LY_EINT;
3222 }
3223
3224 return LY_SUCCESS;
3225}
3226
3227/**
3228 * @brief Parse yin element into generic structure.
3229 *
3230 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3231 * @param[in] parent Identification of parent element.
3232 * @param[out] element Where the element structure should be stored.
Michal Vaskoafac7822020-10-20 14:22:26 +02003233 * @return LY_ERR values.
3234 */
3235LY_ERR
3236yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3237{
3238 LY_ERR ret = LY_SUCCESS;
3239 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003240 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003241
3242 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3243
3244 /* allocate new structure for element */
3245 *element = calloc(1, sizeof(**element));
3246 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003247
3248 /* store identifier */
3249 if (ctx->xmlctx->prefix_len) {
3250 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3251 ctx->xmlctx->name) == -1) {
3252 LOGMEM(ctx->xmlctx->ctx);
3253 ret = LY_EMEM;
3254 goto cleanup;
3255 }
3256 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3257
3258 /* store prefix data for the statement */
Radek Krejci8df109d2021-04-23 12:19:08 +02003259 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 +01003260 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3261 } else {
3262 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3263 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003264
3265 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3266 ctx->xmlctx->prefix_len, parent);
3267
3268 last = (*element)->child;
3269 if ((*element)->kw == LY_STMT_NONE) {
3270 /* unrecognized element */
3271 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3272 ly_stmt2str(parent));
3273 ret = LY_EVALID;
3274 goto cleanup;
3275 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3276 /* element is known yang keyword, which means argument can be parsed correctly. */
3277 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3278 LY_CHECK_GOTO(ret, cleanup);
3279 } else {
3280 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3281
3282 /* load attributes in generic way, save all attributes in linked list */
3283 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3284 new = calloc(1, sizeof(*last));
3285 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3286 if (!(*element)->child) {
3287 /* save first */
3288 (*element)->child = new;
3289 } else {
3290 last->next = new;
3291 }
3292 last = new;
3293
3294 last->flags |= LYS_YIN_ATTR;
3295 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3296 last->kw = LY_STMT_NONE;
3297 /* attributes with prefix are ignored */
3298 if (!ctx->xmlctx->prefix) {
3299 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3300
3301 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3302 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3303 } else {
3304 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3305 }
3306 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3307 }
3308 }
3309
3310 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3311 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3312 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3313 /* parse subelements */
3314 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3315 LY_CHECK_GOTO(ret, cleanup);
3316 if (!(*element)->child) {
3317 /* save first */
3318 (*element)->child = new;
3319 } else {
3320 last->next = new;
3321 }
3322 last = new;
3323
3324 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3325 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3326 }
3327 } else {
3328 /* save element content */
3329 if (ctx->xmlctx->value_len) {
3330 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3331 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003332
3333 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003334 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 +01003335 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003336 }
3337
3338 /* read closing tag */
3339 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3340 }
3341
3342cleanup:
3343 return ret;
3344}
3345
3346/**
3347 * @brief Parse instance of extension.
3348 *
3349 * @param[in,out] ctx Yin parser context for logging and to store current state.
Radek Krejcifc596f92021-02-26 22:40:26 +01003350 * @param[in] subelem The statement this extension instance is a subelement of.
Michal Vaskoafac7822020-10-20 14:22:26 +02003351 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3352 * @param[in,out] exts Extension instance to add to.
Michal Vaskoafac7822020-10-20 14:22:26 +02003353 * @return LY_ERR values.
3354 */
3355LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01003356yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, enum ly_stmt subelem, LY_ARRAY_COUNT_TYPE subelem_index,
Michal Vaskoafac7822020-10-20 14:22:26 +02003357 struct lysp_ext_instance **exts)
3358{
3359 struct lysp_ext_instance *e;
3360 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003361 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003362
3363 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003364 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003365
3366 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3367
Michal Vaskofc2cd072021-02-24 13:17:17 +01003368 if (!ctx->xmlctx->prefix_len) {
3369 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3370 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3371 return LY_EVALID;
3372 }
3373
3374 /* store prefixed name */
3375 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3376 ctx->xmlctx->name) == -1) {
3377 LOGMEM(ctx->xmlctx->ctx);
3378 return LY_EMEM;
3379 }
3380 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3381
3382 /* store prefix data for the name */
Radek Krejci8df109d2021-04-23 12:19:08 +02003383 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 +01003384 &e->format, &e->prefix_data));
3385
Radek Krejciab430862021-03-02 20:13:40 +01003386 e->parent_stmt = subelem;
3387 e->parent_stmt_index = subelem_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003388
Michal Vaskoafac7822020-10-20 14:22:26 +02003389 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3390
3391 /* store attributes as subelements */
3392 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3393 if (!ctx->xmlctx->prefix) {
3394 new_subelem = calloc(1, sizeof(*new_subelem));
3395 if (!e->child) {
3396 e->child = new_subelem;
3397 } else {
3398 last_subelem->next = new_subelem;
3399 }
3400 last_subelem = new_subelem;
3401
3402 last_subelem->flags |= LYS_YIN_ATTR;
3403 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3404 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3405 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3406
Michal Vaskofc2cd072021-02-24 13:17:17 +01003407 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3408 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003409 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3410 } else {
3411 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3412 }
3413
3414 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3415 }
3416
3417 /* parse subelements */
3418 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3419 if (ctx->xmlctx->ws_only) {
3420 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3421 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3422 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3423 if (!e->child) {
3424 e->child = new_subelem;
3425 } else {
3426 last_subelem->next = new_subelem;
3427 }
3428 last_subelem = new_subelem;
3429
3430 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3431 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3432 }
3433 } else if (ctx->xmlctx->value_len) {
3434 /* save text content */
3435 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3436 LY_CHECK_RET(!e->argument, LY_EMEM);
3437
Michal Vaskofc2cd072021-02-24 13:17:17 +01003438 /* store prefix data for the argument as well */
Radek Krejci8df109d2021-04-23 12:19:08 +02003439 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->argument, strlen(e->argument), LY_VALUE_XML,
Radek Krejci07a55962021-03-02 20:16:43 +01003440 &ctx->xmlctx->ns, &e->format, &e->prefix_data));
Michal Vaskofc2cd072021-02-24 13:17:17 +01003441
Michal Vaskoafac7822020-10-20 14:22:26 +02003442 /* parser next */
3443 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3444 }
3445
aPiecek60d9d672021-04-27 15:49:57 +02003446 e->parsed = NULL;
3447
Michal Vaskoafac7822020-10-20 14:22:26 +02003448 return LY_SUCCESS;
3449}
3450
3451/**
3452 * @brief Generic function for content parsing
3453 *
3454 * @param[in,out] ctx Yin parser context for logging and to store current state.
3455 * @param[in] subelem_info array of valid subelement types and meta information
3456 * @param[in] subelem_info_size Size of subelem_info array.
3457 * @param[in] current_element Type of current element.
3458 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3459 * @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 +02003460 * @return LY_ERR values.
3461 */
David Sedlákd6e56892019-07-01 15:40:24 +02003462LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003463yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
Radek Krejci0f969882020-08-21 16:56:47 +02003464 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003465{
3466 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003467 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003468 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003469 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003470
Michal Vaskob36053d2020-03-26 15:49:30 +01003471 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003472
Michal Vaskob36053d2020-03-26 15:49:30 +01003473 if (ctx->xmlctx->ws_only) {
3474 /* check whether there are any children */
3475 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3476 } else {
3477 /* we want to parse the value */
3478 next_status = LYXML_ELEM_CLOSE;
3479 }
3480
3481 if (next_status == LYXML_ELEMENT) {
3482 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3483
3484 /* current element has subelements as content */
3485 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3486 /* match keyword */
3487 last_kw = kw;
3488 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003489 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003490
3491 /* check if this element can be child of current element */
3492 subelem = get_record(kw, subelem_info_size, subelem_info);
3493 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003494 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003495 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3496 } else {
3497 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003498 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003499 }
3500 ret = LY_EVALID;
3501 goto cleanup;
3502 }
3503
3504 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003505 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003506 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3507 LY_CHECK_GOTO(ret, cleanup);
3508 }
3509
3510 /* flag check */
3511 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3512 /* subelement uniquenes */
3513 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3514 return LY_EVALID;
3515 }
3516 if (subelem->flags & YIN_SUBELEM_FIRST) {
3517 /* subelement is supposed to be defined as first subelement */
3518 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3519 LY_CHECK_GOTO(ret, cleanup);
3520 }
3521 if (subelem->flags & YIN_SUBELEM_VER2) {
3522 /* subelement is supported only in version 1.1 or higher */
Michal Vasko8a67eff2021-12-07 14:04:47 +01003523 if (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003524 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003525 ret = LY_EVALID;
3526 goto cleanup;
3527 }
David Sedlákd6e56892019-07-01 15:40:24 +02003528 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003529 /* note that element was parsed for easy uniqueness check in next iterations */
3530 subelem->flags |= YIN_SUBELEM_PARSED;
3531
3532 switch (kw) {
3533 /* call responsible function */
3534 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003535 ret = yin_parse_extension_instance(ctx, current_element,
Michal Vasko69730152020-10-09 16:30:07 +02003536 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003537 break;
3538 case LY_STMT_ACTION:
3539 case LY_STMT_RPC:
3540 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3541 break;
3542 case LY_STMT_ANYDATA:
3543 case LY_STMT_ANYXML:
3544 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3545 break;
3546 case LY_STMT_ARGUMENT:
3547 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3548 break;
3549 case LY_STMT_AUGMENT:
3550 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3551 break;
3552 case LY_STMT_BASE:
3553 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3554 break;
3555 case LY_STMT_BELONGS_TO:
3556 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3557 break;
3558 case LY_STMT_BIT:
3559 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3560 break;
3561 case LY_STMT_CASE:
3562 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3563 break;
3564 case LY_STMT_CHOICE:
3565 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3566 break;
3567 case LY_STMT_CONFIG:
3568 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3569 break;
3570 case LY_STMT_CONTACT:
3571 case LY_STMT_DESCRIPTION:
3572 case LY_STMT_ORGANIZATION:
3573 case LY_STMT_REFERENCE:
3574 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3575 break;
3576 case LY_STMT_CONTAINER:
3577 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3578 break;
3579 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003580 ret = yin_parse_qname(ctx, kw, subelem, exts);
3581 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003582 case LY_STMT_ERROR_APP_TAG:
3583 case LY_STMT_KEY:
3584 case LY_STMT_PRESENCE:
3585 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3586 break;
3587 case LY_STMT_DEVIATE:
3588 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3589 break;
3590 case LY_STMT_DEVIATION:
3591 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3592 break;
3593 case LY_STMT_ENUM:
3594 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3595 break;
3596 case LY_STMT_ERROR_MESSAGE:
3597 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3598 break;
3599 case LY_STMT_EXTENSION:
3600 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3601 break;
3602 case LY_STMT_FEATURE:
3603 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3604 break;
3605 case LY_STMT_FRACTION_DIGITS:
3606 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3607 break;
3608 case LY_STMT_GROUPING:
3609 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3610 break;
3611 case LY_STMT_IDENTITY:
3612 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3613 break;
Radek Išabe8a6532021-03-29 08:54:22 +02003614 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003615 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003616 ret = yin_parse_qname(ctx, kw, subelem, exts);
3617 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003618 case LY_STMT_UNITS:
3619 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3620 break;
3621 case LY_STMT_IMPORT:
3622 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3623 break;
3624 case LY_STMT_INCLUDE:
Michal Vasko8a67eff2021-12-07 14:04:47 +01003625 if ((current_element == LY_STMT_SUBMODULE) && (PARSER_CUR_PMOD(ctx)->version == LYS_VERSION_1_1)) {
Radek Krejcieeee95c2021-01-19 10:57:22 +01003626 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
Michal Vasko8a67eff2021-12-07 14:04:47 +01003627 ((struct lysp_submodule *)PARSER_CUR_PMOD(ctx))->name);
Radek Krejcieeee95c2021-01-19 10:57:22 +01003628 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003629 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3630 break;
3631 case LY_STMT_INPUT:
3632 case LY_STMT_OUTPUT:
3633 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3634 break;
3635 case LY_STMT_LEAF:
3636 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3637 break;
3638 case LY_STMT_LEAF_LIST:
3639 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3640 break;
3641 case LY_STMT_LENGTH:
3642 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3643 break;
3644 case LY_STMT_LIST:
3645 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3646 break;
3647 case LY_STMT_MANDATORY:
3648 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3649 break;
3650 case LY_STMT_MAX_ELEMENTS:
3651 case LY_STMT_MIN_ELEMENTS:
3652 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3653 break;
3654 case LY_STMT_MODIFIER:
3655 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3656 break;
3657 case LY_STMT_MUST:
3658 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3659 break;
3660 case LY_STMT_NAMESPACE:
3661 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3662 break;
3663 case LY_STMT_NOTIFICATION:
3664 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3665 break;
3666 case LY_STMT_ORDERED_BY:
3667 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3668 break;
3669 case LY_STMT_PATH:
3670 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3671 break;
3672 case LY_STMT_PATTERN:
3673 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3674 break;
3675 case LY_STMT_VALUE:
3676 case LY_STMT_POSITION:
3677 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3678 break;
3679 case LY_STMT_PREFIX:
3680 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3681 break;
3682 case LY_STMT_RANGE:
3683 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3684 break;
3685 case LY_STMT_REFINE:
3686 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3687 break;
3688 case LY_STMT_REQUIRE_INSTANCE:
3689 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3690 break;
3691 case LY_STMT_REVISION:
3692 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3693 break;
3694 case LY_STMT_REVISION_DATE:
3695 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3696 break;
3697 case LY_STMT_STATUS:
3698 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3699 break;
3700 case LY_STMT_TYPE:
3701 ret = yin_parse_type(ctx, current_element, subelem);
3702 break;
3703 case LY_STMT_TYPEDEF:
3704 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3705 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003706 case LY_STMT_USES:
3707 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3708 break;
3709 case LY_STMT_WHEN:
3710 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3711 break;
3712 case LY_STMT_YANG_VERSION:
3713 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3714 break;
3715 case LY_STMT_YIN_ELEMENT:
3716 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3717 break;
3718 case LY_STMT_ARG_TEXT:
3719 case LY_STMT_ARG_VALUE:
3720 /* TODO what to do with content/attributes? */
3721 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3722 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3723 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3724 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3725 }
3726 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3727 break;
3728 default:
3729 LOGINT(ctx->xmlctx->ctx);
3730 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003731 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003732 LY_CHECK_GOTO(ret, cleanup);
3733 subelem = NULL;
3734
3735 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003736 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003737 } else {
3738 LY_CHECK_RET(ret);
3739 /* elements with text or none content */
3740 /* save text content, if text_content isn't set, it's just ignored */
3741 /* no resources are allocated in this branch, no need to use cleanup label */
3742 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3743 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003744 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 +01003745 LY_CHECK_RET(!*text_content, LY_EMEM);
3746 }
3747
3748 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003749 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003750
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003751 /* mandatory subelements are checked only after whole element was succesfully parsed */
David Sedlák8b754462019-07-25 16:22:13 +02003752 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003753
3754cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003755 return ret;
3756}
3757
David Sedlákaa98bba2019-09-12 11:52:14 +02003758/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003759 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003760 *
3761 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003762 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003763 * @return LY_ERR values.
3764 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003765LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003766yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003767{
David Sedlák81497a32019-08-13 16:56:26 +02003768 LY_ERR ret = LY_SUCCESS;
3769 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003770 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003771 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003772
Michal Vaskoc3781c32020-10-06 14:04:08 +02003773 mod->is_submod = 0;
3774
Michal Vaskob36053d2020-03-26 15:49:30 +01003775 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3776 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 +01003777 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003778 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3779 LY_STMT_ANYXML, &mod->data, 0,
3780 LY_STMT_AUGMENT, &mod->augments, 0,
3781 LY_STMT_CHOICE, &mod->data, 0,
3782 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3783 LY_STMT_CONTAINER, &mod->data, 0,
3784 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3785 LY_STMT_DEVIATION, &mod->deviations, 0,
3786 LY_STMT_EXTENSION, &mod->extensions, 0,
3787 LY_STMT_FEATURE, &mod->features, 0,
3788 LY_STMT_GROUPING, &mod->groupings, 0,
3789 LY_STMT_IDENTITY, &mod->identities, 0,
3790 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3791 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3792 LY_STMT_LEAF, &mod->data, 0,
3793 LY_STMT_LEAF_LIST, &mod->data, 0,
3794 LY_STMT_LIST, &mod->data, 0,
3795 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3796 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3797 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3798 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3799 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3800 LY_STMT_REVISION, &mod->revs, 0,
3801 LY_STMT_RPC, &mod->rpcs, 0,
3802 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3803 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003804 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003805 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003806
Radek Krejcif13b87b2020-12-01 22:02:17 +01003807 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3808 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003809 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003810
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003811 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
3812 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, mod->exts, 1, NULL));
3813
David Sedláked809f12019-09-13 10:15:11 +02003814 /* submodules share the namespace with the module names, so there must not be
3815 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003816 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003817 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003818 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003819 return LY_EVALID;
3820 }
3821
3822 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003823}
3824
Michal Vaskoafac7822020-10-20 14:22:26 +02003825/**
3826 * @brief Parse submodule element.
3827 *
3828 * @param[in,out] ctx Yin parser context for logging and to store current state.
3829 * @param[in] mod_attrs Attributes of submodule element.
3830 * @param[out] submod Parsed submodule structure.
Michal Vaskoafac7822020-10-20 14:22:26 +02003831 * @return LY_ERR values.
3832 */
David Sedlák3b4db242018-10-19 16:11:01 +02003833LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003834yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003835{
David Sedlák81497a32019-08-13 16:56:26 +02003836 LY_ERR ret = LY_SUCCESS;
3837 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003838 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003839 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003840
Michal Vaskoc3781c32020-10-06 14:04:08 +02003841 submod->is_submod = 1;
3842
Michal Vaskob36053d2020-03-26 15:49:30 +01003843 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3844 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 +01003845 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003846 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3847 LY_STMT_ANYXML, &submod->data, 0,
3848 LY_STMT_AUGMENT, &submod->augments, 0,
3849 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3850 LY_STMT_CHOICE, &submod->data, 0,
3851 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3852 LY_STMT_CONTAINER, &submod->data, 0,
3853 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3854 LY_STMT_DEVIATION, &submod->deviations, 0,
3855 LY_STMT_EXTENSION, &submod->extensions, 0,
3856 LY_STMT_FEATURE, &submod->features, 0,
3857 LY_STMT_GROUPING, &submod->groupings, 0,
3858 LY_STMT_IDENTITY, &submod->identities, 0,
3859 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3860 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3861 LY_STMT_LEAF, &submod->data, 0,
3862 LY_STMT_LEAF_LIST, &submod->data, 0,
3863 LY_STMT_LIST, &submod->data, 0,
3864 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3865 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3866 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3867 LY_STMT_REVISION, &submod->revs, 0,
3868 LY_STMT_RPC, &submod->rpcs, 0,
3869 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3870 LY_STMT_USES, &submod->data, 0,
3871 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3872 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003873
Radek Krejcif13b87b2020-12-01 22:02:17 +01003874 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3875 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003876 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003877
Michal Vaskoc0c64ae2022-10-06 10:15:23 +02003878 /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
3879 LY_CHECK_RET(ly_set_add(&ctx->ext_inst, submod->exts, 1, NULL));
3880
David Sedláked809f12019-09-13 10:15:11 +02003881 /* submodules share the namespace with the module names, so there must not be
3882 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003883 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003884 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003885 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003886 return LY_EVALID;
3887 }
3888
3889 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003890}
3891
3892LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003893yin_parse_submodule(struct lys_yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx,
Radek Krejci0f969882020-08-21 16:56:47 +02003894 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003895{
Radek Krejcid6b76452019-09-03 17:03:03 +02003896 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003897 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003898 struct lysp_submodule *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02003899 struct lysf_ctx fctx = {.ctx = ctx};
David Sedlák8985a142019-07-31 16:43:06 +02003900
aPiecek56be92a2021-07-01 07:18:10 +02003901 assert(yin_ctx && ctx && main_ctx && in && submod);
3902
David Sedlák8985a142019-07-31 16:43:06 +02003903 /* create context */
3904 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003905 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003906 (*yin_ctx)->format = LYS_IN_YIN;
aPiecek56be92a2021-07-01 07:18:10 +02003907 (*yin_ctx)->main_ctx = main_ctx;
Michal Vasko63f3d842020-07-08 10:10:14 +02003908 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003909
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003910 mod_p = calloc(1, sizeof *mod_p);
3911 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
Michal Vasko8a67eff2021-12-07 14:04:47 +01003912 mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003913 mod_p->parsing = 1;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003914
3915 /* use main context parsed mods adding the current one */
3916 (*yin_ctx)->parsed_mods = main_ctx->parsed_mods;
3917 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003918
David Sedlák8985a142019-07-31 16:43:06 +02003919 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003920 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 +02003921 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003922 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003923 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3924 ret = LY_EINVAL;
3925 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003926 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003927 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003928 ret = LY_EVALID;
3929 goto cleanup;
3930 }
3931
Michal Vaskob36053d2020-03-26 15:49:30 +01003932 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003933 LY_CHECK_GOTO(ret, cleanup);
3934
David Sedlákbf8a2b72019-08-14 16:48:10 +02003935 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003936 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003937 if (in->current[0] == '\n') {
3938 LY_IN_NEW_LINE(in);
3939 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003940 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003941 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003942 if (in->current[0]) {
3943 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003944 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003945 ret = LY_EVALID;
3946 goto cleanup;
3947 }
3948
David Sedlák8985a142019-07-31 16:43:06 +02003949 mod_p->parsing = 0;
3950 *submod = mod_p;
3951
3952cleanup:
3953 if (ret) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02003954 lysp_module_free(&fctx, (struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003955 yin_parser_ctx_free(*yin_ctx);
3956 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003957 }
David Sedlák8985a142019-07-31 16:43:06 +02003958 return ret;
3959}
3960
3961LY_ERR
aPiecekc3e26142021-06-22 14:25:49 +02003962yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003963{
David Sedláke4889912018-11-02 09:52:40 +01003964 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003965 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003966 struct lysp_module *mod_p = NULL;
Michal Vaskoc636ea42022-09-16 10:20:31 +02003967 struct lysf_ctx fctx = {.ctx = mod->ctx};
David Sedlák3b4db242018-10-19 16:11:01 +02003968
David Sedlák8985a142019-07-31 16:43:06 +02003969 /* create context */
3970 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003971 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003972 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003973 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 +02003974 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
aPiecek8d4e75d2021-06-24 14:47:06 +02003975 (*yin_ctx)->main_ctx = (struct lys_parser_ctx *)(*yin_ctx);
David Sedlákda8ffa32019-07-08 14:17:10 +02003976
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003977 mod_p = calloc(1, sizeof *mod_p);
3978 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3979 mod_p->mod = mod;
Michal Vasko8a67eff2021-12-07 14:04:47 +01003980 ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003981
David Sedlák8985a142019-07-31 16:43:06 +02003982 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003983 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 +02003984 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003985 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003986 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 +01003987 ret = LY_EINVAL;
3988 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003989 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003990 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003991 ret = LY_EVALID;
3992 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003993 }
3994
David Sedlák00250342019-06-21 14:19:39 +02003995 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003996 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003997 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003998
David Sedlákbf8a2b72019-08-14 16:48:10 +02003999 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02004000 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01004001 if (in->current[0] == '\n') {
4002 LY_IN_NEW_LINE(in);
4003 }
Michal Vasko63f3d842020-07-08 10:10:14 +02004004 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02004005 }
Michal Vasko63f3d842020-07-08 10:10:14 +02004006 if (in->current[0]) {
4007 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02004008 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02004009 ret = LY_EVALID;
4010 goto cleanup;
4011 }
4012
David Sedlák3017da42019-02-15 09:48:04 +01004013 mod->parsed = mod_p;
4014
4015cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02004016 if (ret != LY_SUCCESS) {
Michal Vaskoc636ea42022-09-16 10:20:31 +02004017 lysp_module_free(&fctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02004018 yin_parser_ctx_free(*yin_ctx);
4019 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01004020 }
David Sedlák2e411422018-12-17 02:35:39 +01004021 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02004022}