blob: a467cf7308f6103e849dea3db6797cfa025be365 [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
Michal Vaskofc2cd072021-02-24 13:17:17 +010014#define _GNU_SOURCE
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020017#include <ctype.h>
18#include <errno.h>
19#include <stdarg.h>
20#include <stdbool.h>
Radek Krejci47fab892020-11-05 17:02:41 +010021#include <stdint.h>
David Sedlák3b4db242018-10-19 16:11:01 +020022#include <stdio.h>
23#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020024#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020025
Radek Krejci535ea9f2020-05-29 16:01:05 +020026#include "common.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010027#include "compat.h"
David Sedlákf824ad52018-10-14 23:58:15 +020028#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020029#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010030#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020031#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010032#include "log.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020033#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020034#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020035#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020036#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020037#include "tree.h"
Michal Vaskofc2cd072021-02-24 13:17:17 +010038#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010039#include "tree_edit.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020040#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020041#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020042#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020043
David Sedlák2b214ac2019-06-06 16:11:03 +020044/**
45 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020046 *
David Sedlák2b214ac2019-06-06 16:11:03 +020047 * @param ns Namespace URI to check.
48 *
49 * @return true if ns equals YIN_NS_URI false otherwise.
50 */
51#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
52
Michal Vaskoafac7822020-10-20 14:22:26 +020053enum yin_argument {
54 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
55 YIN_ARG_NAME, /**< argument name */
56 YIN_ARG_TARGET_NODE, /**< argument target-node */
57 YIN_ARG_MODULE, /**< argument module */
58 YIN_ARG_VALUE, /**< argument value */
59 YIN_ARG_TEXT, /**< argument text */
60 YIN_ARG_CONDITION, /**< argument condition */
61 YIN_ARG_URI, /**< argument uri */
62 YIN_ARG_DATE, /**< argument data */
63 YIN_ARG_TAG, /**< argument tag */
64 YIN_ARG_NONE /**< empty (special value) */
65};
66
Michal Vasko22df3f02020-08-24 13:29:22 +020067const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020068 [YIN_ARG_NAME] = "name",
69 [YIN_ARG_TARGET_NODE] = "target-node",
70 [YIN_ARG_MODULE] = "module",
71 [YIN_ARG_VALUE] = "value",
72 [YIN_ARG_TEXT] = "text",
73 [YIN_ARG_CONDITION] = "condition",
74 [YIN_ARG_URI] = "uri",
75 [YIN_ARG_DATE] = "date",
76 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020077 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020078};
79
Michal Vaskoafac7822020-10-20 14:22:26 +020080#define yin_attr2str(STMT) yin_attr_list[STMT]
81
82#define VALID_VALS1 " Only valid value is \"%s\"."
83#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
84#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
85#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
86
87/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
88#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
89 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
90 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
91 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
92
93/* flags to set constraints of subelements */
94#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
95#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
96#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
97#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
98
99#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
100 time to simply check validity of given constraints */
101
102struct yin_subelement {
103 enum ly_stmt type; /**< type of keyword */
104 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
105 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 */
106};
107
108/* Meta information passed to yin_parse_argument function,
109 holds information about where content of argument element will be stored. */
110struct yin_argument_meta {
111 uint16_t *flags; /**< Argument flags */
112 const char **argument; /**< Argument value */
113};
114
115/**
116 * @brief Meta information passed to functions working with tree_schema,
117 * that require additional information about parent node.
118 */
119struct tree_node_meta {
120 struct lysp_node *parent; /**< parent node */
121 struct lysp_node **nodes; /**< linked list of siblings */
122};
123
124/**
125 * @brief Meta information passed to yin_parse_import function.
126 */
127struct import_meta {
128 const char *prefix; /**< module prefix. */
129 struct lysp_import **imports; /**< imports to add to. */
130};
131
132/**
133 * @brief Meta information passed to yin_parse_include function.
134 */
135struct include_meta {
136 const char *name; /**< Module/submodule name. */
137 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
138};
139
140/**
141 * @brief Meta information passed to yin_parse_inout function.
142 */
143struct inout_meta {
144 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100145 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200146};
147
148/**
149 * @brief Meta information passed to yin_parse_minmax function.
150 */
151struct minmax_dev_meta {
152 uint32_t *lim; /**< min/max value to write to. */
153 uint16_t *flags; /**< min/max flags to write to. */
154 struct lysp_ext_instance **exts; /**< extension instances to add to. */
155};
156
157LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
158 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
159
160/**
161 * @brief Match yang keyword from yin data.
162 *
163 * @param[in,out] ctx Yin parser context for logging and to store current state.
164 * @param[in] name Start of keyword name
165 * @param[in] name_len Lenght of keyword name.
166 * @param[in] prefix Start of keyword prefix.
167 * @param[in] prefix_len Lenght of prefix.
168 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
169 *
170 * @return yang_keyword values.
171 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200172enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100173yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200174 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200175{
David Sedlák8f7a1172019-06-20 14:42:18 +0200176 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200177 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200178 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200179 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200180
Michal Vasko69730152020-10-09 16:30:07 +0200181 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200182 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200183 }
184
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200185 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200186 if (ns) {
187 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200188 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200189 }
190 } else {
191 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200192 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200193 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200194
Michal Vasko63f3d842020-07-08 10:10:14 +0200195 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
196 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100197 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200198 name = in->current;
199 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200200
201 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200202 /* 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 +0200203 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200204 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200205 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200206 return kw;
207 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200208 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200209 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200210 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200211 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200212 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200213 }
214}
215
Michal Vaskoafac7822020-10-20 14:22:26 +0200216/**
217 * @brief Match argument name.
218 *
219 * @param[in] name String representing name.
220 * @param[in] len Lenght of the name.
221 *
222 * @return yin_argument values.
223 */
David Sedlákc5b20842019-08-13 10:18:31 +0200224enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200225yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200226{
David Sedlákc5b20842019-08-13 10:18:31 +0200227 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200228 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200229
David Sedlák7ff55a92019-06-17 11:11:41 +0200230 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200231
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200232#define READ_INC(LEN) already_read += LEN
233#define ARG_SET(STMT) arg=STMT
234#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100235
David Sedlák1c8b2702019-02-22 11:03:02 +0100236 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100237 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200238 READ_INC(1);
239 if (ARG_CHECK("ondition", 8)) {
240 ARG_SET(YIN_ARG_CONDITION);
241 }
David Sedlák3b4db242018-10-19 16:11:01 +0200242 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200243
David Sedlák94de2aa2019-02-15 12:42:11 +0100244 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200245 READ_INC(1);
246 if (ARG_CHECK("ate", 3)) {
247 ARG_SET(YIN_ARG_DATE);
248 }
David Sedlák3b4db242018-10-19 16:11:01 +0200249 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200250
David Sedlák94de2aa2019-02-15 12:42:11 +0100251 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200252 READ_INC(1);
253 if (ARG_CHECK("odule", 5)) {
254 ARG_SET(YIN_ARG_MODULE);
255 }
David Sedlák872c7b42018-10-26 13:15:20 +0200256 break;
257
David Sedlák94de2aa2019-02-15 12:42:11 +0100258 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200259 READ_INC(1);
260 if (ARG_CHECK("ame", 3)) {
261 ARG_SET(YIN_ARG_NAME);
262 }
David Sedlák872c7b42018-10-26 13:15:20 +0200263 break;
264
David Sedlák94de2aa2019-02-15 12:42:11 +0100265 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200266 READ_INC(1);
267 if (ARG_CHECK("a", 1)) {
268 if (ARG_CHECK("g", 1)) {
269 ARG_SET(YIN_ARG_TAG);
270 } else if (ARG_CHECK("rget-node", 9)) {
271 ARG_SET(YIN_ARG_TARGET_NODE);
272 }
273 } else if (ARG_CHECK("ext", 3)) {
274 ARG_SET(YIN_ARG_TEXT);
275 }
David Sedlák3b4db242018-10-19 16:11:01 +0200276 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200277
David Sedlák94de2aa2019-02-15 12:42:11 +0100278 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200279 READ_INC(1);
280 if (ARG_CHECK("ri", 2)) {
281 ARG_SET(YIN_ARG_URI);
282 }
David Sedlák3b4db242018-10-19 16:11:01 +0200283 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200284
David Sedlák94de2aa2019-02-15 12:42:11 +0100285 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200286 READ_INC(1);
287 if (ARG_CHECK("alue", 4)) {
288 ARG_SET(YIN_ARG_VALUE);
289 }
David Sedlák3b4db242018-10-19 16:11:01 +0200290 break;
291 }
292
David Sedlákc10e7902018-12-17 02:17:59 +0100293 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200294 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200295 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200296 }
297
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200298#undef ARG_CHECK
299#undef ARG_SET
300#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100301
David Sedlák872c7b42018-10-26 13:15:20 +0200302 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200303}
304
Radek Krejcid6b76452019-09-03 17:03:03 +0200305#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
306 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
307 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
308 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200309
Radek Krejcid6b76452019-09-03 17:03:03 +0200310#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 +0200311
David Sedlák26ea1432019-08-14 13:42:23 +0200312/**
313 * @brief Free subelems information allocated on heap.
314 *
315 * @param[in] count Size of subelems array.
316 * @param[in] subelems Subelems array to free.
317 */
David Sedlák81497a32019-08-13 16:56:26 +0200318static void
319subelems_deallocator(size_t count, struct yin_subelement *subelems)
320{
Michal Vaskod989ba02020-08-24 10:59:24 +0200321 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200322 if (HAS_META(subelems[i].type)) {
323 free(subelems[i].dest);
324 }
325 }
326
327 free(subelems);
328}
329
David Sedlák26ea1432019-08-14 13:42:23 +0200330/**
331 * @brief Allocate subelems information on heap.
332 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200333 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200334 * @param[in] count Number of subelements.
335 * @param[in] parent Parent node if any.
336 * @param[out] result Allocated subelems array.
337 *
338 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
339 */
David Sedlák81497a32019-08-13 16:56:26 +0200340static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100341subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200342 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200343{
344 va_list ap;
345
346 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200347 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200348
349 va_start(ap, result);
350 for (size_t i = 0; i < count; ++i) {
351 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200352 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200353 /* DEST */
354 if (IS_NODE_ELEM((*result)[i].type)) {
355 struct tree_node_meta *node_meta = NULL;
356 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200357 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200358 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200359 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200360 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200361 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200362 struct import_meta *imp_meta = NULL;
363 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200364 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200365 imp_meta->prefix = va_arg(ap, const char *);
366 imp_meta->imports = va_arg(ap, struct lysp_import **);
367 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200368 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200369 struct include_meta *inc_meta = NULL;
370 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200371 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200372 inc_meta->name = va_arg(ap, const char *);
373 inc_meta->includes = va_arg(ap, struct lysp_include **);
374 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200375 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200376 struct inout_meta *inout_meta = NULL;
377 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200378 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200379 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100380 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200381 (*result)[i].dest = inout_meta;
382 } else {
383 (*result)[i].dest = va_arg(ap, void *);
384 }
385 /* FLAGS */
386 (*result)[i].flags = va_arg(ap, int);
387 }
388 va_end(ap);
389
390 return LY_SUCCESS;
391
David Sedlákbf8a2b72019-08-14 16:48:10 +0200392mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200393 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100394 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200395 return LY_EMEM;
396}
397
Michal Vaskoafac7822020-10-20 14:22:26 +0200398/**
399 * @brief Check that val is valid UTF8 character sequence of val_type.
400 * Doesn't check empty string, only character validity.
401 *
402 * @param[in] ctx Yin parser context for logging.
403 * @param[in] val_type Type of the input string to select method of checking character validity.
404 *
405 * @return LY_ERR values.
406 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200407LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100408yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200409{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200410 uint8_t prefix = 0;
411 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100412 size_t utf8_char_len, already_read = 0;
413 const char *val;
414
415 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
416
417 val = ctx->xmlctx->value;
418 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200419 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200420 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200421 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100422 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200423
424 switch (val_type) {
425 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200426 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, NULL));
David Sedlák4a650532019-07-10 11:55:18 +0200427 break;
428 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200429 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, already_read ? 0 : 1, &prefix));
David Sedlák4a650532019-07-10 11:55:18 +0200430 break;
431 case Y_STR_ARG:
432 case Y_MAYBE_STR_ARG:
433 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
434 break;
435 }
436 }
437
438 return LY_SUCCESS;
439}
440
David Sedlákb4e44562019-07-04 15:42:12 +0200441/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100442 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200443 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200444 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200445 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
446 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200447 * @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 +0200448 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200449 * @param[in] current_element Identification of current element, used for logging.
450 *
451 * @return LY_ERR values.
452 */
453static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100454yin_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 +0200455 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200456{
David Sedlákc5b20842019-08-13 10:18:31 +0200457 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200458 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200459
David Sedlák1bccdfa2019-06-17 15:55:27 +0200460 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100461 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200462 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100463 if (!ctx->xmlctx->prefix) {
464 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200465 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100466 /* skip it */
467 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200468 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200469 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200470 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200471 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100472
473 /* go to value */
474 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
475 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200476 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 +0200477 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200478 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100479 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200480 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200481 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200482 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100483 } else {
484 /* skip it */
485 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200486 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100487
488 /* next attribute */
489 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200490 }
491
David Sedlák292763b2019-07-09 11:10:53 +0200492 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200493 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100494 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200495 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200496 return LY_EVALID;
497 }
498
499 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200500}
501
David Sedlákd6e56892019-07-01 15:40:24 +0200502/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200503 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200504 *
505 * @param[in] type Type of wanted record.
506 * @param[in] array_size Size of array.
507 * @param[in] array Searched array.
508 *
509 * @return Pointer to desired record on success, NULL if element is not in the array.
510 */
David Sedlákb4e44562019-07-04 15:42:12 +0200511static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200512get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200513{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200514 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200515 if (array[u].type == type) {
516 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200517 }
518 }
David Sedlákd6e56892019-07-01 15:40:24 +0200519 return NULL;
520}
521
David Sedlákbba38e52019-07-09 15:20:01 +0200522/**
523 * @brief Helper function to check mandatory constraint of subelement.
524 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200525 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200526 * @param[in] subelem_info Array of information about subelements.
527 * @param[in] subelem_info_size Size of subelem_info array.
528 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
529 *
530 * @return LY_ERR values.
531 */
532static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100533yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200534 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200535{
David Sedlákb0faad82019-07-04 14:28:59 +0200536 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200537 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200538 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200539 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200540 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200541 return LY_EVALID;
542 }
543 }
544
545 return LY_SUCCESS;
546}
547
David Sedlákbba38e52019-07-09 15:20:01 +0200548/**
549 * @brief Helper function to check "first" constraint of subelement.
550 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200551 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200552 * @param[in] subelem_info Array of information about subelements.
553 * @param[in] subelem_info_size Size of subelem_info array.
554 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200555 * @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 +0200556 *
557 * @return LY_ERR values.
558 */
559static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100560yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200561 signed char subelem_info_size, enum ly_stmt current_element,
562 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200563{
David Sedlákb0faad82019-07-04 14:28:59 +0200564 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200565 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200566 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200567 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200568 return LY_EVALID;
569 }
570 }
571
572 return LY_SUCCESS;
573}
574
David Sedlákbba38e52019-07-09 15:20:01 +0200575/**
David Sedlákb4e44562019-07-04 15:42:12 +0200576 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
577 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200578 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200579 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200580 * @param[in] kw Type of current element.
581 * @param[out] value Where value of attribute should be stored.
582 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200583 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200584 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200585 * @return LY_ERR values.
586 */
David Sedlákb4e44562019-07-04 15:42:12 +0200587static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100588yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200589 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200590{
Michal Vaskob36053d2020-03-26 15:49:30 +0100591 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
592 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100593 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200594 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
595 };
David Sedlákb4e44562019-07-04 15:42:12 +0200596
Radek Krejcif13b87b2020-12-01 22:02:17 +0100597 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200598}
599
600/**
David Sedlák6542aed2019-08-14 10:47:43 +0200601 * @brief Parse path element.
602 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200603 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200604 * @param[in] kw Type of current element.
605 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200606 * @return LY_ERR values.
607 */
608static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100609yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200610{
Michal Vasko004d3152020-06-11 19:59:22 +0200611 LY_ERR ret;
612 const char *str_path;
613
614 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
Michal Vasko6b26e742020-07-17 15:02:10 +0200615 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko69730152020-10-09 16:30:07 +0200616 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200617 lydict_remove(ctx->xmlctx->ctx, str_path);
618 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200619 type->flags |= LYS_SET_PATH;
620
621 return LY_SUCCESS;
622}
623
624/**
David Sedlákd3983112019-07-12 11:20:56 +0200625 * @brief Parse pattern element.
626 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200627 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200628 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200629 * @return LY_ERR values.
630 */
631static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100632yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200633{
634 const char *real_value = NULL;
635 char *saved_value = NULL;
636 struct lysp_restr *restr;
637
Michal Vaskob36053d2020-03-26 15:49:30 +0100638 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
639 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
640 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 +0200641 size_t len = strlen(real_value);
642
643 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100644 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200645 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100646 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100647 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200648 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200649 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200650 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200651 type->flags |= LYS_SET_PATTERN;
652
Radek Krejcif13b87b2020-12-01 22:02:17 +0100653 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200654 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
655 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
656 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
657 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
658 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
659 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
660 };
Michal Vasko69730152020-10-09 16:30:07 +0200661
Radek Krejcif13b87b2020-12-01 22:02:17 +0100662 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200663}
664
David Sedlákc5b20842019-08-13 10:18:31 +0200665/**
666 * @brief Parse fraction-digits element.
667 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200668 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200669 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200670 * @return LY_ERR values.
671 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200672static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100673yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200674{
675 const char *temp_val = NULL;
676 char *ptr;
677 unsigned long int num;
678
Michal Vaskob36053d2020-03-26 15:49:30 +0100679 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
680 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 +0200681
Michal Vasko69730152020-10-09 16:30:07 +0200682 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200683 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100684 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200685 return LY_EVALID;
686 }
687
688 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100689 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200690 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200691 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100692 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200693 return LY_EVALID;
694 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100695 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200696 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100697 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200698 return LY_EVALID;
699 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100700 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200701 type->fraction_digits = num;
702 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100703 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200704 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
705 };
Michal Vasko69730152020-10-09 16:30:07 +0200706
Radek Krejcif13b87b2020-12-01 22:02:17 +0100707 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200708}
709
David Sedlák07869a52019-07-12 14:28:19 +0200710/**
David Sedlák43801c92019-08-05 15:58:54 +0200711 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200712 *
713 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200714 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200715 * @return LY_ERR values.
716 */
David Sedlákca36c422019-07-12 12:47:55 +0200717static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100718yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200719{
David Sedlák07869a52019-07-12 14:28:19 +0200720 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200721
Michal Vaskob36053d2020-03-26 15:49:30 +0100722 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200723 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100724 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
725 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 +0200726 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100727 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200728 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200729
Radek Krejcif13b87b2020-12-01 22:02:17 +0100730 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200731 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
732 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
733 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
734 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
735 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
736 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
737 };
Michal Vasko69730152020-10-09 16:30:07 +0200738
Radek Krejcif13b87b2020-12-01 22:02:17 +0100739 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200740}
741
742/**
743 * @brief Parse bit element.
744 *
745 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200746 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200747 * @return LY_ERR values.
748 */
749static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100750yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200751{
752 struct lysp_type_enum *en;
753
Michal Vaskob36053d2020-03-26 15:49:30 +0100754 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200755 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100756 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
757 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
David Sedlák43801c92019-08-05 15:58:54 +0200758 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
759
Radek Krejcif13b87b2020-12-01 22:02:17 +0100760 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200761 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
762 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
763 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
764 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
765 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
766 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
767 };
Michal Vasko69730152020-10-09 16:30:07 +0200768
Radek Krejcif13b87b2020-12-01 22:02:17 +0100769 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200770}
771
David Sedlákd3983112019-07-12 11:20:56 +0200772/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200773 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
774 * more instances, such as base or if-feature.
775 *
776 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200777 * @param[in] kw Type of current element.
778 * @param[out] values Parsed values to add to.
779 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200780 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200781 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200782 * @return LY_ERR values.
783 */
784static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100785yin_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 +0200786 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200787{
788 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200789
Michal Vaskob36053d2020-03-26 15:49:30 +0100790 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200791 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100792 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200793 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
794 };
David Sedlák968ac342019-07-11 15:17:59 +0200795
Michal Vaskob36053d2020-03-26 15:49:30 +0100796 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
797 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200798
Radek Krejcif13b87b2020-12-01 22:02:17 +0100799 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200800}
801
802/**
David Sedlák6542aed2019-08-14 10:47:43 +0200803 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
804 *
805 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200806 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200807 * @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 +0200808 * @param[in] arg_type Expected type of attribute.
809 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200810 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200811 * @return LY_ERR values.
812 */
813static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100814yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200815 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200816{
817 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100818 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200819 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200820 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100821 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200822 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200823 }
824
825 return LY_SUCCESS;
826}
827
828/**
829 * @brief Parse base element.
830 *
831 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200832 * @param[in] parent Identification of parent element.
833 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200834 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200835 * @return LY_ERR values.
836 */
837static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100838yin_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 +0200839{
840 struct lysp_type *type = NULL;
841
Radek Krejcid6b76452019-09-03 17:03:03 +0200842 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200843 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100844 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200845 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200846 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200847 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100848 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200849 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200850 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100851 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200852 return LY_EINT;
853 }
854
855 return LY_SUCCESS;
856}
857
858/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200859 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200860 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200861 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100862 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200863 * @return LY_ERR values.
864 */
865static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100866yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200867{
868 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100869 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200870 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
871 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200872
873 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100874 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
875 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 +0200876 if (strcmp(temp_val, "true") == 0) {
877 type->require_instance = 1;
878 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200879 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200880 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100881 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200882 return LY_EVALID;
883 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100884 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200885
Radek Krejcif13b87b2020-12-01 22:02:17 +0100886 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200887}
888
889/**
David Sedlákce77bf52019-07-11 16:59:31 +0200890 * @brief Parse modifier element.
891 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200892 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200893 * @param[in,out] pat Value to write to.
894 * @param[in,out] exts Extension instances to add to.
895 *
896 * @return LY_ERR values.
897 */
898static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100899yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200900{
David Sedlákd3983112019-07-12 11:20:56 +0200901 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200902 const char *temp_val;
903 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100904 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200905 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
906 };
David Sedlákce77bf52019-07-11 16:59:31 +0200907
Michal Vaskob36053d2020-03-26 15:49:30 +0100908 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
909 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 +0200910 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200911 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200912 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100913 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200914 return LY_EVALID;
915 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100916 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200917
918 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200919 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100920 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200921 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100922 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200923
924 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100925 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200926 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200927
Radek Krejcif13b87b2020-12-01 22:02:17 +0100928 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200929}
930
931/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200932 * @brief Parse a restriction element (length, range or one instance of must).
933 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200934 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200935 * @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 +0200936 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200937 */
938static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100939yin_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 +0200940{
Radek Krejcid6b76452019-09-03 17:03:03 +0200941 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100942 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200943 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
944 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
945 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
946 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
947 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
948 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200949 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200950 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200951
Michal Vaskob36053d2020-03-26 15:49:30 +0100952 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200953 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200954 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100955
Radek Krejcif13b87b2020-12-01 22:02:17 +0100956 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200957}
958
959/**
David Sedlák6542aed2019-08-14 10:47:43 +0200960 * @brief Parse range element.
961 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200962 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200963 * @param[out] type Type structure to store parsed value and flags.
964 *
965 * @return LY_ERR values.
966 */
967static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100968yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200969{
970 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100971 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
972 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200973 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200974
975 return LY_SUCCESS;
976}
977
978/**
979 * @brief Parse length element.
980 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200981 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200982 * @param[out] type Type structure to store parsed value and flags.
983 *
984 * @return LY_ERR values.
985 */
986static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100987yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200988{
989 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100990 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
991 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200992 type->flags |= LYS_SET_LENGTH;
993
994 return LY_SUCCESS;
995}
996
997/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200998 * @brief Parse must element.
999 *
1000 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001001 * @param[in,out] restrs Restrictions to add to.
1002 *
1003 * @return LY_ERR values.
1004 */
1005static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001006yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001007{
1008 struct lysp_restr *restr;
1009
Michal Vaskob36053d2020-03-26 15:49:30 +01001010 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1011 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001012}
1013
1014/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001015 * @brief Parse a node id into an array.
1016 *
1017 * @param[in,out] ctx YIN parser context for logging and to store current state.
1018 * @param[in] kw Type of current element.
1019 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1020 * @param[in,out] exts Extension instances to add to.
1021 *
1022 * @return LY_ERR values.
1023 */
1024static LY_ERR
1025yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1026 struct lysp_ext_instance **exts)
1027{
1028 struct lysp_qname *qname, **qnames;
1029
1030 switch (kw) {
1031 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001032 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1033 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001034 } else {
1035 qnames = (struct lysp_qname **)subinfo->dest;
1036 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001037 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001038 qname->mod = ctx->parsed_mod;
1039 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
1040 case LY_STMT_IF_FEATURE:
1041 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1042 qnames = (struct lysp_qname **)subinfo->dest;
1043 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1044 qname->mod = ctx->parsed_mod;
1045 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001046 default:
1047 break;
1048 }
1049
1050 LOGINT(ctx->xmlctx->ctx);
1051 return LY_EINT;
1052}
1053
1054/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001055 * @brief Parse position or value element.
1056 *
1057 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001058 * @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 +02001059 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001060 *
1061 * @return LY_ERR values.
1062 */
1063static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001064yin_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 +02001065{
Radek Krejcid6b76452019-09-03 17:03:03 +02001066 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001067 const char *temp_val = NULL;
1068 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +02001069 long int num = 0;
1070 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001071
1072 /* set value flag */
1073 enm->flags |= LYS_SET_VALUE;
1074
1075 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001076 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1077 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001078 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001079 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001080 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001081 goto error;
1082 }
1083
1084 /* convert value */
1085 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001086 if (kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001087 num = strtol(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001088 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001089 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001090 goto error;
1091 }
1092 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001093 unum = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001094 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001095 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001096 goto error;
1097 }
1098 }
1099 /* check if whole argument value was converted */
1100 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001101 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +02001102 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001103 }
1104 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001105 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +02001106 goto error;
1107 }
1108 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001109 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001110 enm->value = num;
1111 } else {
1112 enm->value = unum;
1113 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001114 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001115
1116 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001117 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001118 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1119 };
Michal Vasko69730152020-10-09 16:30:07 +02001120
Radek Krejcif13b87b2020-12-01 22:02:17 +01001121 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001122
David Sedlákbf8a2b72019-08-14 16:48:10 +02001123error:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001124 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskob36053d2020-03-26 15:49:30 +01001125 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001126}
1127
David Sedlák05404f62019-07-24 14:11:53 +02001128/**
1129 * @brief Parse belongs-to element.
1130 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001131 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001132 * @param[out] submod Structure of submodule that is being parsed.
1133 * @param[in,out] exts Extension instances to add to.
1134 *
1135 * @return LY_ERR values
1136 */
1137static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001138yin_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 +02001139{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001140 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001141 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001142 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1143 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1144 };
David Sedlák05404f62019-07-24 14:11:53 +02001145
Michal Vaskob36053d2020-03-26 15:49:30 +01001146 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001147 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001148 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001149 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001150 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001151 lydict_remove(ctx->xmlctx->ctx, belongsto);
1152 return LY_EVALID;
1153 }
1154 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001155
Radek Krejcif13b87b2020-12-01 22:02:17 +01001156 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001157}
1158
David Sedlák5545f5d2019-07-11 11:55:16 +02001159/**
David Sedlákc1771b12019-07-10 15:55:46 +02001160 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001161 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001162 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001163 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001164 * @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 +02001165 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001166 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001167 *
1168 * @return LY_ERR values.
1169 */
1170static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001171yin_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 +02001172{
Radek Krejcid6b76452019-09-03 17:03:03 +02001173 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 +02001174
Radek Krejcif13b87b2020-12-01 22:02:17 +01001175 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001176 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1177 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1178 };
Michal Vasko69730152020-10-09 16:30:07 +02001179
David Sedlákdf2a9732019-08-07 13:23:16 +02001180 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001181 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1182 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 +02001183
David Sedlákdf2a9732019-08-07 13:23:16 +02001184 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001185 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001186}
1187
1188/**
David Sedlákc1771b12019-07-10 15:55:46 +02001189 * @brief Parse error-message element.
1190 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001191 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001192 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001193 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001194 *
1195 * @return LY_ERR values.
1196 */
1197static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001198yin_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 +02001199{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001200 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001201 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1202 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1203 };
David Sedlákc1771b12019-07-10 15:55:46 +02001204
David Sedlákdf2a9732019-08-07 13:23:16 +02001205 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001206 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1207 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 +02001208
Radek Krejcif13b87b2020-12-01 22:02:17 +01001209 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001210}
1211
1212/**
David Sedlák6542aed2019-08-14 10:47:43 +02001213 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001214 *
1215 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001216 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001217 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001218 *
1219 * @return LY_ERR values.
1220 */
1221static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001222yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001223{
David Sedlák6542aed2019-08-14 10:47:43 +02001224 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001225
Radek Krejcid6b76452019-09-03 17:03:03 +02001226 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001227 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001228 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001229 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001230 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001231 type = (struct lysp_type *)subinfo->dest;
1232 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001233
David Sedlák6542aed2019-08-14 10:47:43 +02001234 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001235 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001236 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001237 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001238 type->flags |= LYS_SET_TYPE;
1239 type = nested_type;
1240 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001241
Michal Vasko5bbcc242021-02-23 09:29:13 +01001242 type->pmod = ctx->parsed_mod;
1243
Radek Krejcif13b87b2020-12-01 22:02:17 +01001244 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001245 {LY_STMT_BASE, type, 0},
1246 {LY_STMT_BIT, type, 0},
1247 {LY_STMT_ENUM, type, 0},
1248 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1249 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1250 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1251 {LY_STMT_PATTERN, type, 0},
1252 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1253 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1254 {LY_STMT_TYPE, type},
1255 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1256 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001257
1258 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1259 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01001260 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001261}
1262
David Sedlák1af868e2019-07-17 17:03:14 +02001263/**
1264 * @brief Parse max-elements element.
1265 *
1266 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001267 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001268 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001269 * @param[in,out] exts Extension instances to add to.
1270 *
1271 * @return LY_ERR values.
1272 */
1273static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001274yin_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 +02001275{
1276 const char *temp_val = NULL;
1277 char *ptr;
1278 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001279 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001280 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1281 };
David Sedlák374d2b32019-07-17 15:06:55 +02001282
David Sedlák1af868e2019-07-17 17:03:14 +02001283 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001284 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1285 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
Michal Vasko69730152020-10-09 16:30:07 +02001286 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 +02001287 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001288 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001289 return LY_EVALID;
1290 }
1291
1292 if (strcmp(temp_val, "unbounded")) {
1293 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001294 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001295 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001296 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001297 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001298 return LY_EVALID;
1299 }
1300 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001301 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001302 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001303 return LY_EVALID;
1304 }
1305 *max = num;
1306 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001307 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001308 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001309}
David Sedlák374d2b32019-07-17 15:06:55 +02001310
1311/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001312 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001313 *
1314 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001315 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001316 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001317 * @param[in,out] exts Extension instances to add to.
1318 *
1319 * @return LY_ERR values.
1320 */
1321static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001322yin_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 +02001323{
1324 const char *temp_val = NULL;
1325 char *ptr;
1326 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001327 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001328 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1329 };
David Sedlák09e18c92019-07-18 11:17:11 +02001330
1331 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001332 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1333 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 +02001334
Michal Vasko69730152020-10-09 16:30:07 +02001335 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001336 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001337 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001338 return LY_EVALID;
1339 }
1340
1341 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001342 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001343 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001345 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001346 return LY_EVALID;
1347 }
Michal Vasko69730152020-10-09 16:30:07 +02001348 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001349 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001350 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001351 return LY_EVALID;
1352 }
1353 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001354 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001355 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001356}
1357
David Sedláka2dad212019-07-18 12:45:19 +02001358/**
1359 * @brief Parse min-elements or max-elements element.
1360 *
1361 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001362 * @param[in] parent Identification of parent element.
1363 * @param[in] current Identification of current element.
1364 * @param[in] dest Where the parsed value and flags should be stored.
1365 *
1366 * @return LY_ERR values.
1367 */
David Sedlák09e18c92019-07-18 11:17:11 +02001368static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001369yin_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 +02001370{
Radek Krejcid6b76452019-09-03 17:03:03 +02001371 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1372 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 +02001373 uint32_t *lim;
1374 uint16_t *flags;
1375 struct lysp_ext_instance **exts;
1376
Radek Krejcid6b76452019-09-03 17:03:03 +02001377 if (parent == LY_STMT_LEAF_LIST) {
1378 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 +02001379 flags = &((struct lysp_node_leaflist *)dest)->flags;
1380 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001381 } else if (parent == LY_STMT_REFINE) {
1382 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001383 flags = &((struct lysp_refine *)dest)->flags;
1384 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001385 } else if (parent == LY_STMT_LIST) {
1386 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 +02001387 flags = &((struct lysp_node_list *)dest)->flags;
1388 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001389 } else {
1390 lim = ((struct minmax_dev_meta *)dest)->lim;
1391 flags = ((struct minmax_dev_meta *)dest)->flags;
1392 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001393 }
1394
Radek Krejcid6b76452019-09-03 17:03:03 +02001395 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001396 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001397 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001398 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001399 }
1400
1401 return LY_SUCCESS;
1402}
1403
1404/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001405 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001406 *
1407 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001408 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001409 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001410 *
1411 * @return LY_ERR values.
1412 */
1413static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001414yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001415{
1416 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001417 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001418 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1419 };
David Sedláka2dad212019-07-18 12:45:19 +02001420
Michal Vaskob36053d2020-03-26 15:49:30 +01001421 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1422 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 +02001423 if (strcmp(temp_val, "system") == 0) {
1424 *flags |= LYS_ORDBY_SYSTEM;
1425 } else if (strcmp(temp_val, "user") == 0) {
1426 *flags |= LYS_ORDBY_USER;
1427 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001428 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001429 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001430 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001431 return LY_EVALID;
1432 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001433 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001434
Radek Krejcif13b87b2020-12-01 22:02:17 +01001435 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001436}
1437
1438/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001439 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001440 *
1441 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001442 * @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 +02001443 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001444 *
1445 * @return LY_ERR values.
1446 */
1447static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001448yin_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 +02001449{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001450 struct lysp_node_anydata *any;
1451
David Sedlák8d552d62019-08-06 15:29:05 +02001452 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001453 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001454 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001455 any->parent = node_meta->parent;
1456
David Sedlákbf8a2b72019-08-14 16:48:10 +02001457 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001458 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1459 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 +02001460
Radek Krejcif13b87b2020-12-01 22:02:17 +01001461 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001462 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1465 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1466 {LY_STMT_MUST, &any->musts, 0},
1467 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1468 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1469 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1470 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1471 };
Michal Vasko69730152020-10-09 16:30:07 +02001472
Radek Krejcif13b87b2020-12-01 22:02:17 +01001473 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001474}
1475
1476/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001477 * @brief parse leaf element.
1478 *
1479 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001480 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001481 *
1482 * @return LY_ERR values.
1483 */
1484static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001485yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001486{
David Sedlák203ca3a2019-07-18 15:26:25 +02001487 struct lysp_node_leaf *leaf;
1488
David Sedlák8d552d62019-08-06 15:29:05 +02001489 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001490 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001491 leaf->nodetype = LYS_LEAF;
1492 leaf->parent = node_meta->parent;
1493
David Sedlák203ca3a2019-07-18 15:26:25 +02001494 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001495 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1496 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 +02001497
1498 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001499 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001500 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1501 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1502 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1503 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1504 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1505 {LY_STMT_MUST, &leaf->musts, 0},
1506 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1507 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1508 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1509 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1511 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1512 };
Michal Vasko69730152020-10-09 16:30:07 +02001513
Radek Krejcif13b87b2020-12-01 22:02:17 +01001514 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001515}
1516
1517/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001518 * @brief Parse leaf-list element.
1519 *
1520 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001521 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001522 *
1523 * @return LY_ERR values.
1524 */
1525static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001526yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001527{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001528 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001529
Michal Vaskob36053d2020-03-26 15:49:30 +01001530 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001531
David Sedlákc3da3ef2019-07-19 12:56:08 +02001532 llist->nodetype = LYS_LEAFLIST;
1533 llist->parent = node_meta->parent;
1534
David Sedlákc3da3ef2019-07-19 12:56:08 +02001535 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001536 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1537 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 +02001538
1539 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001540 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001541 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1542 {LY_STMT_DEFAULT, &llist->dflts, 0},
1543 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1544 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1545 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1546 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1547 {LY_STMT_MUST, &llist->musts, 0},
1548 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1550 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1551 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1552 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1553 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1554 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1555 };
Michal Vasko69730152020-10-09 16:30:07 +02001556
Radek Krejcif13b87b2020-12-01 22:02:17 +01001557 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 +02001558
David Sedlákbf8a2b72019-08-14 16:48:10 +02001559 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001560 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001561 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001562 return LY_EVALID;
1563 }
Michal Vasko69730152020-10-09 16:30:07 +02001564 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001565 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001566 return LY_EVALID;
1567 }
1568
1569 return LY_SUCCESS;
1570}
1571
1572/**
David Sedlák04e17b22019-07-19 15:29:48 +02001573 * @brief Parse typedef element.
1574 *
1575 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001576 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001577 *
1578 * @return LY_ERR values.
1579 */
1580static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001581yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001582{
1583 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001584 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001585
Michal Vaskob36053d2020-03-26 15:49:30 +01001586 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001587
1588 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001589 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1590 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 +02001591
1592 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001593 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001594 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1596 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1597 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1598 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1599 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1600 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1601 };
Michal Vasko69730152020-10-09 16:30:07 +02001602
Radek Krejcif13b87b2020-12-01 22:02:17 +01001603 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 +02001604
1605 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001606 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1607 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001608 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001609 }
1610
1611 return LY_SUCCESS;
1612}
1613
1614/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001615 * @brief Parse refine element.
1616 *
1617 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001618 * @param[in,out] refines Refines to add to.
1619 *
1620 * @return LY_ERR values.
1621 */
1622static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001623yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001624{
1625 struct lysp_refine *rf;
1626
1627 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001628 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001629
1630 /* parse attribute */
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_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1633 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001634
1635 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001636 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001637 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001638 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001639 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001640 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001641 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1642 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1643 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1644 {LY_STMT_MUST, &rf->musts, 0},
1645 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1646 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1647 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1648 };
Michal Vasko69730152020-10-09 16:30:07 +02001649
Radek Krejcif13b87b2020-12-01 22:02:17 +01001650 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001651}
1652
1653/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001654 * @brief Parse uses element.
1655 *
1656 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001657 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001658 *
1659 * @return LY_ERR values.
1660 */
1661static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001662yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001663{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001664 struct lysp_node_uses *uses;
1665
David Sedlák8d552d62019-08-06 15:29:05 +02001666 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001667 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001668 uses->nodetype = LYS_USES;
1669 uses->parent = node_meta->parent;
1670
David Sedlák0d6de5a2019-07-22 13:25:44 +02001671 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001672 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1673 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 +02001674
1675 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001676 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001677 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001678 {LY_STMT_AUGMENT, &augments, 0},
1679 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1680 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1681 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1682 {LY_STMT_REFINE, &uses->refines, 0},
1683 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1684 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1685 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1686 };
Michal Vasko69730152020-10-09 16:30:07 +02001687
Radek Krejcif13b87b2020-12-01 22:02:17 +01001688 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 +02001689
1690 return LY_SUCCESS;
1691}
1692
1693/**
David Sedlákaa854b02019-07-22 14:17:10 +02001694 * @brief Parse revision element.
1695 *
1696 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001697 * @param[in,out] revs Parsed revisions to add to.
1698 *
1699 * @return LY_ERR values.
1700 */
1701static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001702yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001703{
1704 struct lysp_revision *rev;
1705 const char *temp_date = NULL;
1706
1707 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001708 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001709
1710 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001711 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1712 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 +02001713 /* check value */
1714 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001715 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001716 return LY_EVALID;
1717 }
Radek Krejci36642162021-01-12 16:49:22 +01001718 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001719 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001720
1721 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001722 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001723 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1724 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1725 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1726 };
Michal Vasko69730152020-10-09 16:30:07 +02001727
Radek Krejcif13b87b2020-12-01 22:02:17 +01001728 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001729}
1730
David Sedlák5e13dea2019-07-22 16:06:45 +02001731/**
1732 * @brief Parse include element.
1733 *
1734 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001735 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1736 *
1737 * @return LY_ERR values.
1738 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001739static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001740yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001741{
1742 struct lysp_include *inc;
1743
1744 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001745 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001746
1747 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001748 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1749 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 +02001750
1751 /* submodules share the namespace with the module names, so there must not be
1752 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001753 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001754 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001755 return LY_EVALID;
1756 }
1757
1758 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001759 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001760 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1761 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1762 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1763 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1764 };
Michal Vasko69730152020-10-09 16:30:07 +02001765
Radek Krejcif13b87b2020-12-01 22:02:17 +01001766 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001767}
1768
David Sedlákaa854b02019-07-22 14:17:10 +02001769/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001770 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001771 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001772 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001773 * @param[in,out] rev Array to store the parsed value in.
1774 * @param[in,out] exts Extension instances to add to.
1775 *
1776 * @return LY_ERR values.
1777 */
1778static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001779yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001780{
1781 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001782 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001783 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1784 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001785
Michal Vaskob36053d2020-03-26 15:49:30 +01001786 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1787 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 +02001788 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 +01001789 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001790
1791 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001792 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001793
Radek Krejcif13b87b2020-12-01 22:02:17 +01001794 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001795}
1796
1797/**
1798 * @brief Parse config element.
1799 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001800 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001801 * @param[in,out] flags Flags to add to.
1802 * @param[in,out] exts Extension instances to add to.
1803 *
1804 * @return LY_ERR values.
1805 */
1806static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001807yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001808{
1809 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001810 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001811 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1812 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001813
Michal Vaskob36053d2020-03-26 15:49:30 +01001814 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1815 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 +02001816 if (strcmp(temp_val, "true") == 0) {
1817 *flags |= LYS_CONFIG_W;
1818 } else if (strcmp(temp_val, "false") == 0) {
1819 *flags |= LYS_CONFIG_R;
1820 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001821 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001822 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001823 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001824 return LY_EVALID;
1825 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001826 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001827
Radek Krejcif13b87b2020-12-01 22:02:17 +01001828 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001829}
1830
1831/**
1832 * @brief Parse yang-version element.
1833 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001834 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001835 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001836 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001837 *
1838 * @return LY_ERR values.
1839 */
1840static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001841yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001842{
1843 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001844 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001845 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1846 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001847
Michal Vaskob36053d2020-03-26 15:49:30 +01001848 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1849 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 +02001850 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001851 *version = LYS_VERSION_1_0;
1852 } else if (strcmp(temp_version, "1.1") == 0) {
1853 *version = LYS_VERSION_1_1;
1854 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001855 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001856 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001857 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001858 return LY_EVALID;
1859 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001860 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001861
Radek Krejcif13b87b2020-12-01 22:02:17 +01001862 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001863}
1864
1865/**
1866 * @brief Parse import element.
1867 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001868 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001869 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1870 *
1871 * @return LY_ERR values.
1872 */
1873static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001874yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001875{
1876 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001877
David Sedlákdfbbb442019-08-06 16:33:21 +02001878 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001879 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001880
Radek Krejcif13b87b2020-12-01 22:02:17 +01001881 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001882 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1883 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1884 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1885 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1886 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1887 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001888
1889 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001890 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1891 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 +01001892 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001893 /* check prefix validity */
1894 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1895
1896 return LY_SUCCESS;
1897}
1898
1899/**
1900 * @brief Parse mandatory element.
1901 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001902 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001903 * @param[in,out] flags Flags to add to.
1904 * @param[in,out] exts Extension instances to add to.
1905 *
1906 * @return LY_ERR values.
1907 */
1908static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001909yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001910{
1911 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001912 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001913 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1914 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001915
Michal Vaskob36053d2020-03-26 15:49:30 +01001916 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1917 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 +02001918 if (strcmp(temp_val, "true") == 0) {
1919 *flags |= LYS_MAND_TRUE;
1920 } else if (strcmp(temp_val, "false") == 0) {
1921 *flags |= LYS_MAND_FALSE;
1922 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001923 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001924 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001925 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001926 return LY_EVALID;
1927 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001928 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001929
Radek Krejcif13b87b2020-12-01 22:02:17 +01001930 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001931}
1932
1933/**
1934 * @brief Parse status element.
1935 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001936 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001937 * @param[in,out] flags Flags to add to.
1938 * @param[in,out] exts Extension instances to add to.
1939 *
1940 * @return LY_ERR values.
1941 */
1942static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001943yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001944{
1945 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001946 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001947 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1948 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001949
Michal Vaskob36053d2020-03-26 15:49:30 +01001950 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1951 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 +02001952 if (strcmp(value, "current") == 0) {
1953 *flags |= LYS_STATUS_CURR;
1954 } else if (strcmp(value, "deprecated") == 0) {
1955 *flags |= LYS_STATUS_DEPRC;
1956 } else if (strcmp(value, "obsolete") == 0) {
1957 *flags |= LYS_STATUS_OBSLT;
1958 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001959 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001960 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001961 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001962 return LY_EVALID;
1963 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001964 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001965
Radek Krejcif13b87b2020-12-01 22:02:17 +01001966 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001967}
1968
1969/**
1970 * @brief Parse when element.
1971 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001972 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001973 * @param[out] when_p When pointer to parse to.
1974 */
1975static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001976yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001977{
1978 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001979 LY_ERR ret = LY_SUCCESS;
1980
David Sedlákdfbbb442019-08-06 16:33:21 +02001981 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001982 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001983
1984 ret = lyxml_ctx_next(ctx->xmlctx);
1985 LY_CHECK_ERR_RET(ret, free(when), ret);
1986
Michal Vaskob36053d2020-03-26 15:49:30 +01001987 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001988 LY_CHECK_ERR_RET(ret, free(when), ret);
1989
David Sedlákdfbbb442019-08-06 16:33:21 +02001990 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001991 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001992 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1993 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1994 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1995 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001996
Radek Krejcif13b87b2020-12-01 22:02:17 +01001997 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001998}
1999
2000/**
2001 * @brief Parse yin-elemenet element.
2002 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002003 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002004 * @param[in,out] data Data to read from, always moved to currently handled position.
2005 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002006 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002007 *
2008 * @return LY_ERR values.
2009 */
2010static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002011yin_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 +02002012{
2013 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002014 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002015 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2016 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002017
Michal Vaskob36053d2020-03-26 15:49:30 +01002018 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2019 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 +02002020 if (strcmp(temp_val, "true") == 0) {
2021 *flags |= LYS_YINELEM_TRUE;
2022 } else if (strcmp(temp_val, "false") == 0) {
2023 *flags |= LYS_YINELEM_FALSE;
2024 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002025 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002026 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002027 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002028 return LY_EVALID;
2029 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002030 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002031
Radek Krejcif13b87b2020-12-01 22:02:17 +01002032 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002033}
2034
2035/**
2036 * @brief Parse argument element.
2037 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002038 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002039 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2040 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002041 *
2042 * @return LY_ERR values.
2043 */
2044static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002045yin_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 +02002046{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002047 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002048 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2049 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2050 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002051
Michal Vaskob36053d2020-03-26 15:49:30 +01002052 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2053 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 +02002054
Radek Krejcif13b87b2020-12-01 22:02:17 +01002055 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002056}
2057
2058/**
2059 * @brief Parse the extension statement.
2060 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002061 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002062 * @param[in,out] extensions Extensions to add to.
2063 *
2064 * @return LY_ERR values.
2065 */
2066static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002067yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002068{
2069 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002070
Michal Vaskob36053d2020-03-26 15:49:30 +01002071 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2072 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2073 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 +02002074
Radek Krejci9f87b0c2021-03-05 14:45:26 +01002075 struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002076 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002077 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2078 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2079 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2080 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2081 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2082 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002083
Radek Krejcif13b87b2020-12-01 22:02:17 +01002084 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002085}
2086
2087/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002088 * @brief Parse feature element.
2089 *
2090 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002091 * @param[in,out] features Features to add to.
2092 *
2093 * @return LY_ERR values.
2094 */
2095static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002096yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002097{
2098 struct lysp_feature *feat;
2099
2100 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002101 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002102
2103 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002104 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2105 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 +02002106
2107 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002108 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002109 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2110 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2111 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2112 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2113 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2114 };
Michal Vasko69730152020-10-09 16:30:07 +02002115
Radek Krejcif13b87b2020-12-01 22:02:17 +01002116 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002117}
2118
2119/**
David Sedlák28794f22019-07-22 16:45:00 +02002120 * @brief Parse identity element.
2121 *
2122 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002123 * @param[in,out] identities Identities to add to.
2124 *
2125 * @return LY_ERR values.
2126 */
2127static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002128yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002129{
2130 struct lysp_ident *ident;
2131
2132 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002133 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002134
2135 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002136 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2137 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 +02002138
2139 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002140 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002141 {LY_STMT_BASE, &ident->bases, 0},
2142 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2143 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2144 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2145 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2146 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2147 };
Michal Vasko69730152020-10-09 16:30:07 +02002148
Radek Krejcif13b87b2020-12-01 22:02:17 +01002149 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002150}
2151
2152/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002153 * @brief Parse list element.
2154 *
2155 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002156 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002157 *
2158 * @return LY_ERR values.
2159 */
2160static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002161yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002162{
David Sedlákaf536aa2019-07-23 13:42:23 +02002163 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002164 LY_ERR ret = LY_SUCCESS;
2165 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002166 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002167
Michal Vaskob36053d2020-03-26 15:49:30 +01002168 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002169 list->nodetype = LYS_LIST;
2170 list->parent = node_meta->parent;
2171
David Sedlákaf536aa2019-07-23 13:42:23 +02002172 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002173 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2174 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 +02002175
2176 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002177 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002178 LY_STMT_ACTION, &list->actions, 0,
2179 LY_STMT_ANYDATA, &list->child, 0,
2180 LY_STMT_ANYXML, &list->child, 0,
2181 LY_STMT_CHOICE, &list->child, 0,
2182 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2183 LY_STMT_CONTAINER, &list->child, 0,
2184 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2185 LY_STMT_GROUPING, &list->groupings, 0,
2186 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2187 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2188 LY_STMT_LEAF, &list->child, 0,
2189 LY_STMT_LEAF_LIST, &list->child, 0,
2190 LY_STMT_LIST, &list->child, 0,
2191 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2192 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2193 LY_STMT_MUST, &list->musts, 0,
2194 LY_STMT_NOTIFICATION, &list->notifs, 0,
2195 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2196 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2197 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2198 LY_STMT_TYPEDEF, &list->typedefs, 0,
2199 LY_STMT_UNIQUE, &list->uniques, 0,
2200 LY_STMT_USES, &list->child, 0,
2201 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2202 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002203 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2204 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002205 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002206
Michal Vasko69730152020-10-09 16:30:07 +02002207 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002208 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002209 return LY_EVALID;
2210 }
2211
2212 return LY_SUCCESS;
2213}
2214
2215/**
David Sedlák031b9e72019-07-23 15:19:37 +02002216 * @brief Parse notification element.
2217 *
2218 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002219 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002220 *
2221 * @return LY_ERR values.
2222 */
2223static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002224yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002225{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002226 struct lysp_node_notif *notif;
2227 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002228 LY_ERR ret = LY_SUCCESS;
2229 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002230 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002231
2232 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002233 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002234 notif->nodetype = LYS_NOTIF;
2235 notif->parent = notif_meta->parent;
2236
2237 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002238 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2239 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 +02002240
2241 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002242 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002243 LY_STMT_ANYDATA, &notif->child, 0,
2244 LY_STMT_ANYXML, &notif->child, 0,
2245 LY_STMT_CHOICE, &notif->child, 0,
2246 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002247 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2248 LY_STMT_GROUPING, &notif->groupings, 0,
2249 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002250 LY_STMT_LEAF, &notif->child, 0,
2251 LY_STMT_LEAF_LIST, &notif->child, 0,
2252 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002253 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2254 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2255 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2256 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002257 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002258 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002259
Radek Krejcif13b87b2020-12-01 22:02:17 +01002260 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2261 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002262 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002263
David Sedlák031b9e72019-07-23 15:19:37 +02002264 return LY_SUCCESS;
2265}
2266
2267/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002268 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002269 *
2270 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002271 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002272 *
2273 * @return LY_ERR values.
2274 */
2275static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002276yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002277{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002278 struct lysp_node_grp *grp;
2279 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002280 LY_ERR ret = LY_SUCCESS;
2281 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002282 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002283
2284 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002285 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002286 grp->nodetype = LYS_GROUPING;
2287 grp->parent = gr_meta->parent;
2288
2289 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002290 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2291 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 +02002292
2293 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002294 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002295 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002296 LY_STMT_ANYDATA, &grp->child, 0,
2297 LY_STMT_ANYXML, &grp->child, 0,
2298 LY_STMT_CHOICE, &grp->child, 0,
2299 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002300 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2301 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002302 LY_STMT_LEAF, &grp->child, 0,
2303 LY_STMT_LEAF_LIST, &grp->child, 0,
2304 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002305 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2306 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2307 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2308 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002309 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002310 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002311 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2312 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002313
Radek Krejci2a9fc652021-01-22 17:44:34 +01002314 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002315}
2316
2317/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002318 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002319 *
2320 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002321 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002322 *
2323 * @return LY_ERR values.
2324 */
2325static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002326yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002327{
David Sedlákf111bcb2019-07-23 17:15:51 +02002328 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002329 LY_ERR ret = LY_SUCCESS;
2330 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002331 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002332
2333 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002334 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002335 cont->nodetype = LYS_CONTAINER;
2336 cont->parent = node_meta->parent;
2337
David Sedlákf111bcb2019-07-23 17:15:51 +02002338 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002339 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2340 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 +02002341
2342 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002343 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002344 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2345 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2346 LY_STMT_ANYXML, &cont->child, 0,
2347 LY_STMT_CHOICE, &cont->child, 0,
2348 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2349 LY_STMT_CONTAINER, &cont->child, 0,
2350 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2351 LY_STMT_GROUPING, &cont->groupings, 0,
2352 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2353 LY_STMT_LEAF, &cont->child, 0,
2354 LY_STMT_LEAF_LIST, &cont->child, 0,
2355 LY_STMT_LIST, &cont->child, 0,
2356 LY_STMT_MUST, &cont->musts, 0,
2357 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2358 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2360 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2361 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2362 LY_STMT_USES, &cont->child, 0,
2363 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2364 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002365 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2366 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002367
Radek Krejci2a9fc652021-01-22 17:44:34 +01002368 return ret;
David Sedlákf111bcb2019-07-23 17:15:51 +02002369}
2370
2371/**
David Sedlák5379d392019-07-24 10:42:03 +02002372 * @brief Parse case element.
2373 *
2374 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002375 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002376 *
2377 * @return LY_ERR values.
2378 */
2379static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002380yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002381{
David Sedlák5379d392019-07-24 10:42:03 +02002382 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002383 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002384 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002385 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002386
2387 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002388 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002389 cas->nodetype = LYS_CASE;
2390 cas->parent = node_meta->parent;
2391
David Sedlák5379d392019-07-24 10:42:03 +02002392 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002393 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2394 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 +02002395
2396 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002397 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002398 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2399 LY_STMT_ANYXML, &cas->child, 0,
2400 LY_STMT_CHOICE, &cas->child, 0,
2401 LY_STMT_CONTAINER, &cas->child, 0,
2402 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2403 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2404 LY_STMT_LEAF, &cas->child, 0,
2405 LY_STMT_LEAF_LIST, &cas->child, 0,
2406 LY_STMT_LIST, &cas->child, 0,
2407 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2408 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2409 LY_STMT_USES, &cas->child, 0,
2410 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2411 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002412 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2413 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002414
2415 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002416}
2417
2418/**
David Sedlák05404f62019-07-24 14:11:53 +02002419 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002420 *
2421 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002422 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002423 *
2424 * @return LY_ERR values.
2425 */
2426LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002427yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002428{
David Sedlák81497a32019-08-13 16:56:26 +02002429 LY_ERR ret = LY_SUCCESS;
2430 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002431 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002432 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002433
2434 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002435 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002436
David Sedlákb7abcfa2019-07-24 12:33:35 +02002437 choice->nodetype = LYS_CHOICE;
2438 choice->parent = node_meta->parent;
2439
David Sedlákb7abcfa2019-07-24 12:33:35 +02002440 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002441 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2442 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 +02002443
2444 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002445 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002446 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2447 LY_STMT_ANYXML, &choice->child, 0,
2448 LY_STMT_CASE, &choice->child, 0,
2449 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2450 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2451 LY_STMT_CONTAINER, &choice->child, 0,
2452 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2453 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2454 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2455 LY_STMT_LEAF, &choice->child, 0,
2456 LY_STMT_LEAF_LIST, &choice->child, 0,
2457 LY_STMT_LIST, &choice->child, 0,
2458 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2459 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2460 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2461 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2462 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002463 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2464 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002465 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002466}
2467
2468/**
David Sedlák05404f62019-07-24 14:11:53 +02002469 * @brief Parse input or output element.
2470 *
2471 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002472 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002473 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2474 *
2475 * @return LY_ERR values.
2476 */
2477static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002478yin_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 +02002479{
David Sedlák81497a32019-08-13 16:56:26 +02002480 LY_ERR ret = LY_SUCCESS;
2481 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002482 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002483
David Sedlák05404f62019-07-24 14:11:53 +02002484 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002485 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 +02002486 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002487 inout_meta->inout_p->parent = inout_meta->parent;
2488
2489 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002490 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2491 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 +02002492
2493 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002494 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002495 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2496 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2497 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2498 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002499 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002500 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2501 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2502 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002503 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2504 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002505 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002506 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002507 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2508 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002509 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002510
Radek Krejci01180ac2021-01-27 08:48:22 +01002511 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002512 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2513 return LY_EVALID;
2514 }
2515
David Sedlák05404f62019-07-24 14:11:53 +02002516 return LY_SUCCESS;
2517}
2518
David Sedlák992fb7c2019-07-24 16:51:01 +02002519/**
2520 * @brief Parse action element.
2521 *
2522 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002523 * @param[in] act_meta Meta information about parent node and actions to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002527static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002528yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002529{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002530 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002531 LY_ERR ret = LY_SUCCESS;
2532 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002533 size_t subelems_size;
Radek Krejci39b7fc22021-02-26 23:29:18 +01002534 enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002535
2536 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002537 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002538 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002539 act->parent = act_meta->parent;
2540
2541 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002542 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002543 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
David Sedlák85d0eca2019-07-24 15:15:21 +02002544
2545 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002546 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002547 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2548 LY_STMT_GROUPING, &act->groupings, 0,
2549 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2550 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2551 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2552 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2553 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2554 LY_STMT_TYPEDEF, &act->typedefs, 0,
2555 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejci39b7fc22021-02-26 23:29:18 +01002556 ret = (yin_parse_content(ctx, subelems, subelems_size, kw, NULL, &act->exts));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002557 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002558 LY_CHECK_RET(ret);
2559
Michal Vasko7f45cf22020-10-01 12:49:44 +02002560 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2561 if (!act->input.nodetype) {
2562 act->input.nodetype = LYS_INPUT;
2563 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002564 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002565 }
2566 if (!act->output.nodetype) {
2567 act->output.nodetype = LYS_OUTPUT;
2568 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002569 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002570 }
2571
David Sedlák85d0eca2019-07-24 15:15:21 +02002572 return LY_SUCCESS;
2573}
2574
David Sedlák05404f62019-07-24 14:11:53 +02002575/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002576 * @brief Parse augment element.
2577 *
2578 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002579 * @param[in] aug_meta Meta information about parent node and augments to add to.
2580 *
2581 * @return LY_ERR values.
2582 */
2583static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002584yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002585{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002586 struct lysp_node_augment *aug;
2587 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002588 LY_ERR ret = LY_SUCCESS;
2589 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002590 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002591
2592 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002593 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002594 aug->nodetype = LYS_AUGMENT;
2595 aug->parent = aug_meta->parent;
2596
2597 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002598 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2599 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2600 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002601
2602 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002603 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002604 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2605 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2606 LY_STMT_ANYXML, &aug->child, 0,
2607 LY_STMT_CASE, &aug->child, 0,
2608 LY_STMT_CHOICE, &aug->child, 0,
2609 LY_STMT_CONTAINER, &aug->child, 0,
2610 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002611 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002612 LY_STMT_LEAF, &aug->child, 0,
2613 LY_STMT_LEAF_LIST, &aug->child, 0,
2614 LY_STMT_LIST, &aug->child, 0,
2615 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2616 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2617 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2618 LY_STMT_USES, &aug->child, 0,
2619 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2620 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002621 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2622 subelems_deallocator(subelems_size, subelems);
David Sedlák992fb7c2019-07-24 16:51:01 +02002623
Radek Krejci2a9fc652021-01-22 17:44:34 +01002624 return ret;
David Sedlák992fb7c2019-07-24 16:51:01 +02002625}
2626
David Sedlák8b754462019-07-25 16:22:13 +02002627/**
2628 * @brief Parse deviate element.
2629 *
2630 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002631 * @param[in] deviates Deviates to add to.
2632 *
2633 * @return LY_ERR values.
2634 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002635static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002636yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002637{
2638 LY_ERR ret = LY_SUCCESS;
2639 uint8_t dev_mod;
2640 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002641 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002642 struct lysp_deviate_add *d_add = NULL;
2643 struct lysp_deviate_rpl *d_rpl = NULL;
2644 struct lysp_deviate_del *d_del = NULL;
2645
2646 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002647 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2648 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 +02002649
2650 if (strcmp(temp_val, "not-supported") == 0) {
2651 dev_mod = LYS_DEV_NOT_SUPPORTED;
2652 } else if (strcmp(temp_val, "add") == 0) {
2653 dev_mod = LYS_DEV_ADD;
2654 } else if (strcmp(temp_val, "replace") == 0) {
2655 dev_mod = LYS_DEV_REPLACE;
2656 } else if (strcmp(temp_val, "delete") == 0) {
2657 dev_mod = LYS_DEV_DELETE;
2658 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002659 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002660 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002661 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002662 return LY_EVALID;
2663 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002664 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002665
2666 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2667 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002668 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002669 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002670 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2671 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002672 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002673
2674 } else if (dev_mod == LYS_DEV_ADD) {
2675 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002676 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002677 d = (struct lysp_deviate *)d_add;
2678 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2679 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002680 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002681 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002682 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002683 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2684 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2685 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2686 {LY_STMT_MUST, &d_add->musts, 0},
2687 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2688 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2689 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2690 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002691 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002692
2693 } else if (dev_mod == LYS_DEV_REPLACE) {
2694 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002695 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002696 d = (struct lysp_deviate *)d_rpl;
2697 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2698 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002699 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002700 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002701 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002702 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2703 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2704 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2705 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2706 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2707 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2708 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002709 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002710
2711 } else {
2712 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002713 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002714 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002715 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002716 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002717 {LY_STMT_MUST, &d_del->musts, 0},
2718 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2719 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2720 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2721 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002722 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002723 }
2724 LY_CHECK_GOTO(ret, cleanup);
2725
2726 d->mod = dev_mod;
2727 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002728 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002729
2730 return ret;
2731
2732cleanup:
2733 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002734 return ret;
2735}
2736
David Sedlák992fb7c2019-07-24 16:51:01 +02002737/**
David Sedlák8b754462019-07-25 16:22:13 +02002738 * @brief Parse deviation element.
2739 *
2740 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002741 * @param[in] deviations Deviations to add to.
2742 *
2743 * @return LY_ERR values.
2744 */
2745static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002746yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002747{
2748 struct lysp_deviation *dev;
2749
2750 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002751 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002752
2753 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002754 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2755 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2756 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002757 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002758 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2759 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2760 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2761 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2762 };
Michal Vasko69730152020-10-09 16:30:07 +02002763
Radek Krejcif13b87b2020-12-01 22:02:17 +01002764 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002765}
2766
2767/**
David Sedlákc5b20842019-08-13 10:18:31 +02002768 * @brief map keyword to keyword-group.
2769 *
2770 * @param[in] ctx YIN parser context used for logging.
2771 * @param[in] kw Keyword that is child of module or submodule.
2772 * @param[out] group Group of keyword.
2773 *
2774 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2775 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002776static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002777kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002778{
2779 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002780 /* module header */
2781 case LY_STMT_NONE:
2782 case LY_STMT_NAMESPACE:
2783 case LY_STMT_PREFIX:
2784 case LY_STMT_BELONGS_TO:
2785 case LY_STMT_YANG_VERSION:
2786 *group = Y_MOD_MODULE_HEADER;
2787 break;
2788 /* linkage */
2789 case LY_STMT_INCLUDE:
2790 case LY_STMT_IMPORT:
2791 *group = Y_MOD_LINKAGE;
2792 break;
2793 /* meta */
2794 case LY_STMT_ORGANIZATION:
2795 case LY_STMT_CONTACT:
2796 case LY_STMT_DESCRIPTION:
2797 case LY_STMT_REFERENCE:
2798 *group = Y_MOD_META;
2799 break;
2800 /* revision */
2801 case LY_STMT_REVISION:
2802 *group = Y_MOD_REVISION;
2803 break;
2804 /* body */
2805 case LY_STMT_ANYDATA:
2806 case LY_STMT_ANYXML:
2807 case LY_STMT_AUGMENT:
2808 case LY_STMT_CHOICE:
2809 case LY_STMT_CONTAINER:
2810 case LY_STMT_DEVIATION:
2811 case LY_STMT_EXTENSION:
2812 case LY_STMT_FEATURE:
2813 case LY_STMT_GROUPING:
2814 case LY_STMT_IDENTITY:
2815 case LY_STMT_LEAF:
2816 case LY_STMT_LEAF_LIST:
2817 case LY_STMT_LIST:
2818 case LY_STMT_NOTIFICATION:
2819 case LY_STMT_RPC:
2820 case LY_STMT_TYPEDEF:
2821 case LY_STMT_USES:
2822 case LY_STMT_EXTENSION_INSTANCE:
2823 *group = Y_MOD_BODY;
2824 break;
2825 default:
2826 LOGINT(ctx->xmlctx->ctx);
2827 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002828 }
2829
2830 return LY_SUCCESS;
2831}
2832
David Sedlákc5b20842019-08-13 10:18:31 +02002833/**
2834 * @brief Check if relative order of two keywords is valid.
2835 *
2836 * @param[in] ctx YIN parser context used for logging.
2837 * @param[in] kw Current keyword.
2838 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002839 * @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 +02002840 * because relative order is required only in module and submodule sub-elements, used for logging.
2841 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002842 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002843 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002844static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002845yin_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 +02002846{
Radek Krejcid6b76452019-09-03 17:03:03 +02002847 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002848 enum yang_module_stmt gr, next_gr;
2849
2850 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2851 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2852
2853 if (gr > next_gr) {
2854 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2855 return LY_EVALID;
2856 }
2857
2858 return LY_SUCCESS;
2859}
2860
David Sedlákc5dd0942019-09-13 10:23:59 +02002861/**
Michal Vaskoafac7822020-10-20 14:22:26 +02002862 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2863 *
2864 * @param[in,out] ctx Yin parser context for logging and to store current state.
2865 * @param[in] elem_type Type of element that is currently being parsed.
2866 * @param[out] arg Value to write to.
2867 *
2868 * @return LY_ERR values.
2869 */
2870static LY_ERR
2871yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2872{
2873 enum ly_stmt child;
2874
2875 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2876
2877 switch (elem_type) {
2878 case LY_STMT_ACTION:
2879 case LY_STMT_ANYDATA:
2880 case LY_STMT_ANYXML:
2881 case LY_STMT_ARGUMENT:
2882 case LY_STMT_BASE:
2883 case LY_STMT_BIT:
2884 case LY_STMT_CASE:
2885 case LY_STMT_CHOICE:
2886 case LY_STMT_CONTAINER:
2887 case LY_STMT_ENUM:
2888 case LY_STMT_EXTENSION:
2889 case LY_STMT_FEATURE:
2890 case LY_STMT_GROUPING:
2891 case LY_STMT_IDENTITY:
2892 case LY_STMT_IF_FEATURE:
2893 case LY_STMT_LEAF:
2894 case LY_STMT_LEAF_LIST:
2895 case LY_STMT_LIST:
2896 case LY_STMT_MODULE:
2897 case LY_STMT_NOTIFICATION:
2898 case LY_STMT_RPC:
2899 case LY_STMT_SUBMODULE:
2900 case LY_STMT_TYPE:
2901 case LY_STMT_TYPEDEF:
2902 case LY_STMT_UNITS:
2903 case LY_STMT_USES:
2904 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
2905 break;
2906 case LY_STMT_AUGMENT:
2907 case LY_STMT_DEVIATION:
2908 case LY_STMT_REFINE:
2909 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
2910 break;
2911 case LY_STMT_CONFIG:
2912 case LY_STMT_DEFAULT:
2913 case LY_STMT_DEVIATE:
2914 case LY_STMT_ERROR_APP_TAG:
2915 case LY_STMT_FRACTION_DIGITS:
2916 case LY_STMT_KEY:
2917 case LY_STMT_LENGTH:
2918 case LY_STMT_MANDATORY:
2919 case LY_STMT_MAX_ELEMENTS:
2920 case LY_STMT_MIN_ELEMENTS:
2921 case LY_STMT_MODIFIER:
2922 case LY_STMT_ORDERED_BY:
2923 case LY_STMT_PATH:
2924 case LY_STMT_PATTERN:
2925 case LY_STMT_POSITION:
2926 case LY_STMT_PREFIX:
2927 case LY_STMT_PRESENCE:
2928 case LY_STMT_RANGE:
2929 case LY_STMT_REQUIRE_INSTANCE:
2930 case LY_STMT_STATUS:
2931 case LY_STMT_VALUE:
2932 case LY_STMT_YANG_VERSION:
2933 case LY_STMT_YIN_ELEMENT:
2934 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
2935 break;
2936 case LY_STMT_IMPORT:
2937 case LY_STMT_INCLUDE:
2938 case LY_STMT_BELONGS_TO:
2939 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
2940 break;
2941 case LY_STMT_INPUT:
2942 case LY_STMT_OUTPUT:
2943 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2944 break;
2945 case LY_STMT_MUST:
2946 case LY_STMT_WHEN:
2947 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
2948 break;
2949 case LY_STMT_NAMESPACE:
2950 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
2951 break;
2952 case LY_STMT_REVISION:
2953 case LY_STMT_REVISION_DATE:
2954 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
2955 break;
2956 case LY_STMT_UNIQUE:
2957 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
2958 break;
2959 /* argument is mapped to yin element */
2960 case LY_STMT_CONTACT:
2961 case LY_STMT_DESCRIPTION:
2962 case LY_STMT_ORGANIZATION:
2963 case LY_STMT_REFERENCE:
2964 case LY_STMT_ERROR_MESSAGE:
2965 /* there shouldn't be any attribute, argument is supposed to be first subelement */
2966 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
2967
2968 /* no content */
2969 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
2970 if (ctx->xmlctx->ws_only) {
2971 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2972 }
2973 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
2974 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
2975 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
2976 return LY_EVALID;
2977 }
2978
2979 /* parse child element */
2980 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
2981 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
2982 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
2983 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
2984 ly_stmt2str(elem_type));
2985 return LY_EVALID;
2986 }
2987 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2988
2989 /* no attributes expected? TODO */
2990 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
2991 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2992 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2993 }
2994
2995 /* load and save content */
2996 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
2997 LY_CHECK_RET(!*arg, LY_EMEM);
2998
2999 /* load closing tag of subelement */
3000 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3001
3002 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3003 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3004 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3005 }*/
3006 break;
3007 default:
3008 LOGINT(ctx->xmlctx->ctx);
3009 return LY_EINT;
3010 }
3011
3012 return LY_SUCCESS;
3013}
3014
3015/**
3016 * @brief Parse yin element into generic structure.
3017 *
3018 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3019 * @param[in] parent Identification of parent element.
3020 * @param[out] element Where the element structure should be stored.
3021 *
3022 * @return LY_ERR values.
3023 */
3024LY_ERR
3025yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3026{
3027 LY_ERR ret = LY_SUCCESS;
3028 struct lysp_stmt *last = NULL, *new = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003029 char *id;
Michal Vaskoafac7822020-10-20 14:22:26 +02003030
3031 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3032
3033 /* allocate new structure for element */
3034 *element = calloc(1, sizeof(**element));
3035 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003036
3037 /* store identifier */
3038 if (ctx->xmlctx->prefix_len) {
3039 if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3040 ctx->xmlctx->name) == -1) {
3041 LOGMEM(ctx->xmlctx->ctx);
3042 ret = LY_EMEM;
3043 goto cleanup;
3044 }
3045 LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3046
3047 /* store prefix data for the statement */
3048 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->stmt, strlen((*element)->stmt), LY_PREF_XML,
3049 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3050 } else {
3051 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3052 }
Michal Vaskoafac7822020-10-20 14:22:26 +02003053
3054 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3055 ctx->xmlctx->prefix_len, parent);
3056
3057 last = (*element)->child;
3058 if ((*element)->kw == LY_STMT_NONE) {
3059 /* unrecognized element */
3060 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3061 ly_stmt2str(parent));
3062 ret = LY_EVALID;
3063 goto cleanup;
3064 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3065 /* element is known yang keyword, which means argument can be parsed correctly. */
3066 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3067 LY_CHECK_GOTO(ret, cleanup);
3068 } else {
3069 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3070
3071 /* load attributes in generic way, save all attributes in linked list */
3072 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3073 new = calloc(1, sizeof(*last));
3074 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3075 if (!(*element)->child) {
3076 /* save first */
3077 (*element)->child = new;
3078 } else {
3079 last->next = new;
3080 }
3081 last = new;
3082
3083 last->flags |= LYS_YIN_ATTR;
3084 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3085 last->kw = LY_STMT_NONE;
3086 /* attributes with prefix are ignored */
3087 if (!ctx->xmlctx->prefix) {
3088 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3089
3090 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3091 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3092 } else {
3093 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3094 }
3095 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3096 }
3097 }
3098
3099 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3100 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3101 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3102 /* parse subelements */
3103 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3104 LY_CHECK_GOTO(ret, cleanup);
3105 if (!(*element)->child) {
3106 /* save first */
3107 (*element)->child = new;
3108 } else {
3109 last->next = new;
3110 }
3111 last = new;
3112
3113 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3114 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3115 }
3116 } else {
3117 /* save element content */
3118 if (ctx->xmlctx->value_len) {
3119 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3120 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
Michal Vaskofc2cd072021-02-24 13:17:17 +01003121
3122 /* store prefix data for the argument as well */
3123 LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->arg, strlen((*element)->arg), LY_PREF_XML,
3124 &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
Michal Vaskoafac7822020-10-20 14:22:26 +02003125 }
3126
3127 /* read closing tag */
3128 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3129 }
3130
3131cleanup:
3132 return ret;
3133}
3134
3135/**
3136 * @brief Parse instance of extension.
3137 *
3138 * @param[in,out] ctx Yin parser context for logging and to store current state.
Radek Krejcifc596f92021-02-26 22:40:26 +01003139 * @param[in] subelem The statement this extension instance is a subelement of.
Michal Vaskoafac7822020-10-20 14:22:26 +02003140 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3141 * @param[in,out] exts Extension instance to add to.
3142 *
3143 * @return LY_ERR values.
3144 */
3145LY_ERR
Radek Krejcifc596f92021-02-26 22:40:26 +01003146yin_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 +02003147 struct lysp_ext_instance **exts)
3148{
3149 struct lysp_ext_instance *e;
3150 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003151 char *ext_name;
Michal Vaskoafac7822020-10-20 14:22:26 +02003152
3153 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003154 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003155
3156 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3157
Michal Vaskofc2cd072021-02-24 13:17:17 +01003158 if (!ctx->xmlctx->prefix_len) {
3159 LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3160 (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3161 return LY_EVALID;
3162 }
3163
3164 /* store prefixed name */
3165 if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3166 ctx->xmlctx->name) == -1) {
3167 LOGMEM(ctx->xmlctx->ctx);
3168 return LY_EMEM;
3169 }
3170 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3171
3172 /* store prefix data for the name */
3173 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->name, strlen(e->name), LY_PREF_XML, &ctx->xmlctx->ns,
3174 &e->format, &e->prefix_data));
3175
Radek Krejciab430862021-03-02 20:13:40 +01003176 e->parent_stmt = subelem;
3177 e->parent_stmt_index = subelem_index;
Michal Vaskofc2cd072021-02-24 13:17:17 +01003178
Michal Vaskoafac7822020-10-20 14:22:26 +02003179 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3180
3181 /* store attributes as subelements */
3182 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3183 if (!ctx->xmlctx->prefix) {
3184 new_subelem = calloc(1, sizeof(*new_subelem));
3185 if (!e->child) {
3186 e->child = new_subelem;
3187 } else {
3188 last_subelem->next = new_subelem;
3189 }
3190 last_subelem = new_subelem;
3191
3192 last_subelem->flags |= LYS_YIN_ATTR;
3193 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3194 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3195 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3196
Michal Vaskofc2cd072021-02-24 13:17:17 +01003197 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3198 last_subelem->arg);
Michal Vaskoafac7822020-10-20 14:22:26 +02003199 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3200 } else {
3201 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3202 }
3203
3204 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3205 }
3206
3207 /* parse subelements */
3208 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3209 if (ctx->xmlctx->ws_only) {
3210 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3211 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3212 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3213 if (!e->child) {
3214 e->child = new_subelem;
3215 } else {
3216 last_subelem->next = new_subelem;
3217 }
3218 last_subelem = new_subelem;
3219
3220 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3221 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3222 }
3223 } else if (ctx->xmlctx->value_len) {
3224 /* save text content */
3225 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3226 LY_CHECK_RET(!e->argument, LY_EMEM);
3227
Michal Vaskofc2cd072021-02-24 13:17:17 +01003228 /* store prefix data for the argument as well */
3229 LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->argument, strlen(e->argument), LY_PREF_XML,
Radek Krejci07a55962021-03-02 20:16:43 +01003230 &ctx->xmlctx->ns, &e->format, &e->prefix_data));
Michal Vaskofc2cd072021-02-24 13:17:17 +01003231
Michal Vaskoafac7822020-10-20 14:22:26 +02003232 /* parser next */
3233 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3234 }
3235
3236 return LY_SUCCESS;
3237}
3238
3239/**
3240 * @brief Generic function for content parsing
3241 *
3242 * @param[in,out] ctx Yin parser context for logging and to store current state.
3243 * @param[in] subelem_info array of valid subelement types and meta information
3244 * @param[in] subelem_info_size Size of subelem_info array.
3245 * @param[in] current_element Type of current element.
3246 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3247 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3248 *
3249 * @return LY_ERR values.
3250 */
David Sedlákd6e56892019-07-01 15:40:24 +02003251LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003252yin_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 +02003253 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003254{
3255 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003256 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003257 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003258 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003259
Michal Vaskob36053d2020-03-26 15:49:30 +01003260 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003261
Michal Vaskob36053d2020-03-26 15:49:30 +01003262 if (ctx->xmlctx->ws_only) {
3263 /* check whether there are any children */
3264 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3265 } else {
3266 /* we want to parse the value */
3267 next_status = LYXML_ELEM_CLOSE;
3268 }
3269
3270 if (next_status == LYXML_ELEMENT) {
3271 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3272
3273 /* current element has subelements as content */
3274 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3275 /* match keyword */
3276 last_kw = kw;
3277 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003278 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003279
3280 /* check if this element can be child of current element */
3281 subelem = get_record(kw, subelem_info_size, subelem_info);
3282 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003283 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003284 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3285 } else {
3286 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003287 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003288 }
3289 ret = LY_EVALID;
3290 goto cleanup;
3291 }
3292
3293 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003294 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003295 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3296 LY_CHECK_GOTO(ret, cleanup);
3297 }
3298
3299 /* flag check */
3300 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3301 /* subelement uniquenes */
3302 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3303 return LY_EVALID;
3304 }
3305 if (subelem->flags & YIN_SUBELEM_FIRST) {
3306 /* subelement is supposed to be defined as first subelement */
3307 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3308 LY_CHECK_GOTO(ret, cleanup);
3309 }
3310 if (subelem->flags & YIN_SUBELEM_VER2) {
3311 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003312 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003313 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 +02003314 ret = LY_EVALID;
3315 goto cleanup;
3316 }
David Sedlákd6e56892019-07-01 15:40:24 +02003317 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003318 /* note that element was parsed for easy uniqueness check in next iterations */
3319 subelem->flags |= YIN_SUBELEM_PARSED;
3320
3321 switch (kw) {
3322 /* call responsible function */
3323 case LY_STMT_EXTENSION_INSTANCE:
Radek Krejci39b7fc22021-02-26 23:29:18 +01003324 ret = yin_parse_extension_instance(ctx, current_element,
Michal Vasko69730152020-10-09 16:30:07 +02003325 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003326 break;
3327 case LY_STMT_ACTION:
3328 case LY_STMT_RPC:
3329 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3330 break;
3331 case LY_STMT_ANYDATA:
3332 case LY_STMT_ANYXML:
3333 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3334 break;
3335 case LY_STMT_ARGUMENT:
3336 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3337 break;
3338 case LY_STMT_AUGMENT:
3339 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3340 break;
3341 case LY_STMT_BASE:
3342 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3343 break;
3344 case LY_STMT_BELONGS_TO:
3345 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3346 break;
3347 case LY_STMT_BIT:
3348 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3349 break;
3350 case LY_STMT_CASE:
3351 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3352 break;
3353 case LY_STMT_CHOICE:
3354 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3355 break;
3356 case LY_STMT_CONFIG:
3357 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3358 break;
3359 case LY_STMT_CONTACT:
3360 case LY_STMT_DESCRIPTION:
3361 case LY_STMT_ORGANIZATION:
3362 case LY_STMT_REFERENCE:
3363 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3364 break;
3365 case LY_STMT_CONTAINER:
3366 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3367 break;
3368 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003369 ret = yin_parse_qname(ctx, kw, subelem, exts);
3370 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003371 case LY_STMT_ERROR_APP_TAG:
3372 case LY_STMT_KEY:
3373 case LY_STMT_PRESENCE:
3374 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3375 break;
3376 case LY_STMT_DEVIATE:
3377 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3378 break;
3379 case LY_STMT_DEVIATION:
3380 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3381 break;
3382 case LY_STMT_ENUM:
3383 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3384 break;
3385 case LY_STMT_ERROR_MESSAGE:
3386 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3387 break;
3388 case LY_STMT_EXTENSION:
3389 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3390 break;
3391 case LY_STMT_FEATURE:
3392 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3393 break;
3394 case LY_STMT_FRACTION_DIGITS:
3395 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3396 break;
3397 case LY_STMT_GROUPING:
3398 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3399 break;
3400 case LY_STMT_IDENTITY:
3401 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3402 break;
3403 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003404 ret = yin_parse_qname(ctx, kw, subelem, exts);
3405 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003406 case LY_STMT_UNITS:
3407 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3408 break;
3409 case LY_STMT_IMPORT:
3410 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3411 break;
3412 case LY_STMT_INCLUDE:
Radek Krejcieeee95c2021-01-19 10:57:22 +01003413 if ((current_element == LY_STMT_SUBMODULE) && (ctx->parsed_mod->version == LYS_VERSION_1_1)) {
3414 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
3415 ((struct lysp_submodule *)(ctx->parsed_mod))->name);
3416 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003417 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3418 break;
3419 case LY_STMT_INPUT:
3420 case LY_STMT_OUTPUT:
3421 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3422 break;
3423 case LY_STMT_LEAF:
3424 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3425 break;
3426 case LY_STMT_LEAF_LIST:
3427 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3428 break;
3429 case LY_STMT_LENGTH:
3430 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3431 break;
3432 case LY_STMT_LIST:
3433 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3434 break;
3435 case LY_STMT_MANDATORY:
3436 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3437 break;
3438 case LY_STMT_MAX_ELEMENTS:
3439 case LY_STMT_MIN_ELEMENTS:
3440 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3441 break;
3442 case LY_STMT_MODIFIER:
3443 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3444 break;
3445 case LY_STMT_MUST:
3446 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3447 break;
3448 case LY_STMT_NAMESPACE:
3449 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3450 break;
3451 case LY_STMT_NOTIFICATION:
3452 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3453 break;
3454 case LY_STMT_ORDERED_BY:
3455 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3456 break;
3457 case LY_STMT_PATH:
3458 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3459 break;
3460 case LY_STMT_PATTERN:
3461 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3462 break;
3463 case LY_STMT_VALUE:
3464 case LY_STMT_POSITION:
3465 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3466 break;
3467 case LY_STMT_PREFIX:
3468 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3469 break;
3470 case LY_STMT_RANGE:
3471 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3472 break;
3473 case LY_STMT_REFINE:
3474 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3475 break;
3476 case LY_STMT_REQUIRE_INSTANCE:
3477 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3478 break;
3479 case LY_STMT_REVISION:
3480 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3481 break;
3482 case LY_STMT_REVISION_DATE:
3483 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3484 break;
3485 case LY_STMT_STATUS:
3486 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3487 break;
3488 case LY_STMT_TYPE:
3489 ret = yin_parse_type(ctx, current_element, subelem);
3490 break;
3491 case LY_STMT_TYPEDEF:
3492 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3493 break;
3494 case LY_STMT_UNIQUE:
3495 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3496 break;
3497 case LY_STMT_USES:
3498 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3499 break;
3500 case LY_STMT_WHEN:
3501 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3502 break;
3503 case LY_STMT_YANG_VERSION:
3504 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3505 break;
3506 case LY_STMT_YIN_ELEMENT:
3507 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3508 break;
3509 case LY_STMT_ARG_TEXT:
3510 case LY_STMT_ARG_VALUE:
3511 /* TODO what to do with content/attributes? */
3512 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3513 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3514 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3515 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3516 }
3517 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3518 break;
3519 default:
3520 LOGINT(ctx->xmlctx->ctx);
3521 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003522 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003523 LY_CHECK_GOTO(ret, cleanup);
3524 subelem = NULL;
3525
3526 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003527 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003528 } else {
3529 LY_CHECK_RET(ret);
3530 /* elements with text or none content */
3531 /* save text content, if text_content isn't set, it's just ignored */
3532 /* no resources are allocated in this branch, no need to use cleanup label */
3533 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3534 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003535 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 +01003536 LY_CHECK_RET(!*text_content, LY_EMEM);
3537 }
3538
3539 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003540 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003541
David Sedlák8b754462019-07-25 16:22:13 +02003542 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3543 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003544
3545cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003546 return ret;
3547}
3548
David Sedlákaa98bba2019-09-12 11:52:14 +02003549/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003550 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003551 *
3552 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003553 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003554 *
3555 * @return LY_ERR values.
3556 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003557LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003558yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003559{
David Sedlák81497a32019-08-13 16:56:26 +02003560 LY_ERR ret = LY_SUCCESS;
3561 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003562 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003563 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003564
Michal Vaskoc3781c32020-10-06 14:04:08 +02003565 mod->is_submod = 0;
3566
Michal Vaskob36053d2020-03-26 15:49:30 +01003567 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3568 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 +01003569 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003570 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3571 LY_STMT_ANYXML, &mod->data, 0,
3572 LY_STMT_AUGMENT, &mod->augments, 0,
3573 LY_STMT_CHOICE, &mod->data, 0,
3574 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3575 LY_STMT_CONTAINER, &mod->data, 0,
3576 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3577 LY_STMT_DEVIATION, &mod->deviations, 0,
3578 LY_STMT_EXTENSION, &mod->extensions, 0,
3579 LY_STMT_FEATURE, &mod->features, 0,
3580 LY_STMT_GROUPING, &mod->groupings, 0,
3581 LY_STMT_IDENTITY, &mod->identities, 0,
3582 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3583 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3584 LY_STMT_LEAF, &mod->data, 0,
3585 LY_STMT_LEAF_LIST, &mod->data, 0,
3586 LY_STMT_LIST, &mod->data, 0,
3587 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3588 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3589 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3590 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3591 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3592 LY_STMT_REVISION, &mod->revs, 0,
3593 LY_STMT_RPC, &mod->rpcs, 0,
3594 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3595 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003596 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003597 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003598
Radek Krejcif13b87b2020-12-01 22:02:17 +01003599 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3600 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003601 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003602
David Sedláked809f12019-09-13 10:15:11 +02003603 /* submodules share the namespace with the module names, so there must not be
3604 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003605 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003606 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003607 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003608 return LY_EVALID;
3609 }
3610
3611 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003612}
3613
Michal Vaskoafac7822020-10-20 14:22:26 +02003614/**
3615 * @brief Parse submodule element.
3616 *
3617 * @param[in,out] ctx Yin parser context for logging and to store current state.
3618 * @param[in] mod_attrs Attributes of submodule element.
3619 * @param[out] submod Parsed submodule structure.
3620 *
3621 * @return LY_ERR values.
3622 */
David Sedlák3b4db242018-10-19 16:11:01 +02003623LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003624yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003625{
David Sedlák81497a32019-08-13 16:56:26 +02003626 LY_ERR ret = LY_SUCCESS;
3627 struct yin_subelement *subelems = NULL;
Michal Vasko8dc31992021-02-22 10:30:47 +01003628 const struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003629 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003630
Michal Vaskoc3781c32020-10-06 14:04:08 +02003631 submod->is_submod = 1;
3632
Michal Vaskob36053d2020-03-26 15:49:30 +01003633 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3634 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 +01003635 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003636 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3637 LY_STMT_ANYXML, &submod->data, 0,
3638 LY_STMT_AUGMENT, &submod->augments, 0,
3639 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3640 LY_STMT_CHOICE, &submod->data, 0,
3641 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3642 LY_STMT_CONTAINER, &submod->data, 0,
3643 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3644 LY_STMT_DEVIATION, &submod->deviations, 0,
3645 LY_STMT_EXTENSION, &submod->extensions, 0,
3646 LY_STMT_FEATURE, &submod->features, 0,
3647 LY_STMT_GROUPING, &submod->groupings, 0,
3648 LY_STMT_IDENTITY, &submod->identities, 0,
3649 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3650 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3651 LY_STMT_LEAF, &submod->data, 0,
3652 LY_STMT_LEAF_LIST, &submod->data, 0,
3653 LY_STMT_LIST, &submod->data, 0,
3654 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3655 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3656 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3657 LY_STMT_REVISION, &submod->revs, 0,
3658 LY_STMT_RPC, &submod->rpcs, 0,
3659 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3660 LY_STMT_USES, &submod->data, 0,
3661 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3662 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003663
Radek Krejcif13b87b2020-12-01 22:02:17 +01003664 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3665 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003666 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003667
David Sedláked809f12019-09-13 10:15:11 +02003668 /* submodules share the namespace with the module names, so there must not be
3669 * a submodule of the same name in the context, no need for revision matching */
Michal Vasko8dc31992021-02-22 10:30:47 +01003670 dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003671 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003672 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003673 return LY_EVALID;
3674 }
3675
3676 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003677}
3678
3679LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003680yin_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 +02003681 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003682{
Radek Krejcid6b76452019-09-03 17:03:03 +02003683 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003684 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003685 struct lysp_submodule *mod_p = NULL;
3686
3687 /* create context */
3688 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003689 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003690 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003691 (*yin_ctx)->unres = main_ctx->unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003692 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003693
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003694 mod_p = calloc(1, sizeof *mod_p);
3695 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3696 mod_p->mod = main_ctx->parsed_mod->mod;
3697 mod_p->parsing = 1;
3698 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3699
David Sedlák1b623122019-08-05 15:27:49 +02003700 /* map the typedefs and groupings list from main context to the submodule's context */
3701 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3702 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3703
David Sedlák8985a142019-07-31 16:43:06 +02003704 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003705 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 +02003706 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003707 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003708 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3709 ret = LY_EINVAL;
3710 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003711 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003712 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003713 ret = LY_EVALID;
3714 goto cleanup;
3715 }
3716
Michal Vaskob36053d2020-03-26 15:49:30 +01003717 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003718 LY_CHECK_GOTO(ret, cleanup);
3719
David Sedlákbf8a2b72019-08-14 16:48:10 +02003720 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003721 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003722 if (in->current[0] == '\n') {
3723 LY_IN_NEW_LINE(in);
3724 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003725 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003726 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003727 if (in->current[0]) {
3728 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003729 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003730 ret = LY_EVALID;
3731 goto cleanup;
3732 }
3733
David Sedlák8985a142019-07-31 16:43:06 +02003734 mod_p->parsing = 0;
3735 *submod = mod_p;
3736
3737cleanup:
3738 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003739 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003740 yin_parser_ctx_free(*yin_ctx);
3741 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003742 }
David Sedlák8985a142019-07-31 16:43:06 +02003743 return ret;
3744}
3745
3746LY_ERR
Michal Vasko405cc9e2020-12-01 12:01:27 +01003747yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
David Sedlák3b4db242018-10-19 16:11:01 +02003748{
David Sedláke4889912018-11-02 09:52:40 +01003749 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003750 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003751 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003752
David Sedlák8985a142019-07-31 16:43:06 +02003753 /* create context */
3754 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003755 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003756 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003757 (*yin_ctx)->unres = unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003758 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003759
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003760 mod_p = calloc(1, sizeof *mod_p);
3761 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3762 mod_p->mod = mod;
3763 mod_p->parsing = 1;
3764 (*yin_ctx)->parsed_mod = mod_p;
3765
David Sedlák8985a142019-07-31 16:43:06 +02003766 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003767 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 +02003768 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003769 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003770 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 +01003771 ret = LY_EINVAL;
3772 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003773 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003774 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003775 ret = LY_EVALID;
3776 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003777 }
3778
David Sedlák00250342019-06-21 14:19:39 +02003779 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003780 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003781 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003782
David Sedlákbf8a2b72019-08-14 16:48:10 +02003783 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003784 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003785 if (in->current[0] == '\n') {
3786 LY_IN_NEW_LINE(in);
3787 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003788 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003789 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003790 if (in->current[0]) {
3791 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003792 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003793 ret = LY_EVALID;
3794 goto cleanup;
3795 }
3796
David Sedlák3017da42019-02-15 09:48:04 +01003797 mod_p->parsing = 0;
3798 mod->parsed = mod_p;
3799
3800cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003801 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003802 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003803 yin_parser_ctx_free(*yin_ctx);
3804 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003805 }
David Sedlák2e411422018-12-17 02:35:39 +01003806 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003807}