blob: 87e32061def281096f56de4cfcd44f70a7b58f5f [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 */
David Sedlák3ffbc522019-07-02 17:49:28 +020014#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020015#include <ctype.h>
16#include <errno.h>
17#include <stdarg.h>
18#include <stdbool.h>
David Sedlák3b4db242018-10-19 16:11:01 +020019#include <stdio.h>
20#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020021#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020022
Radek Krejci535ea9f2020-05-29 16:01:05 +020023#include "common.h"
David Sedlákf824ad52018-10-14 23:58:15 +020024#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020025#include "dict.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020026#include "in_internal.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020027#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020028#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020029#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020030#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020031#include "tree.h"
32#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020033#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020034#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020035
David Sedlák2b214ac2019-06-06 16:11:03 +020036/**
37 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020038 *
David Sedlák2b214ac2019-06-06 16:11:03 +020039 * @param ns Namespace URI to check.
40 *
41 * @return true if ns equals YIN_NS_URI false otherwise.
42 */
43#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
44
Michal Vaskoafac7822020-10-20 14:22:26 +020045enum yin_argument {
46 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
47 YIN_ARG_NAME, /**< argument name */
48 YIN_ARG_TARGET_NODE, /**< argument target-node */
49 YIN_ARG_MODULE, /**< argument module */
50 YIN_ARG_VALUE, /**< argument value */
51 YIN_ARG_TEXT, /**< argument text */
52 YIN_ARG_CONDITION, /**< argument condition */
53 YIN_ARG_URI, /**< argument uri */
54 YIN_ARG_DATE, /**< argument data */
55 YIN_ARG_TAG, /**< argument tag */
56 YIN_ARG_NONE /**< empty (special value) */
57};
58
Michal Vasko22df3f02020-08-24 13:29:22 +020059const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020060 [YIN_ARG_NAME] = "name",
61 [YIN_ARG_TARGET_NODE] = "target-node",
62 [YIN_ARG_MODULE] = "module",
63 [YIN_ARG_VALUE] = "value",
64 [YIN_ARG_TEXT] = "text",
65 [YIN_ARG_CONDITION] = "condition",
66 [YIN_ARG_URI] = "uri",
67 [YIN_ARG_DATE] = "date",
68 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020069 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020070};
71
Michal Vaskoafac7822020-10-20 14:22:26 +020072#define yin_attr2str(STMT) yin_attr_list[STMT]
73
74#define VALID_VALS1 " Only valid value is \"%s\"."
75#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
76#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
77#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
78
79/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
80#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
81 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
82 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
83 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
84
85/* flags to set constraints of subelements */
86#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
87#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
88#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
89#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
90
91#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
92 time to simply check validity of given constraints */
93
94struct yin_subelement {
95 enum ly_stmt type; /**< type of keyword */
96 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
97 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 */
98};
99
100/* Meta information passed to yin_parse_argument function,
101 holds information about where content of argument element will be stored. */
102struct yin_argument_meta {
103 uint16_t *flags; /**< Argument flags */
104 const char **argument; /**< Argument value */
105};
106
107/**
108 * @brief Meta information passed to functions working with tree_schema,
109 * that require additional information about parent node.
110 */
111struct tree_node_meta {
112 struct lysp_node *parent; /**< parent node */
113 struct lysp_node **nodes; /**< linked list of siblings */
114};
115
116/**
117 * @brief Meta information passed to yin_parse_import function.
118 */
119struct import_meta {
120 const char *prefix; /**< module prefix. */
121 struct lysp_import **imports; /**< imports to add to. */
122};
123
124/**
125 * @brief Meta information passed to yin_parse_include function.
126 */
127struct include_meta {
128 const char *name; /**< Module/submodule name. */
129 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
130};
131
132/**
133 * @brief Meta information passed to yin_parse_inout function.
134 */
135struct inout_meta {
136 struct lysp_node *parent; /**< Parent node. */
137 struct lysp_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
138};
139
140/**
141 * @brief Meta information passed to yin_parse_minmax function.
142 */
143struct minmax_dev_meta {
144 uint32_t *lim; /**< min/max value to write to. */
145 uint16_t *flags; /**< min/max flags to write to. */
146 struct lysp_ext_instance **exts; /**< extension instances to add to. */
147};
148
149LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
150 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
151
152/**
153 * @brief Match yang keyword from yin data.
154 *
155 * @param[in,out] ctx Yin parser context for logging and to store current state.
156 * @param[in] name Start of keyword name
157 * @param[in] name_len Lenght of keyword name.
158 * @param[in] prefix Start of keyword prefix.
159 * @param[in] prefix_len Lenght of prefix.
160 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
161 *
162 * @return yang_keyword values.
163 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200164enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100165yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200166 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200167{
David Sedlák8f7a1172019-06-20 14:42:18 +0200168 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200169 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200170 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200171 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200172
Michal Vasko69730152020-10-09 16:30:07 +0200173 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200174 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200175 }
176
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200177 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200178 if (ns) {
179 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200180 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200181 }
182 } else {
183 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200184 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200185 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200186
Michal Vasko63f3d842020-07-08 10:10:14 +0200187 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
188 start = in->current;
189 kw = lysp_match_kw(NULL, in);
190 name = in->current;
191 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200192
193 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200194 /* 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 +0200195 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200196 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200197 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200198 return kw;
199 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200200 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200201 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200202 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200203 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200204 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200205 }
206}
207
Michal Vaskoafac7822020-10-20 14:22:26 +0200208/**
209 * @brief Match argument name.
210 *
211 * @param[in] name String representing name.
212 * @param[in] len Lenght of the name.
213 *
214 * @return yin_argument values.
215 */
David Sedlákc5b20842019-08-13 10:18:31 +0200216enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200217yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200218{
David Sedlákc5b20842019-08-13 10:18:31 +0200219 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200220 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200221
David Sedlák7ff55a92019-06-17 11:11:41 +0200222 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200223
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200224#define READ_INC(LEN) already_read += LEN
225#define ARG_SET(STMT) arg=STMT
226#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100227
David Sedlák1c8b2702019-02-22 11:03:02 +0100228 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100229 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200230 READ_INC(1);
231 if (ARG_CHECK("ondition", 8)) {
232 ARG_SET(YIN_ARG_CONDITION);
233 }
David Sedlák3b4db242018-10-19 16:11:01 +0200234 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200235
David Sedlák94de2aa2019-02-15 12:42:11 +0100236 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200237 READ_INC(1);
238 if (ARG_CHECK("ate", 3)) {
239 ARG_SET(YIN_ARG_DATE);
240 }
David Sedlák3b4db242018-10-19 16:11:01 +0200241 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200242
David Sedlák94de2aa2019-02-15 12:42:11 +0100243 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200244 READ_INC(1);
245 if (ARG_CHECK("odule", 5)) {
246 ARG_SET(YIN_ARG_MODULE);
247 }
David Sedlák872c7b42018-10-26 13:15:20 +0200248 break;
249
David Sedlák94de2aa2019-02-15 12:42:11 +0100250 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200251 READ_INC(1);
252 if (ARG_CHECK("ame", 3)) {
253 ARG_SET(YIN_ARG_NAME);
254 }
David Sedlák872c7b42018-10-26 13:15:20 +0200255 break;
256
David Sedlák94de2aa2019-02-15 12:42:11 +0100257 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200258 READ_INC(1);
259 if (ARG_CHECK("a", 1)) {
260 if (ARG_CHECK("g", 1)) {
261 ARG_SET(YIN_ARG_TAG);
262 } else if (ARG_CHECK("rget-node", 9)) {
263 ARG_SET(YIN_ARG_TARGET_NODE);
264 }
265 } else if (ARG_CHECK("ext", 3)) {
266 ARG_SET(YIN_ARG_TEXT);
267 }
David Sedlák3b4db242018-10-19 16:11:01 +0200268 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200269
David Sedlák94de2aa2019-02-15 12:42:11 +0100270 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200271 READ_INC(1);
272 if (ARG_CHECK("ri", 2)) {
273 ARG_SET(YIN_ARG_URI);
274 }
David Sedlák3b4db242018-10-19 16:11:01 +0200275 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200276
David Sedlák94de2aa2019-02-15 12:42:11 +0100277 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200278 READ_INC(1);
279 if (ARG_CHECK("alue", 4)) {
280 ARG_SET(YIN_ARG_VALUE);
281 }
David Sedlák3b4db242018-10-19 16:11:01 +0200282 break;
283 }
284
David Sedlákc10e7902018-12-17 02:17:59 +0100285 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200286 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200287 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200288 }
289
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200290#undef ARG_CHECK
291#undef ARG_SET
292#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100293
David Sedlák872c7b42018-10-26 13:15:20 +0200294 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200295}
296
Radek Krejcid6b76452019-09-03 17:03:03 +0200297#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
298 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
299 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
300 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200301
Radek Krejcid6b76452019-09-03 17:03:03 +0200302#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 +0200303
David Sedlák26ea1432019-08-14 13:42:23 +0200304/**
305 * @brief Free subelems information allocated on heap.
306 *
307 * @param[in] count Size of subelems array.
308 * @param[in] subelems Subelems array to free.
309 */
David Sedlák81497a32019-08-13 16:56:26 +0200310static void
311subelems_deallocator(size_t count, struct yin_subelement *subelems)
312{
Michal Vaskod989ba02020-08-24 10:59:24 +0200313 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200314 if (HAS_META(subelems[i].type)) {
315 free(subelems[i].dest);
316 }
317 }
318
319 free(subelems);
320}
321
David Sedlák26ea1432019-08-14 13:42:23 +0200322/**
323 * @brief Allocate subelems information on heap.
324 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200325 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200326 * @param[in] count Number of subelements.
327 * @param[in] parent Parent node if any.
328 * @param[out] result Allocated subelems array.
329 *
330 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
331 */
David Sedlák81497a32019-08-13 16:56:26 +0200332static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100333subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200334 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200335{
336 va_list ap;
337
338 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200339 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200340
341 va_start(ap, result);
342 for (size_t i = 0; i < count; ++i) {
343 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200344 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200345 /* DEST */
346 if (IS_NODE_ELEM((*result)[i].type)) {
347 struct tree_node_meta *node_meta = NULL;
348 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200349 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200350 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200351 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200352 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200353 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200354 struct import_meta *imp_meta = NULL;
355 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200356 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200357 imp_meta->prefix = va_arg(ap, const char *);
358 imp_meta->imports = va_arg(ap, struct lysp_import **);
359 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200360 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200361 struct include_meta *inc_meta = NULL;
362 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200363 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200364 inc_meta->name = va_arg(ap, const char *);
365 inc_meta->includes = va_arg(ap, struct lysp_include **);
366 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200367 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200368 struct inout_meta *inout_meta = NULL;
369 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200370 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200371 inout_meta->parent = parent;
372 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
373 (*result)[i].dest = inout_meta;
374 } else {
375 (*result)[i].dest = va_arg(ap, void *);
376 }
377 /* FLAGS */
378 (*result)[i].flags = va_arg(ap, int);
379 }
380 va_end(ap);
381
382 return LY_SUCCESS;
383
David Sedlákbf8a2b72019-08-14 16:48:10 +0200384mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200385 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100386 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200387 return LY_EMEM;
388}
389
Michal Vaskoafac7822020-10-20 14:22:26 +0200390/**
391 * @brief Check that val is valid UTF8 character sequence of val_type.
392 * Doesn't check empty string, only character validity.
393 *
394 * @param[in] ctx Yin parser context for logging.
395 * @param[in] val_type Type of the input string to select method of checking character validity.
396 *
397 * @return LY_ERR values.
398 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200399LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100400yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200401{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200402 uint8_t prefix = 0;
403 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100404 size_t utf8_char_len, already_read = 0;
405 const char *val;
406
407 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
408
409 val = ctx->xmlctx->value;
410 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200411 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200412 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200413 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100414 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200415
416 switch (val_type) {
417 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200418 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 +0200419 break;
420 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200421 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 +0200422 break;
423 case Y_STR_ARG:
424 case Y_MAYBE_STR_ARG:
425 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
426 break;
427 }
428 }
429
430 return LY_SUCCESS;
431}
432
David Sedlákb4e44562019-07-04 15:42:12 +0200433/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100434 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200435 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200436 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200437 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
438 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200439 * @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 +0200440 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200441 * @param[in] current_element Identification of current element, used for logging.
442 *
443 * @return LY_ERR values.
444 */
445static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100446yin_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 +0200447 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200448{
David Sedlákc5b20842019-08-13 10:18:31 +0200449 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200450 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200451
David Sedlák1bccdfa2019-06-17 15:55:27 +0200452 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100453 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200454 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100455 if (!ctx->xmlctx->prefix) {
456 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200457 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100458 /* skip it */
459 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200460 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200461 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200462 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200463 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100464
465 /* go to value */
466 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
467 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200468 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 +0200469 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200470 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100471 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200472 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200473 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200474 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100475 } else {
476 /* skip it */
477 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200478 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100479
480 /* next attribute */
481 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200482 }
483
David Sedlák292763b2019-07-09 11:10:53 +0200484 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200485 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100486 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200487 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200488 return LY_EVALID;
489 }
490
491 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200492}
493
David Sedlákd6e56892019-07-01 15:40:24 +0200494/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200495 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200496 *
497 * @param[in] type Type of wanted record.
498 * @param[in] array_size Size of array.
499 * @param[in] array Searched array.
500 *
501 * @return Pointer to desired record on success, NULL if element is not in the array.
502 */
David Sedlákb4e44562019-07-04 15:42:12 +0200503static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200504get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200505{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200506 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200507 if (array[u].type == type) {
508 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200509 }
510 }
David Sedlákd6e56892019-07-01 15:40:24 +0200511 return NULL;
512}
513
David Sedlákbba38e52019-07-09 15:20:01 +0200514/**
515 * @brief Helper function to check mandatory constraint of subelement.
516 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200517 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200518 * @param[in] subelem_info Array of information about subelements.
519 * @param[in] subelem_info_size Size of subelem_info array.
520 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
521 *
522 * @return LY_ERR values.
523 */
524static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100525yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200526 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200527{
David Sedlákb0faad82019-07-04 14:28:59 +0200528 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200529 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200530 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200531 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200532 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200533 return LY_EVALID;
534 }
535 }
536
537 return LY_SUCCESS;
538}
539
David Sedlákbba38e52019-07-09 15:20:01 +0200540/**
541 * @brief Helper function to check "first" constraint of subelement.
542 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200543 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200544 * @param[in] subelem_info Array of information about subelements.
545 * @param[in] subelem_info_size Size of subelem_info array.
546 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200547 * @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 +0200548 *
549 * @return LY_ERR values.
550 */
551static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100552yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200553 signed char subelem_info_size, enum ly_stmt current_element,
554 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200555{
David Sedlákb0faad82019-07-04 14:28:59 +0200556 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200557 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200558 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200559 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200560 return LY_EVALID;
561 }
562 }
563
564 return LY_SUCCESS;
565}
566
David Sedlákbba38e52019-07-09 15:20:01 +0200567/**
David Sedlákb4e44562019-07-04 15:42:12 +0200568 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
569 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200570 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200571 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200572 * @param[in] kw Type of current element.
573 * @param[out] value Where value of attribute should be stored.
574 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200575 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200576 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200577 * @return LY_ERR values.
578 */
David Sedlákb4e44562019-07-04 15:42:12 +0200579static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100580yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200581 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200582{
Michal Vaskob36053d2020-03-26 15:49:30 +0100583 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
584 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200585 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200586 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
587 };
David Sedlákb4e44562019-07-04 15:42:12 +0200588
Michal Vaskob36053d2020-03-26 15:49:30 +0100589 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200590}
591
592/**
David Sedlák6542aed2019-08-14 10:47:43 +0200593 * @brief Parse path element.
594 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200595 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200596 * @param[in] kw Type of current element.
597 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200598 * @return LY_ERR values.
599 */
600static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100601yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200602{
Michal Vasko004d3152020-06-11 19:59:22 +0200603 LY_ERR ret;
604 const char *str_path;
605
606 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 +0200607 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 +0200608 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200609 lydict_remove(ctx->xmlctx->ctx, str_path);
610 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200611 type->flags |= LYS_SET_PATH;
612
613 return LY_SUCCESS;
614}
615
616/**
David Sedlákd3983112019-07-12 11:20:56 +0200617 * @brief Parse pattern element.
618 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200619 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200620 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200621 * @return LY_ERR values.
622 */
623static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100624yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200625{
626 const char *real_value = NULL;
627 char *saved_value = NULL;
628 struct lysp_restr *restr;
629
Michal Vaskob36053d2020-03-26 15:49:30 +0100630 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
631 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
632 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 +0200633 size_t len = strlen(real_value);
634
635 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100636 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200637 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100638 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200639 saved_value[0] = 0x06;
640 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200641 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200642 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200643 type->flags |= LYS_SET_PATTERN;
644
645 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200646 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
647 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
648 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
649 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
650 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
651 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
652 };
Michal Vasko69730152020-10-09 16:30:07 +0200653
Michal Vaskob36053d2020-03-26 15:49:30 +0100654 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200655}
656
David Sedlákc5b20842019-08-13 10:18:31 +0200657/**
658 * @brief Parse fraction-digits element.
659 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200660 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200661 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200662 * @return LY_ERR values.
663 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200664static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100665yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200666{
667 const char *temp_val = NULL;
668 char *ptr;
669 unsigned long int num;
670
Michal Vaskob36053d2020-03-26 15:49:30 +0100671 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
672 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 +0200673
Michal Vasko69730152020-10-09 16:30:07 +0200674 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200675 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100676 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200677 return LY_EVALID;
678 }
679
680 errno = 0;
681 num = strtoul(temp_val, &ptr, 10);
682 if (*ptr != '\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 Vaskob36053d2020-03-26 15:49:30 +0100684 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200685 return LY_EVALID;
686 }
687 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200688 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100689 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200690 return LY_EVALID;
691 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100692 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200693 type->fraction_digits = num;
694 type->flags |= LYS_SET_FRDIGITS;
695 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200696 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
697 };
Michal Vasko69730152020-10-09 16:30:07 +0200698
Michal Vaskob36053d2020-03-26 15:49:30 +0100699 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200700}
701
David Sedlák07869a52019-07-12 14:28:19 +0200702/**
David Sedlák43801c92019-08-05 15:58:54 +0200703 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200704 *
705 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200706 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200707 * @return LY_ERR values.
708 */
David Sedlákca36c422019-07-12 12:47:55 +0200709static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100710yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200711{
David Sedlák07869a52019-07-12 14:28:19 +0200712 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200713
Michal Vaskob36053d2020-03-26 15:49:30 +0100714 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200715 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100716 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
717 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 +0200718 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100719 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200720 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200721
722 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200723 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
724 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
725 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
726 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
727 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
728 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
729 };
Michal Vasko69730152020-10-09 16:30:07 +0200730
Michal Vaskob36053d2020-03-26 15:49:30 +0100731 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200732}
733
734/**
735 * @brief Parse bit element.
736 *
737 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200738 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200739 * @return LY_ERR values.
740 */
741static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100742yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200743{
744 struct lysp_type_enum *en;
745
Michal Vaskob36053d2020-03-26 15:49:30 +0100746 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200747 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100748 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
749 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 +0200750 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
751
752 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200753 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
754 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
755 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
756 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
757 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
758 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
759 };
Michal Vasko69730152020-10-09 16:30:07 +0200760
Michal Vaskob36053d2020-03-26 15:49:30 +0100761 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200762}
763
David Sedlákd3983112019-07-12 11:20:56 +0200764/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200765 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
766 * more instances, such as base or if-feature.
767 *
768 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200769 * @param[in] kw Type of current element.
770 * @param[out] values Parsed values to add to.
771 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200772 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200773 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200774 * @return LY_ERR values.
775 */
776static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100777yin_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 +0200778 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200779{
780 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200781
Michal Vaskob36053d2020-03-26 15:49:30 +0100782 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200783 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200784 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200785 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
786 };
David Sedlák968ac342019-07-11 15:17:59 +0200787
Michal Vaskob36053d2020-03-26 15:49:30 +0100788 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
789 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200790
Michal Vaskob36053d2020-03-26 15:49:30 +0100791 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200792}
793
794/**
David Sedlák6542aed2019-08-14 10:47:43 +0200795 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
796 *
797 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200798 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200799 * @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 +0200800 * @param[in] arg_type Expected type of attribute.
801 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200802 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200803 * @return LY_ERR values.
804 */
805static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100806yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200807 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200808{
809 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100810 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200811 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200812 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100813 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200814 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200815 }
816
817 return LY_SUCCESS;
818}
819
820/**
821 * @brief Parse base element.
822 *
823 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200824 * @param[in] parent Identification of parent element.
825 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200826 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200827 * @return LY_ERR values.
828 */
829static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100830yin_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 +0200831{
832 struct lysp_type *type = NULL;
833
Radek Krejcid6b76452019-09-03 17:03:03 +0200834 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200835 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100836 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200837 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200838 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200839 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100840 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200841 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200842 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100843 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200844 return LY_EINT;
845 }
846
847 return LY_SUCCESS;
848}
849
850/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200851 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200852 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200853 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100854 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200855 * @return LY_ERR values.
856 */
857static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100858yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200859{
860 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200861 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200862 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
863 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200864
865 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100866 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
867 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 +0200868 if (strcmp(temp_val, "true") == 0) {
869 type->require_instance = 1;
870 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200871 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200872 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100873 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200874 return LY_EVALID;
875 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100876 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200877
Michal Vaskob36053d2020-03-26 15:49:30 +0100878 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200879}
880
881/**
David Sedlákce77bf52019-07-11 16:59:31 +0200882 * @brief Parse modifier element.
883 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200884 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200885 * @param[in,out] pat Value to write to.
886 * @param[in,out] exts Extension instances to add to.
887 *
888 * @return LY_ERR values.
889 */
890static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100891yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200892{
David Sedlákd3983112019-07-12 11:20:56 +0200893 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200894 const char *temp_val;
895 char *modified_val;
896 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200897 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
898 };
David Sedlákce77bf52019-07-11 16:59:31 +0200899
Michal Vaskob36053d2020-03-26 15:49:30 +0100900 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
901 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 +0200902 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200903 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200904 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100905 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200906 return LY_EVALID;
907 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100908 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200909
910 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200911 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100912 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200913 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100914 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200915
916 /* modify the new value */
917 modified_val[0] = 0x15;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200918 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200919
Michal Vaskob36053d2020-03-26 15:49:30 +0100920 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200921}
922
923/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200924 * @brief Parse a restriction element (length, range or one instance of must).
925 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200926 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200927 * @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 +0200928 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200929 */
930static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100931yin_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 +0200932{
Radek Krejcid6b76452019-09-03 17:03:03 +0200933 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200934 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200935 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
936 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
937 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
938 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
939 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
940 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200941 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200942 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200943
Michal Vaskob36053d2020-03-26 15:49:30 +0100944 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200945 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200946 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100947
948 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200949}
950
951/**
David Sedlák6542aed2019-08-14 10:47:43 +0200952 * @brief Parse range element.
953 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200954 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200955 * @param[out] type Type structure to store parsed value and flags.
956 *
957 * @return LY_ERR values.
958 */
959static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100960yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200961{
962 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100963 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
964 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200965 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200966
967 return LY_SUCCESS;
968}
969
970/**
971 * @brief Parse length element.
972 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200973 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200974 * @param[out] type Type structure to store parsed value and flags.
975 *
976 * @return LY_ERR values.
977 */
978static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100979yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200980{
981 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100982 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
983 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200984 type->flags |= LYS_SET_LENGTH;
985
986 return LY_SUCCESS;
987}
988
989/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200990 * @brief Parse must element.
991 *
992 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200993 * @param[in,out] restrs Restrictions to add to.
994 *
995 * @return LY_ERR values.
996 */
997static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100998yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200999{
1000 struct lysp_restr *restr;
1001
Michal Vaskob36053d2020-03-26 15:49:30 +01001002 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1003 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001004}
1005
1006/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001007 * @brief Parse a node id into an array.
1008 *
1009 * @param[in,out] ctx YIN parser context for logging and to store current state.
1010 * @param[in] kw Type of current element.
1011 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1012 * @param[in,out] exts Extension instances to add to.
1013 *
1014 * @return LY_ERR values.
1015 */
1016static LY_ERR
1017yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1018 struct lysp_ext_instance **exts)
1019{
1020 struct lysp_qname *qname, **qnames;
1021
1022 switch (kw) {
1023 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001024 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1025 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001026 } else {
1027 qnames = (struct lysp_qname **)subinfo->dest;
1028 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001029 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001030 qname->mod = ctx->parsed_mod;
1031 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
1032 case LY_STMT_IF_FEATURE:
1033 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1034 qnames = (struct lysp_qname **)subinfo->dest;
1035 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1036 qname->mod = ctx->parsed_mod;
1037 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001038 default:
1039 break;
1040 }
1041
1042 LOGINT(ctx->xmlctx->ctx);
1043 return LY_EINT;
1044}
1045
1046/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001047 * @brief Parse position or value element.
1048 *
1049 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001050 * @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 +02001051 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001052 *
1053 * @return LY_ERR values.
1054 */
1055static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001056yin_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 +02001057{
Radek Krejcid6b76452019-09-03 17:03:03 +02001058 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001059 const char *temp_val = NULL;
1060 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +02001061 long int num = 0;
1062 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001063
1064 /* set value flag */
1065 enm->flags |= LYS_SET_VALUE;
1066
1067 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001068 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1069 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001070 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001071 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001072 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 +02001073 goto error;
1074 }
1075
1076 /* convert value */
1077 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001078 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001079 num = strtol(temp_val, &ptr, 10);
Michal Vasko69730152020-10-09 16:30:07 +02001080 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001081 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 +02001082 goto error;
1083 }
1084 } else {
1085 unum = strtoul(temp_val, &ptr, 10);
1086 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001087 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 +02001088 goto error;
1089 }
1090 }
1091 /* check if whole argument value was converted */
1092 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001093 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 +02001094 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001095 }
1096 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001097 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 +02001098 goto error;
1099 }
1100 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001101 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001102 enm->value = num;
1103 } else {
1104 enm->value = unum;
1105 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001106 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001107
1108 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +02001109 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001110 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1111 };
Michal Vasko69730152020-10-09 16:30:07 +02001112
Michal Vaskob36053d2020-03-26 15:49:30 +01001113 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001114
David Sedlákbf8a2b72019-08-14 16:48:10 +02001115error:
Michal Vaskob36053d2020-03-26 15:49:30 +01001116 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1117 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001118}
1119
David Sedlák05404f62019-07-24 14:11:53 +02001120/**
1121 * @brief Parse belongs-to element.
1122 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001123 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001124 * @param[out] submod Structure of submodule that is being parsed.
1125 * @param[in,out] exts Extension instances to add to.
1126 *
1127 * @return LY_ERR values
1128 */
1129static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001130yin_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 +02001131{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001132 const char *belongsto;
David Sedlák05404f62019-07-24 14:11:53 +02001133 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001134 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1135 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1136 };
David Sedlák05404f62019-07-24 14:11:53 +02001137
Michal Vaskob36053d2020-03-26 15:49:30 +01001138 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001139 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 +02001140 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001141 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 +02001142 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001143 lydict_remove(ctx->xmlctx->ctx, belongsto);
1144 return LY_EVALID;
1145 }
1146 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001147
1148 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001149}
1150
David Sedlák5545f5d2019-07-11 11:55:16 +02001151/**
David Sedlákc1771b12019-07-10 15:55:46 +02001152 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001153 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001154 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001155 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001156 * @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 +02001157 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001158 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001159 *
1160 * @return LY_ERR values.
1161 */
1162static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001163yin_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 +02001164{
Radek Krejcid6b76452019-09-03 17:03:03 +02001165 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 +02001166
David Sedlák968ac342019-07-11 15:17:59 +02001167 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001168 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1169 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1170 };
Michal Vasko69730152020-10-09 16:30:07 +02001171
David Sedlákdf2a9732019-08-07 13:23:16 +02001172 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001173 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1174 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 +02001175
David Sedlákdf2a9732019-08-07 13:23:16 +02001176 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +01001177 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001178}
1179
1180/**
David Sedlákc1771b12019-07-10 15:55:46 +02001181 * @brief Parse error-message element.
1182 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001183 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001184 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001185 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001186 *
1187 * @return LY_ERR values.
1188 */
1189static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001190yin_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 +02001191{
David Sedlák968ac342019-07-11 15:17:59 +02001192 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001193 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1194 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1195 };
David Sedlákc1771b12019-07-10 15:55:46 +02001196
David Sedlákdf2a9732019-08-07 13:23:16 +02001197 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001198 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1199 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 +02001200
Michal Vaskob36053d2020-03-26 15:49:30 +01001201 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001202}
1203
1204/**
David Sedlák6542aed2019-08-14 10:47:43 +02001205 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001206 *
1207 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001208 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001209 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001210 *
1211 * @return LY_ERR values.
1212 */
1213static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001214yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001215{
David Sedlák6542aed2019-08-14 10:47:43 +02001216 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001217
Radek Krejcid6b76452019-09-03 17:03:03 +02001218 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001219 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001220 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001221 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001222 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001223 type = (struct lysp_type *)subinfo->dest;
1224 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001225
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001226 type->pmod = ctx->parsed_mod;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001227
David Sedlák6542aed2019-08-14 10:47:43 +02001228 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001229 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001230 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001231 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001232 type->flags |= LYS_SET_TYPE;
1233 type = nested_type;
1234 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001235
David Sedlák374d2b32019-07-17 15:06:55 +02001236 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001237 {LY_STMT_BASE, type, 0},
1238 {LY_STMT_BIT, type, 0},
1239 {LY_STMT_ENUM, type, 0},
1240 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1241 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1242 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1243 {LY_STMT_PATTERN, type, 0},
1244 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1245 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1246 {LY_STMT_TYPE, type},
1247 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1248 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001249
1250 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1251 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1252 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001253}
1254
David Sedlák1af868e2019-07-17 17:03:14 +02001255/**
1256 * @brief Parse max-elements element.
1257 *
1258 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001259 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001260 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001261 * @param[in,out] exts Extension instances to add to.
1262 *
1263 * @return LY_ERR values.
1264 */
1265static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001266yin_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 +02001267{
1268 const char *temp_val = NULL;
1269 char *ptr;
1270 unsigned long int num;
1271 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001272 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1273 };
David Sedlák374d2b32019-07-17 15:06:55 +02001274
David Sedlák1af868e2019-07-17 17:03:14 +02001275 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001276 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1277 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 +02001278 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 +02001279 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001280 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001281 return LY_EVALID;
1282 }
1283
1284 if (strcmp(temp_val, "unbounded")) {
1285 errno = 0;
1286 num = strtoul(temp_val, &ptr, 10);
1287 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001288 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001289 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001290 return LY_EVALID;
1291 }
1292 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001293 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001294 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001295 return LY_EVALID;
1296 }
1297 *max = num;
1298 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001299 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1300 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001301}
David Sedlák374d2b32019-07-17 15:06:55 +02001302
1303/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001304 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001305 *
1306 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001307 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001308 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001309 * @param[in,out] exts Extension instances to add to.
1310 *
1311 * @return LY_ERR values.
1312 */
1313static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001314yin_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 +02001315{
1316 const char *temp_val = NULL;
1317 char *ptr;
1318 unsigned long int num;
1319 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001320 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1321 };
David Sedlák09e18c92019-07-18 11:17:11 +02001322
1323 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001324 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1325 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 +02001326
Michal Vasko69730152020-10-09 16:30:07 +02001327 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001328 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001329 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001330 return LY_EVALID;
1331 }
1332
1333 errno = 0;
1334 num = strtoul(temp_val, &ptr, 10);
1335 if (ptr[0] != 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 Vaskob36053d2020-03-26 15:49:30 +01001337 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001338 return LY_EVALID;
1339 }
Michal Vasko69730152020-10-09 16:30:07 +02001340 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001341 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001342 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001343 return LY_EVALID;
1344 }
1345 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001346 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1347 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001348}
1349
David Sedláka2dad212019-07-18 12:45:19 +02001350/**
1351 * @brief Parse min-elements or max-elements element.
1352 *
1353 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001354 * @param[in] parent Identification of parent element.
1355 * @param[in] current Identification of current element.
1356 * @param[in] dest Where the parsed value and flags should be stored.
1357 *
1358 * @return LY_ERR values.
1359 */
David Sedlák09e18c92019-07-18 11:17:11 +02001360static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001361yin_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 +02001362{
Radek Krejcid6b76452019-09-03 17:03:03 +02001363 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1364 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 +02001365 uint32_t *lim;
1366 uint16_t *flags;
1367 struct lysp_ext_instance **exts;
1368
Radek Krejcid6b76452019-09-03 17:03:03 +02001369 if (parent == LY_STMT_LEAF_LIST) {
1370 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 +02001371 flags = &((struct lysp_node_leaflist *)dest)->flags;
1372 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001373 } else if (parent == LY_STMT_REFINE) {
1374 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001375 flags = &((struct lysp_refine *)dest)->flags;
1376 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001377 } else if (parent == LY_STMT_LIST) {
1378 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 +02001379 flags = &((struct lysp_node_list *)dest)->flags;
1380 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001381 } else {
1382 lim = ((struct minmax_dev_meta *)dest)->lim;
1383 flags = ((struct minmax_dev_meta *)dest)->flags;
1384 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001385 }
1386
Radek Krejcid6b76452019-09-03 17:03:03 +02001387 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001388 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001389 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001390 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001391 }
1392
1393 return LY_SUCCESS;
1394}
1395
1396/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001397 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001398 *
1399 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001400 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001401 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001402 *
1403 * @return LY_ERR values.
1404 */
1405static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001406yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001407{
1408 const char *temp_val;
1409 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001410 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1411 };
David Sedláka2dad212019-07-18 12:45:19 +02001412
Michal Vaskob36053d2020-03-26 15:49:30 +01001413 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1414 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
David Sedláka2dad212019-07-18 12:45:19 +02001415 if (strcmp(temp_val, "system") == 0) {
1416 *flags |= LYS_ORDBY_SYSTEM;
1417 } else if (strcmp(temp_val, "user") == 0) {
1418 *flags |= LYS_ORDBY_USER;
1419 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001420 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001421 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001422 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001423 return LY_EVALID;
1424 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001425 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001426
Michal Vaskob36053d2020-03-26 15:49:30 +01001427 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001428}
1429
1430/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001431 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001432 *
1433 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001434 * @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 +02001435 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001436 *
1437 * @return LY_ERR values.
1438 */
1439static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001440yin_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 +02001441{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001442 struct lysp_node_anydata *any;
1443
David Sedlák8d552d62019-08-06 15:29:05 +02001444 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001445 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001446 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001447 any->parent = node_meta->parent;
1448
David Sedlákbf8a2b72019-08-14 16:48:10 +02001449 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001450 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1451 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 +02001452
1453 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001454 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1455 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1456 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1457 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1458 {LY_STMT_MUST, &any->musts, 0},
1459 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1460 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1461 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1462 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1463 };
Michal Vasko69730152020-10-09 16:30:07 +02001464
Michal Vaskob36053d2020-03-26 15:49:30 +01001465 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001466}
1467
1468/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001469 * @brief parse leaf element.
1470 *
1471 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001472 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001473 *
1474 * @return LY_ERR values.
1475 */
1476static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001477yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001478{
David Sedlák203ca3a2019-07-18 15:26:25 +02001479 struct lysp_node_leaf *leaf;
1480
David Sedlák8d552d62019-08-06 15:29:05 +02001481 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001482 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001483 leaf->nodetype = LYS_LEAF;
1484 leaf->parent = node_meta->parent;
1485
David Sedlák203ca3a2019-07-18 15:26:25 +02001486 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001487 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1488 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 +02001489
1490 /* parse content */
1491 struct yin_subelement subelems[12] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001492 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1493 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1494 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1495 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1496 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1497 {LY_STMT_MUST, &leaf->musts, 0},
1498 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1499 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1500 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1501 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1502 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1503 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1504 };
Michal Vasko69730152020-10-09 16:30:07 +02001505
Michal Vaskob36053d2020-03-26 15:49:30 +01001506 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001507}
1508
1509/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001510 * @brief Parse leaf-list element.
1511 *
1512 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001513 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001514 *
1515 * @return LY_ERR values.
1516 */
1517static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001518yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001519{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001520 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001521
Michal Vaskob36053d2020-03-26 15:49:30 +01001522 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001523
David Sedlákc3da3ef2019-07-19 12:56:08 +02001524 llist->nodetype = LYS_LEAFLIST;
1525 llist->parent = node_meta->parent;
1526
David Sedlákc3da3ef2019-07-19 12:56:08 +02001527 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001528 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1529 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 +02001530
1531 /* parse content */
1532 struct yin_subelement subelems[14] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001533 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1534 {LY_STMT_DEFAULT, &llist->dflts, 0},
1535 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1536 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1537 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1538 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1539 {LY_STMT_MUST, &llist->musts, 0},
1540 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1541 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1542 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1543 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1544 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1545 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1546 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1547 };
Michal Vasko69730152020-10-09 16:30:07 +02001548
Michal Vaskob36053d2020-03-26 15:49:30 +01001549 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001550
David Sedlákbf8a2b72019-08-14 16:48:10 +02001551 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001552 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001553 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001554 return LY_EVALID;
1555 }
Michal Vasko69730152020-10-09 16:30:07 +02001556 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001557 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001558 return LY_EVALID;
1559 }
1560
1561 return LY_SUCCESS;
1562}
1563
1564/**
David Sedlák04e17b22019-07-19 15:29:48 +02001565 * @brief Parse typedef element.
1566 *
1567 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001568 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001569 *
1570 * @return LY_ERR values.
1571 */
1572static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001573yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001574{
1575 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001576 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001577
Michal Vaskob36053d2020-03-26 15:49:30 +01001578 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001579
1580 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001581 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1582 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 +02001583
1584 /* parse content */
1585 struct yin_subelement subelems[7] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001586 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1587 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1588 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1589 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1590 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1591 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1592 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1593 };
Michal Vasko69730152020-10-09 16:30:07 +02001594
Michal Vaskob36053d2020-03-26 15:49:30 +01001595 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001596
1597 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001598 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1599 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001600 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001601 }
1602
1603 return LY_SUCCESS;
1604}
1605
1606/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001607 * @brief Parse refine element.
1608 *
1609 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001610 * @param[in,out] refines Refines to add to.
1611 *
1612 * @return LY_ERR values.
1613 */
1614static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001615yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001616{
1617 struct lysp_refine *rf;
1618
1619 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001620 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001621
1622 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001623 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1624 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1625 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001626
1627 /* parse content */
1628 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001629 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001630 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001631 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001632 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001633 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1634 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1635 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1636 {LY_STMT_MUST, &rf->musts, 0},
1637 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1638 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1639 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1640 };
Michal Vasko69730152020-10-09 16:30:07 +02001641
Michal Vaskob36053d2020-03-26 15:49:30 +01001642 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001643}
1644
1645/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001646 * @brief Parse uses element.
1647 *
1648 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001649 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001650 *
1651 * @return LY_ERR values.
1652 */
1653static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001654yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001655{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001656 struct lysp_node_uses *uses;
1657
David Sedlák8d552d62019-08-06 15:29:05 +02001658 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001659 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001660 uses->nodetype = LYS_USES;
1661 uses->parent = node_meta->parent;
1662
David Sedlák0d6de5a2019-07-22 13:25:44 +02001663 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001664 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1665 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 +02001666
1667 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001668 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001669 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001670 {LY_STMT_AUGMENT, &augments, 0},
1671 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1672 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1673 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1674 {LY_STMT_REFINE, &uses->refines, 0},
1675 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1676 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1677 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1678 };
Michal Vasko69730152020-10-09 16:30:07 +02001679
Michal Vaskob36053d2020-03-26 15:49:30 +01001680 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001681 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1682
1683 return LY_SUCCESS;
1684}
1685
1686/**
David Sedlákaa854b02019-07-22 14:17:10 +02001687 * @brief Parse revision element.
1688 *
1689 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001690 * @param[in,out] revs Parsed revisions to add to.
1691 *
1692 * @return LY_ERR values.
1693 */
1694static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001695yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001696{
1697 struct lysp_revision *rev;
1698 const char *temp_date = NULL;
1699
1700 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001701 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001702
1703 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001704 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1705 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 +02001706 /* check value */
1707 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001708 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001709 return LY_EVALID;
1710 }
1711 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001712 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001713
1714 /* parse content */
1715 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001716 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1717 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1718 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1719 };
Michal Vasko69730152020-10-09 16:30:07 +02001720
Michal Vaskob36053d2020-03-26 15:49:30 +01001721 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001722}
1723
David Sedlák5e13dea2019-07-22 16:06:45 +02001724/**
1725 * @brief Parse include element.
1726 *
1727 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001728 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1729 *
1730 * @return LY_ERR values.
1731 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001732static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001733yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001734{
1735 struct lysp_include *inc;
1736
1737 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001738 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001739
1740 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001741 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1742 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 +02001743
1744 /* submodules share the namespace with the module names, so there must not be
1745 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001746 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
David Sedlák1538a842019-08-08 15:38:51 +02001747 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001748 return LY_EVALID;
1749 }
1750
1751 /* parse content */
1752 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001753 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1754 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1755 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1756 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1757 };
Michal Vasko69730152020-10-09 16:30:07 +02001758
Michal Vaskob36053d2020-03-26 15:49:30 +01001759 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001760}
1761
David Sedlákaa854b02019-07-22 14:17:10 +02001762/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001763 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001764 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001765 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001766 * @param[in,out] rev Array to store the parsed value in.
1767 * @param[in,out] exts Extension instances to add to.
1768 *
1769 * @return LY_ERR values.
1770 */
1771static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001772yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001773{
1774 const char *temp_rev;
1775 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001776 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1777 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001778
Michal Vaskob36053d2020-03-26 15:49:30 +01001779 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1780 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 +02001781 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vasko69730152020-10-09 16:30:07 +02001782 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001783
1784 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001785 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001786
Michal Vaskob36053d2020-03-26 15:49:30 +01001787 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001788}
1789
1790/**
1791 * @brief Parse config element.
1792 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001793 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001794 * @param[in,out] flags Flags to add to.
1795 * @param[in,out] exts Extension instances to add to.
1796 *
1797 * @return LY_ERR values.
1798 */
1799static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001800yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001801{
1802 const char *temp_val = NULL;
1803 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001804 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1805 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001806
Michal Vaskob36053d2020-03-26 15:49:30 +01001807 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1808 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
David Sedlákdfbbb442019-08-06 16:33:21 +02001809 if (strcmp(temp_val, "true") == 0) {
1810 *flags |= LYS_CONFIG_W;
1811 } else if (strcmp(temp_val, "false") == 0) {
1812 *flags |= LYS_CONFIG_R;
1813 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001814 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001815 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001816 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001817 return LY_EVALID;
1818 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001819 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001820
Michal Vaskob36053d2020-03-26 15:49:30 +01001821 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001822}
1823
1824/**
1825 * @brief Parse yang-version element.
1826 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001827 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001828 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001829 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001830 *
1831 * @return LY_ERR values.
1832 */
1833static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001834yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001835{
1836 const char *temp_version = NULL;
1837 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001838 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1839 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001840
Michal Vaskob36053d2020-03-26 15:49:30 +01001841 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1842 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 +02001843 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001844 *version = LYS_VERSION_1_0;
1845 } else if (strcmp(temp_version, "1.1") == 0) {
1846 *version = LYS_VERSION_1_1;
1847 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001848 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001849 "yang-version", "1", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001850 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001851 return LY_EVALID;
1852 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001853 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001854
Michal Vaskob36053d2020-03-26 15:49:30 +01001855 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001856}
1857
1858/**
1859 * @brief Parse import element.
1860 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001861 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001862 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1863 *
1864 * @return LY_ERR values.
1865 */
1866static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001867yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001868{
1869 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001870
David Sedlákdfbbb442019-08-06 16:33:21 +02001871 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001872 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001873
1874 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001875 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1876 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1877 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1878 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1879 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1880 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001881
1882 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001883 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1884 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1885 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001886 /* check prefix validity */
1887 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1888
1889 return LY_SUCCESS;
1890}
1891
1892/**
1893 * @brief Parse mandatory element.
1894 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001895 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001896 * @param[in,out] flags Flags to add to.
1897 * @param[in,out] exts Extension instances to add to.
1898 *
1899 * @return LY_ERR values.
1900 */
1901static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001902yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001903{
1904 const char *temp_val = NULL;
1905 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001906 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1907 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001908
Michal Vaskob36053d2020-03-26 15:49:30 +01001909 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1910 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 +02001911 if (strcmp(temp_val, "true") == 0) {
1912 *flags |= LYS_MAND_TRUE;
1913 } else if (strcmp(temp_val, "false") == 0) {
1914 *flags |= LYS_MAND_FALSE;
1915 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001916 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001917 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001918 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001919 return LY_EVALID;
1920 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001921 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001922
Michal Vaskob36053d2020-03-26 15:49:30 +01001923 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001924}
1925
1926/**
1927 * @brief Parse status element.
1928 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001929 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001930 * @param[in,out] flags Flags to add to.
1931 * @param[in,out] exts Extension instances to add to.
1932 *
1933 * @return LY_ERR values.
1934 */
1935static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001936yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001937{
1938 const char *value = NULL;
1939 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001940 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1941 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001942
Michal Vaskob36053d2020-03-26 15:49:30 +01001943 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1944 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 +02001945 if (strcmp(value, "current") == 0) {
1946 *flags |= LYS_STATUS_CURR;
1947 } else if (strcmp(value, "deprecated") == 0) {
1948 *flags |= LYS_STATUS_DEPRC;
1949 } else if (strcmp(value, "obsolete") == 0) {
1950 *flags |= LYS_STATUS_OBSLT;
1951 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001952 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001953 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001954 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001955 return LY_EVALID;
1956 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001957 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001958
Michal Vaskob36053d2020-03-26 15:49:30 +01001959 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001960}
1961
1962/**
1963 * @brief Parse when element.
1964 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001965 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001966 * @param[out] when_p When pointer to parse to.
1967 */
1968static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001969yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001970{
1971 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001972 LY_ERR ret = LY_SUCCESS;
1973
David Sedlákdfbbb442019-08-06 16:33:21 +02001974 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001975 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001976
1977 ret = lyxml_ctx_next(ctx->xmlctx);
1978 LY_CHECK_ERR_RET(ret, free(when), ret);
1979
Michal Vaskob36053d2020-03-26 15:49:30 +01001980 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001981 LY_CHECK_ERR_RET(ret, free(when), ret);
1982
David Sedlákdfbbb442019-08-06 16:33:21 +02001983 *when_p = when;
1984 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001985 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1986 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1987 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1988 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001989
Michal Vaskob36053d2020-03-26 15:49:30 +01001990 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001991}
1992
1993/**
1994 * @brief Parse yin-elemenet element.
1995 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001996 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001997 * @param[in,out] data Data to read from, always moved to currently handled position.
1998 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001999 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002000 *
2001 * @return LY_ERR values.
2002 */
2003static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002004yin_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 +02002005{
2006 const char *temp_val = NULL;
2007 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002008 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2009 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002010
Michal Vaskob36053d2020-03-26 15:49:30 +01002011 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2012 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 +02002013 if (strcmp(temp_val, "true") == 0) {
2014 *flags |= LYS_YINELEM_TRUE;
2015 } else if (strcmp(temp_val, "false") == 0) {
2016 *flags |= LYS_YINELEM_FALSE;
2017 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002018 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002019 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01002020 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002021 return LY_EVALID;
2022 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002023 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002024
Michal Vaskob36053d2020-03-26 15:49:30 +01002025 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002026}
2027
2028/**
2029 * @brief Parse argument element.
2030 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002031 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002032 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2033 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002034 *
2035 * @return LY_ERR values.
2036 */
2037static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002038yin_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 +02002039{
2040 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002041 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2042 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2043 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002044
Michal Vaskob36053d2020-03-26 15:49:30 +01002045 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2046 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02002047
Michal Vaskob36053d2020-03-26 15:49:30 +01002048 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002049}
2050
2051/**
2052 * @brief Parse the extension statement.
2053 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002054 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002055 * @param[in,out] extensions Extensions to add to.
2056 *
2057 * @return LY_ERR values.
2058 */
2059static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002060yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002061{
2062 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002063
Michal Vaskob36053d2020-03-26 15:49:30 +01002064 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2065 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2066 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 +02002067
2068 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
2069 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002070 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2071 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2072 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2073 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2074 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2075 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002076
Michal Vaskob36053d2020-03-26 15:49:30 +01002077 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002078}
2079
2080/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002081 * @brief Parse feature element.
2082 *
2083 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002084 * @param[in,out] features Features to add to.
2085 *
2086 * @return LY_ERR values.
2087 */
2088static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002089yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002090{
2091 struct lysp_feature *feat;
2092
2093 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002094 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002095
2096 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002097 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2098 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 +02002099
2100 /* parse content */
2101 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002102 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2103 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2104 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2105 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2106 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2107 };
Michal Vasko69730152020-10-09 16:30:07 +02002108
Michal Vaskob36053d2020-03-26 15:49:30 +01002109 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002110}
2111
2112/**
David Sedlák28794f22019-07-22 16:45:00 +02002113 * @brief Parse identity element.
2114 *
2115 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002116 * @param[in,out] identities Identities to add to.
2117 *
2118 * @return LY_ERR values.
2119 */
2120static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002121yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002122{
2123 struct lysp_ident *ident;
2124
2125 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002126 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002127
2128 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002129 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2130 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 +02002131
2132 /* parse content */
2133 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002134 {LY_STMT_BASE, &ident->bases, 0},
2135 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2136 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2137 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2138 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2139 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2140 };
Michal Vasko69730152020-10-09 16:30:07 +02002141
Michal Vaskob36053d2020-03-26 15:49:30 +01002142 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002143}
2144
2145/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002146 * @brief Parse list element.
2147 *
2148 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002149 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002150 *
2151 * @return LY_ERR values.
2152 */
2153static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002154yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002155{
David Sedlákaf536aa2019-07-23 13:42:23 +02002156 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002157 LY_ERR ret = LY_SUCCESS;
2158 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002159
Michal Vaskob36053d2020-03-26 15:49:30 +01002160 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002161 list->nodetype = LYS_LIST;
2162 list->parent = node_meta->parent;
2163
David Sedlákaf536aa2019-07-23 13:42:23 +02002164 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002165 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2166 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 +02002167
2168 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002169 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002170 LY_STMT_ACTION, &list->actions, 0,
2171 LY_STMT_ANYDATA, &list->child, 0,
2172 LY_STMT_ANYXML, &list->child, 0,
2173 LY_STMT_CHOICE, &list->child, 0,
2174 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2175 LY_STMT_CONTAINER, &list->child, 0,
2176 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2177 LY_STMT_GROUPING, &list->groupings, 0,
2178 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2179 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2180 LY_STMT_LEAF, &list->child, 0,
2181 LY_STMT_LEAF_LIST, &list->child, 0,
2182 LY_STMT_LIST, &list->child, 0,
2183 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2184 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2185 LY_STMT_MUST, &list->musts, 0,
2186 LY_STMT_NOTIFICATION, &list->notifs, 0,
2187 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2188 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2189 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2190 LY_STMT_TYPEDEF, &list->typedefs, 0,
2191 LY_STMT_UNIQUE, &list->uniques, 0,
2192 LY_STMT_USES, &list->child, 0,
2193 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2194 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002195 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002196 subelems_deallocator(25, subelems);
2197 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002198
2199 /* finalize parent pointers to the reallocated items */
2200 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2201
Michal Vasko69730152020-10-09 16:30:07 +02002202 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002203 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002204 return LY_EVALID;
2205 }
2206
2207 return LY_SUCCESS;
2208}
2209
2210/**
David Sedlák031b9e72019-07-23 15:19:37 +02002211 * @brief Parse notification element.
2212 *
2213 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002214 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002215 *
2216 * @return LY_ERR values.
2217 */
2218static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002219yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002220{
2221 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002222 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002223 LY_ERR ret = LY_SUCCESS;
2224 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002225
2226 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002227 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002228 notif->nodetype = LYS_NOTIF;
2229 notif->parent = notif_meta->parent;
2230
2231 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002232 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2233 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 +02002234
2235 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002236 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002237 LY_STMT_ANYDATA, &notif->data, 0,
2238 LY_STMT_ANYXML, &notif->data, 0,
2239 LY_STMT_CHOICE, &notif->data, 0,
2240 LY_STMT_CONTAINER, &notif->data, 0,
2241 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2242 LY_STMT_GROUPING, &notif->groupings, 0,
2243 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2244 LY_STMT_LEAF, &notif->data, 0,
2245 LY_STMT_LEAF_LIST, &notif->data, 0,
2246 LY_STMT_LIST, &notif->data, 0,
2247 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2248 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2249 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2250 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2251 LY_STMT_USES, &notif->data, 0,
2252 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002253
Michal Vaskob36053d2020-03-26 15:49:30 +01002254 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002255 subelems_deallocator(16, subelems);
2256 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002257
2258 /* finalize parent pointers to the reallocated items */
2259 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2260
2261 return LY_SUCCESS;
2262}
2263
2264/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002265 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002266 *
2267 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002268 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002269 *
2270 * @return LY_ERR values.
2271 */
2272static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002273yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002274{
2275 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002276 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002277 LY_ERR ret = LY_SUCCESS;
2278 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002279
2280 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002281 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002282 grp->nodetype = LYS_GROUPING;
2283 grp->parent = gr_meta->parent;
2284
2285 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002286 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2287 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 +02002288
2289 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002290 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002291 LY_STMT_ACTION, &grp->actions, 0,
2292 LY_STMT_ANYDATA, &grp->data, 0,
2293 LY_STMT_ANYXML, &grp->data, 0,
2294 LY_STMT_CHOICE, &grp->data, 0,
2295 LY_STMT_CONTAINER, &grp->data, 0,
2296 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2297 LY_STMT_GROUPING, &grp->groupings, 0,
2298 LY_STMT_LEAF, &grp->data, 0,
2299 LY_STMT_LEAF_LIST, &grp->data, 0,
2300 LY_STMT_LIST, &grp->data, 0,
2301 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2302 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2303 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2304 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2305 LY_STMT_USES, &grp->data, 0,
2306 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002307 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002308 subelems_deallocator(16, subelems);
2309 LY_CHECK_RET(ret);
2310
David Sedláke3ce9ef2019-07-23 16:34:30 +02002311 /* finalize parent pointers to the reallocated items */
2312 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2313
2314 return LY_SUCCESS;
2315}
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;
David Sedlákf111bcb2019-07-23 17:15:51 +02002331
2332 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002333 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002334 cont->nodetype = LYS_CONTAINER;
2335 cont->parent = node_meta->parent;
2336
David Sedlákf111bcb2019-07-23 17:15:51 +02002337 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002338 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2339 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 +02002340
2341 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002342 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002343 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2344 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2345 LY_STMT_ANYXML, &cont->child, 0,
2346 LY_STMT_CHOICE, &cont->child, 0,
2347 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2348 LY_STMT_CONTAINER, &cont->child, 0,
2349 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_GROUPING, &cont->groupings, 0,
2351 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2352 LY_STMT_LEAF, &cont->child, 0,
2353 LY_STMT_LEAF_LIST, &cont->child, 0,
2354 LY_STMT_LIST, &cont->child, 0,
2355 LY_STMT_MUST, &cont->musts, 0,
2356 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2357 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2358 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2360 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2361 LY_STMT_USES, &cont->child, 0,
2362 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2363 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002364 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002365 subelems_deallocator(21, subelems);
2366 LY_CHECK_RET(ret);
2367
David Sedlákf111bcb2019-07-23 17:15:51 +02002368 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2369
2370 return LY_SUCCESS;
2371}
2372
2373/**
David Sedlák5379d392019-07-24 10:42:03 +02002374 * @brief Parse case element.
2375 *
2376 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002377 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002378 *
2379 * @return LY_ERR values.
2380 */
2381static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002382yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002383{
David Sedlák5379d392019-07-24 10:42:03 +02002384 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002385 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002386 struct yin_subelement *subelems = NULL;
David Sedlák5379d392019-07-24 10:42:03 +02002387
2388 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002389 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002390 cas->nodetype = LYS_CASE;
2391 cas->parent = node_meta->parent;
2392
David Sedlák5379d392019-07-24 10:42:03 +02002393 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002394 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2395 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 +02002396
2397 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002398 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002399 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2400 LY_STMT_ANYXML, &cas->child, 0,
2401 LY_STMT_CHOICE, &cas->child, 0,
2402 LY_STMT_CONTAINER, &cas->child, 0,
2403 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2404 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2405 LY_STMT_LEAF, &cas->child, 0,
2406 LY_STMT_LEAF_LIST, &cas->child, 0,
2407 LY_STMT_LIST, &cas->child, 0,
2408 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2409 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2410 LY_STMT_USES, &cas->child, 0,
2411 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2412 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002413 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002414 subelems_deallocator(14, subelems);
2415
2416 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002417}
2418
2419/**
David Sedlák05404f62019-07-24 14:11:53 +02002420 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002421 *
2422 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002423 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002424 *
2425 * @return LY_ERR values.
2426 */
2427LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002428yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002429{
David Sedlák81497a32019-08-13 16:56:26 +02002430 LY_ERR ret = LY_SUCCESS;
2431 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002432 struct lysp_node_choice *choice;
2433
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 */
David Sedlák81497a32019-08-13 16:56:26 +02002445 LY_CHECK_RET(subelems_allocator(ctx, 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));
Michal Vaskob36053d2020-03-26 15:49:30 +01002463 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002464 subelems_deallocator(17, subelems);
2465 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;
2482
David Sedlák05404f62019-07-24 14:11:53 +02002483 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002484 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002485 inout_meta->inout_p->parent = inout_meta->parent;
2486
2487 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002488 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2489 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 +02002490
2491 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002492 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002493 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2494 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2495 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2496 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2497 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2498 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2499 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2500 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2501 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2502 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2503 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2504 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002505 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002506 subelems_deallocator(12, subelems);
2507 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002508
Michal Vaskob83af8a2020-01-06 09:49:22 +01002509 if (!inout_meta->inout_p->data) {
2510 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2511 return LY_EVALID;
2512 }
2513
David Sedlák05404f62019-07-24 14:11:53 +02002514 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002515 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings, NULL, NULL, NULL));
David Sedlák05404f62019-07-24 14:11:53 +02002516
2517 return LY_SUCCESS;
2518}
2519
David Sedlák992fb7c2019-07-24 16:51:01 +02002520/**
2521 * @brief Parse action element.
2522 *
2523 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002524 * @param[in] act_meta Meta information about parent node and actions to add to.
2525 *
2526 * @return LY_ERR values.
2527 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002528static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002529yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002530{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002531 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002532 LY_ERR ret = LY_SUCCESS;
2533 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002534
2535 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002536 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002537 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002538 act->parent = act_meta->parent;
2539
2540 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002541 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2542 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, LY_STMT_ACTION));
David Sedlák85d0eca2019-07-24 15:15:21 +02002543
2544 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002545 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002546 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2547 LY_STMT_GROUPING, &act->groupings, 0,
2548 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2549 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2550 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2551 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2552 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2553 LY_STMT_TYPEDEF, &act->typedefs, 0,
2554 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002555 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002556 subelems_deallocator(9, subelems);
2557 LY_CHECK_RET(ret);
2558
Michal Vasko7f45cf22020-10-01 12:49:44 +02002559 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2560 if (!act->input.nodetype) {
2561 act->input.nodetype = LYS_INPUT;
2562 act->input.parent = (struct lysp_node *)act;
2563 }
2564 if (!act->output.nodetype) {
2565 act->output.nodetype = LYS_OUTPUT;
2566 act->output.parent = (struct lysp_node *)act;
2567 }
2568
David Sedlák85d0eca2019-07-24 15:15:21 +02002569 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2570
2571 return LY_SUCCESS;
2572}
2573
David Sedlák05404f62019-07-24 14:11:53 +02002574/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002575 * @brief Parse augment element.
2576 *
2577 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002578 * @param[in] aug_meta Meta information about parent node and augments to add to.
2579 *
2580 * @return LY_ERR values.
2581 */
2582static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002583yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002584{
2585 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002586 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002587 LY_ERR ret = LY_SUCCESS;
2588 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002589
2590 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002591 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002592 aug->nodetype = LYS_AUGMENT;
2593 aug->parent = aug_meta->parent;
2594
2595 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002596 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2597 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2598 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002599
2600 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002601 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002602 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2603 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2604 LY_STMT_ANYXML, &aug->child, 0,
2605 LY_STMT_CASE, &aug->child, 0,
2606 LY_STMT_CHOICE, &aug->child, 0,
2607 LY_STMT_CONTAINER, &aug->child, 0,
2608 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002609 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002610 LY_STMT_LEAF, &aug->child, 0,
2611 LY_STMT_LEAF_LIST, &aug->child, 0,
2612 LY_STMT_LIST, &aug->child, 0,
2613 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2614 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2615 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2616 LY_STMT_USES, &aug->child, 0,
2617 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2618 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002619 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002620 subelems_deallocator(17, subelems);
2621 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002622
2623 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2624
2625 return LY_SUCCESS;
2626}
2627
David Sedlák8b754462019-07-25 16:22:13 +02002628/**
2629 * @brief Parse deviate element.
2630 *
2631 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002632 * @param[in] deviates Deviates to add to.
2633 *
2634 * @return LY_ERR values.
2635 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002636static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002637yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002638{
2639 LY_ERR ret = LY_SUCCESS;
2640 uint8_t dev_mod;
2641 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002642 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002643 struct lysp_deviate_add *d_add = NULL;
2644 struct lysp_deviate_rpl *d_rpl = NULL;
2645 struct lysp_deviate_del *d_del = NULL;
2646
2647 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002648 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2649 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 +02002650
2651 if (strcmp(temp_val, "not-supported") == 0) {
2652 dev_mod = LYS_DEV_NOT_SUPPORTED;
2653 } else if (strcmp(temp_val, "add") == 0) {
2654 dev_mod = LYS_DEV_ADD;
2655 } else if (strcmp(temp_val, "replace") == 0) {
2656 dev_mod = LYS_DEV_REPLACE;
2657 } else if (strcmp(temp_val, "delete") == 0) {
2658 dev_mod = LYS_DEV_DELETE;
2659 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002660 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002661 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002662 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002663 return LY_EVALID;
2664 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002665 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002666
2667 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2668 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002669 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002670 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002671 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2672 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002673 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002674
2675 } else if (dev_mod == LYS_DEV_ADD) {
2676 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002677 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002678 d = (struct lysp_deviate *)d_add;
2679 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2680 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2681 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002682 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002683 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002684 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2685 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2686 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2687 {LY_STMT_MUST, &d_add->musts, 0},
2688 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2689 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2690 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2691 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002692 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002693
2694 } else if (dev_mod == LYS_DEV_REPLACE) {
2695 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002696 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002697 d = (struct lysp_deviate *)d_rpl;
2698 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2699 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2700 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002701 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002702 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002703 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2704 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2705 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2706 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2707 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2708 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2709 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002710 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002711
2712 } else {
2713 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002714 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002715 d = (struct lysp_deviate *)d_del;
2716 struct yin_subelement subelems[5] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002717 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002718 {LY_STMT_MUST, &d_del->musts, 0},
2719 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2720 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2721 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2722 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002723 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002724 }
2725 LY_CHECK_GOTO(ret, cleanup);
2726
2727 d->mod = dev_mod;
2728 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002729 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002730
2731 return ret;
2732
2733cleanup:
2734 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002735 return ret;
2736}
2737
David Sedlák992fb7c2019-07-24 16:51:01 +02002738/**
David Sedlák8b754462019-07-25 16:22:13 +02002739 * @brief Parse deviation element.
2740 *
2741 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002742 * @param[in] deviations Deviations to add to.
2743 *
2744 * @return LY_ERR values.
2745 */
2746static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002747yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002748{
2749 struct lysp_deviation *dev;
2750
2751 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002752 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002753
2754 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002755 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2756 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2757 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002758 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002759 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2760 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2761 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2762 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2763 };
Michal Vasko69730152020-10-09 16:30:07 +02002764
Michal Vaskob36053d2020-03-26 15:49:30 +01002765 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002766}
2767
2768/**
David Sedlákb4e44562019-07-04 15:42:12 +02002769 * @brief Map keyword type to substatement info.
2770 *
2771 * @param[in] kw Keyword type.
2772 *
2773 * @return correct LYEXT_SUBSTMT information.
2774 */
2775static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002776kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002777{
2778 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002779 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002780 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002781 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002782 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002783 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002784 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002785 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002786 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002787 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002788 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002789 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002790 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002791 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002792 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002793 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002794 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002795 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002796 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002797 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002798 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002799 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002800 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002801 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002802 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002803 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002804 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002805 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002806 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002807 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002808 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002809 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002810 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002811 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002812 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002813 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002814 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002815 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002816 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002817 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002818 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002819 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002820 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002821 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002822 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002823 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002824 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002825 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002826 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002827 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002828 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002829 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002830 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002831 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002832 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002833 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002834 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002835 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002836 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002837 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002838 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002839 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002840 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002841 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002842 return LYEXT_SUBSTMT_IFFEATURE;
2843 default:
2844 return LYEXT_SUBSTMT_SELF;
2845 }
2846}
2847
David Sedlákc5b20842019-08-13 10:18:31 +02002848/**
2849 * @brief map keyword to keyword-group.
2850 *
2851 * @param[in] ctx YIN parser context used for logging.
2852 * @param[in] kw Keyword that is child of module or submodule.
2853 * @param[out] group Group of keyword.
2854 *
2855 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2856 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002857static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002858kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002859{
2860 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002861 /* module header */
2862 case LY_STMT_NONE:
2863 case LY_STMT_NAMESPACE:
2864 case LY_STMT_PREFIX:
2865 case LY_STMT_BELONGS_TO:
2866 case LY_STMT_YANG_VERSION:
2867 *group = Y_MOD_MODULE_HEADER;
2868 break;
2869 /* linkage */
2870 case LY_STMT_INCLUDE:
2871 case LY_STMT_IMPORT:
2872 *group = Y_MOD_LINKAGE;
2873 break;
2874 /* meta */
2875 case LY_STMT_ORGANIZATION:
2876 case LY_STMT_CONTACT:
2877 case LY_STMT_DESCRIPTION:
2878 case LY_STMT_REFERENCE:
2879 *group = Y_MOD_META;
2880 break;
2881 /* revision */
2882 case LY_STMT_REVISION:
2883 *group = Y_MOD_REVISION;
2884 break;
2885 /* body */
2886 case LY_STMT_ANYDATA:
2887 case LY_STMT_ANYXML:
2888 case LY_STMT_AUGMENT:
2889 case LY_STMT_CHOICE:
2890 case LY_STMT_CONTAINER:
2891 case LY_STMT_DEVIATION:
2892 case LY_STMT_EXTENSION:
2893 case LY_STMT_FEATURE:
2894 case LY_STMT_GROUPING:
2895 case LY_STMT_IDENTITY:
2896 case LY_STMT_LEAF:
2897 case LY_STMT_LEAF_LIST:
2898 case LY_STMT_LIST:
2899 case LY_STMT_NOTIFICATION:
2900 case LY_STMT_RPC:
2901 case LY_STMT_TYPEDEF:
2902 case LY_STMT_USES:
2903 case LY_STMT_EXTENSION_INSTANCE:
2904 *group = Y_MOD_BODY;
2905 break;
2906 default:
2907 LOGINT(ctx->xmlctx->ctx);
2908 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002909 }
2910
2911 return LY_SUCCESS;
2912}
2913
David Sedlákc5b20842019-08-13 10:18:31 +02002914/**
2915 * @brief Check if relative order of two keywords is valid.
2916 *
2917 * @param[in] ctx YIN parser context used for logging.
2918 * @param[in] kw Current keyword.
2919 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002920 * @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 +02002921 * because relative order is required only in module and submodule sub-elements, used for logging.
2922 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002923 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002924 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002925static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002926yin_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 +02002927{
Radek Krejcid6b76452019-09-03 17:03:03 +02002928 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002929 enum yang_module_stmt gr, next_gr;
2930
2931 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2932 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2933
2934 if (gr > next_gr) {
2935 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2936 return LY_EVALID;
2937 }
2938
2939 return LY_SUCCESS;
2940}
2941
David Sedlákc5dd0942019-09-13 10:23:59 +02002942/**
2943 * @brief Get element name prefixed by full URI of xml namespace.
2944 *
2945 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2946 * @param[in] name Name of element.
2947 * @param[in] name_len Length of element name.
2948 * @param[in] prefix Prefix of element.
2949 * @param[in] prefix_len Length of element prefix.
2950 *
2951 * @return Element name prefixed by URI on success, NULL on failure.
2952 */
2953static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002954name2nsname(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
David Sedlák068dd352019-09-13 09:08:22 +02002955{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002956 const char *ename = NULL;
Michal Vaskoc8a230d2020-08-14 12:17:10 +02002957 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002958
Michal Vaskob36053d2020-03-26 15:49:30 +01002959 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002960
Radek Krejci02728562019-09-18 14:13:05 +02002961 if (!strcmp(ns->uri, YIN_NS_URI)) {
2962 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002963 lydict_insert(ctx->xmlctx->ctx, name, name_len, &ename);
2964 return ename;
Radek Krejci02728562019-09-18 14:13:05 +02002965 }
2966 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002967 size_t ns_len = strlen(ns->uri);
2968 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2969
2970 char *result;
2971 char *temp;
Michal Vasko69730152020-10-09 16:30:07 +02002972
David Sedláke0ef1c62019-09-13 10:05:55 +02002973 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002974 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002975
2976 strcpy(result, ns->uri);
2977 result[ns_len] = ':';
2978 temp = &result[ns_len + 1];
2979 strncpy(temp, name, name_len);
2980 result[len] = '\0';
2981
Radek Krejci011e4aa2020-09-04 15:22:31 +02002982 lydict_insert_zc(ctx->xmlctx->ctx, result, &ename);
2983 return ename;
David Sedlák068dd352019-09-13 09:08:22 +02002984}
2985
Michal Vaskoafac7822020-10-20 14:22:26 +02002986/**
2987 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2988 *
2989 * @param[in,out] ctx Yin parser context for logging and to store current state.
2990 * @param[in] elem_type Type of element that is currently being parsed.
2991 * @param[out] arg Value to write to.
2992 *
2993 * @return LY_ERR values.
2994 */
2995static LY_ERR
2996yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2997{
2998 enum ly_stmt child;
2999
3000 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3001
3002 switch (elem_type) {
3003 case LY_STMT_ACTION:
3004 case LY_STMT_ANYDATA:
3005 case LY_STMT_ANYXML:
3006 case LY_STMT_ARGUMENT:
3007 case LY_STMT_BASE:
3008 case LY_STMT_BIT:
3009 case LY_STMT_CASE:
3010 case LY_STMT_CHOICE:
3011 case LY_STMT_CONTAINER:
3012 case LY_STMT_ENUM:
3013 case LY_STMT_EXTENSION:
3014 case LY_STMT_FEATURE:
3015 case LY_STMT_GROUPING:
3016 case LY_STMT_IDENTITY:
3017 case LY_STMT_IF_FEATURE:
3018 case LY_STMT_LEAF:
3019 case LY_STMT_LEAF_LIST:
3020 case LY_STMT_LIST:
3021 case LY_STMT_MODULE:
3022 case LY_STMT_NOTIFICATION:
3023 case LY_STMT_RPC:
3024 case LY_STMT_SUBMODULE:
3025 case LY_STMT_TYPE:
3026 case LY_STMT_TYPEDEF:
3027 case LY_STMT_UNITS:
3028 case LY_STMT_USES:
3029 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
3030 break;
3031 case LY_STMT_AUGMENT:
3032 case LY_STMT_DEVIATION:
3033 case LY_STMT_REFINE:
3034 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
3035 break;
3036 case LY_STMT_CONFIG:
3037 case LY_STMT_DEFAULT:
3038 case LY_STMT_DEVIATE:
3039 case LY_STMT_ERROR_APP_TAG:
3040 case LY_STMT_FRACTION_DIGITS:
3041 case LY_STMT_KEY:
3042 case LY_STMT_LENGTH:
3043 case LY_STMT_MANDATORY:
3044 case LY_STMT_MAX_ELEMENTS:
3045 case LY_STMT_MIN_ELEMENTS:
3046 case LY_STMT_MODIFIER:
3047 case LY_STMT_ORDERED_BY:
3048 case LY_STMT_PATH:
3049 case LY_STMT_PATTERN:
3050 case LY_STMT_POSITION:
3051 case LY_STMT_PREFIX:
3052 case LY_STMT_PRESENCE:
3053 case LY_STMT_RANGE:
3054 case LY_STMT_REQUIRE_INSTANCE:
3055 case LY_STMT_STATUS:
3056 case LY_STMT_VALUE:
3057 case LY_STMT_YANG_VERSION:
3058 case LY_STMT_YIN_ELEMENT:
3059 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
3060 break;
3061 case LY_STMT_IMPORT:
3062 case LY_STMT_INCLUDE:
3063 case LY_STMT_BELONGS_TO:
3064 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
3065 break;
3066 case LY_STMT_INPUT:
3067 case LY_STMT_OUTPUT:
3068 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3069 break;
3070 case LY_STMT_MUST:
3071 case LY_STMT_WHEN:
3072 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
3073 break;
3074 case LY_STMT_NAMESPACE:
3075 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
3076 break;
3077 case LY_STMT_REVISION:
3078 case LY_STMT_REVISION_DATE:
3079 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
3080 break;
3081 case LY_STMT_UNIQUE:
3082 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
3083 break;
3084 /* argument is mapped to yin element */
3085 case LY_STMT_CONTACT:
3086 case LY_STMT_DESCRIPTION:
3087 case LY_STMT_ORGANIZATION:
3088 case LY_STMT_REFERENCE:
3089 case LY_STMT_ERROR_MESSAGE:
3090 /* there shouldn't be any attribute, argument is supposed to be first subelement */
3091 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3092
3093 /* no content */
3094 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3095 if (ctx->xmlctx->ws_only) {
3096 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3097 }
3098 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3099 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3100 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
3101 return LY_EVALID;
3102 }
3103
3104 /* parse child element */
3105 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3106 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3107 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
3108 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3109 ly_stmt2str(elem_type));
3110 return LY_EVALID;
3111 }
3112 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3113
3114 /* no attributes expected? TODO */
3115 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3116 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3117 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3118 }
3119
3120 /* load and save content */
3121 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3122 LY_CHECK_RET(!*arg, LY_EMEM);
3123
3124 /* load closing tag of subelement */
3125 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3126
3127 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3128 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3129 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3130 }*/
3131 break;
3132 default:
3133 LOGINT(ctx->xmlctx->ctx);
3134 return LY_EINT;
3135 }
3136
3137 return LY_SUCCESS;
3138}
3139
3140/**
3141 * @brief Parse yin element into generic structure.
3142 *
3143 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3144 * @param[in] parent Identification of parent element.
3145 * @param[out] element Where the element structure should be stored.
3146 *
3147 * @return LY_ERR values.
3148 */
3149LY_ERR
3150yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3151{
3152 LY_ERR ret = LY_SUCCESS;
3153 struct lysp_stmt *last = NULL, *new = NULL;
3154
3155 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3156
3157 /* allocate new structure for element */
3158 *element = calloc(1, sizeof(**element));
3159 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3160 (*element)->stmt = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
3161 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
3162
3163 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3164 ctx->xmlctx->prefix_len, parent);
3165
3166 last = (*element)->child;
3167 if ((*element)->kw == LY_STMT_NONE) {
3168 /* unrecognized element */
3169 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3170 ly_stmt2str(parent));
3171 ret = LY_EVALID;
3172 goto cleanup;
3173 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3174 /* element is known yang keyword, which means argument can be parsed correctly. */
3175 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3176 LY_CHECK_GOTO(ret, cleanup);
3177 } else {
3178 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3179
3180 /* load attributes in generic way, save all attributes in linked list */
3181 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3182 new = calloc(1, sizeof(*last));
3183 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3184 if (!(*element)->child) {
3185 /* save first */
3186 (*element)->child = new;
3187 } else {
3188 last->next = new;
3189 }
3190 last = new;
3191
3192 last->flags |= LYS_YIN_ATTR;
3193 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3194 last->kw = LY_STMT_NONE;
3195 /* attributes with prefix are ignored */
3196 if (!ctx->xmlctx->prefix) {
3197 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3198
3199 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3200 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3201 } else {
3202 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3203 }
3204 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3205 }
3206 }
3207
3208 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3209 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3210 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3211 /* parse subelements */
3212 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3213 LY_CHECK_GOTO(ret, cleanup);
3214 if (!(*element)->child) {
3215 /* save first */
3216 (*element)->child = new;
3217 } else {
3218 last->next = new;
3219 }
3220 last = new;
3221
3222 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3223 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3224 }
3225 } else {
3226 /* save element content */
3227 if (ctx->xmlctx->value_len) {
3228 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3229 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3230 }
3231
3232 /* read closing tag */
3233 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3234 }
3235
3236cleanup:
3237 return ret;
3238}
3239
3240/**
3241 * @brief Parse instance of extension.
3242 *
3243 * @param[in,out] ctx Yin parser context for logging and to store current state.
3244 * @param[in] subelem Type of the keyword this extension instance is a subelement of.
3245 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3246 * @param[in,out] exts Extension instance to add to.
3247 *
3248 * @return LY_ERR values.
3249 */
3250LY_ERR
3251yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, LY_ARRAY_COUNT_TYPE subelem_index,
3252 struct lysp_ext_instance **exts)
3253{
3254 struct lysp_ext_instance *e;
3255 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3256
3257 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3258
3259 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3260
3261 e->yin = 0;
3262 /* store name and insubstmt info */
3263 e->name = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
3264 LY_CHECK_RET(!e->name, LY_EMEM);
3265 e->insubstmt = subelem;
3266 e->insubstmt_index = subelem_index;
3267 e->yin |= LYS_YIN;
3268 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3269
3270 /* store attributes as subelements */
3271 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3272 if (!ctx->xmlctx->prefix) {
3273 new_subelem = calloc(1, sizeof(*new_subelem));
3274 if (!e->child) {
3275 e->child = new_subelem;
3276 } else {
3277 last_subelem->next = new_subelem;
3278 }
3279 last_subelem = new_subelem;
3280
3281 last_subelem->flags |= LYS_YIN_ATTR;
3282 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3283 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3284 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3285
3286 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last_subelem->arg);
3287 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3288 } else {
3289 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3290 }
3291
3292 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3293 }
3294
3295 /* parse subelements */
3296 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3297 if (ctx->xmlctx->ws_only) {
3298 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3299 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3300 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3301 if (!e->child) {
3302 e->child = new_subelem;
3303 } else {
3304 last_subelem->next = new_subelem;
3305 }
3306 last_subelem = new_subelem;
3307
3308 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3309 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3310 }
3311 } else if (ctx->xmlctx->value_len) {
3312 /* save text content */
3313 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3314 LY_CHECK_RET(!e->argument, LY_EMEM);
3315
3316 /* parser next */
3317 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3318 }
3319
3320 return LY_SUCCESS;
3321}
3322
3323/**
3324 * @brief Generic function for content parsing
3325 *
3326 * @param[in,out] ctx Yin parser context for logging and to store current state.
3327 * @param[in] subelem_info array of valid subelement types and meta information
3328 * @param[in] subelem_info_size Size of subelem_info array.
3329 * @param[in] current_element Type of current element.
3330 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3331 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3332 *
3333 * @return LY_ERR values.
3334 */
David Sedlákd6e56892019-07-01 15:40:24 +02003335LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003336yin_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 +02003337 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003338{
3339 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003340 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003341 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003342 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003343
Michal Vaskob36053d2020-03-26 15:49:30 +01003344 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003345
Michal Vaskob36053d2020-03-26 15:49:30 +01003346 if (ctx->xmlctx->ws_only) {
3347 /* check whether there are any children */
3348 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3349 } else {
3350 /* we want to parse the value */
3351 next_status = LYXML_ELEM_CLOSE;
3352 }
3353
3354 if (next_status == LYXML_ELEMENT) {
3355 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3356
3357 /* current element has subelements as content */
3358 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3359 /* match keyword */
3360 last_kw = kw;
3361 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003362 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003363
3364 /* check if this element can be child of current element */
3365 subelem = get_record(kw, subelem_info_size, subelem_info);
3366 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003367 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003368 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3369 } else {
3370 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003371 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003372 }
3373 ret = LY_EVALID;
3374 goto cleanup;
3375 }
3376
3377 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003378 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003379 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3380 LY_CHECK_GOTO(ret, cleanup);
3381 }
3382
3383 /* flag check */
3384 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3385 /* subelement uniquenes */
3386 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3387 return LY_EVALID;
3388 }
3389 if (subelem->flags & YIN_SUBELEM_FIRST) {
3390 /* subelement is supposed to be defined as first subelement */
3391 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3392 LY_CHECK_GOTO(ret, cleanup);
3393 }
3394 if (subelem->flags & YIN_SUBELEM_VER2) {
3395 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003396 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003397 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 +02003398 ret = LY_EVALID;
3399 goto cleanup;
3400 }
David Sedlákd6e56892019-07-01 15:40:24 +02003401 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003402 /* note that element was parsed for easy uniqueness check in next iterations */
3403 subelem->flags |= YIN_SUBELEM_PARSED;
3404
3405 switch (kw) {
3406 /* call responsible function */
3407 case LY_STMT_EXTENSION_INSTANCE:
3408 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vasko69730152020-10-09 16:30:07 +02003409 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003410 break;
3411 case LY_STMT_ACTION:
3412 case LY_STMT_RPC:
3413 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3414 break;
3415 case LY_STMT_ANYDATA:
3416 case LY_STMT_ANYXML:
3417 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3418 break;
3419 case LY_STMT_ARGUMENT:
3420 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3421 break;
3422 case LY_STMT_AUGMENT:
3423 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3424 break;
3425 case LY_STMT_BASE:
3426 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3427 break;
3428 case LY_STMT_BELONGS_TO:
3429 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3430 break;
3431 case LY_STMT_BIT:
3432 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3433 break;
3434 case LY_STMT_CASE:
3435 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3436 break;
3437 case LY_STMT_CHOICE:
3438 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3439 break;
3440 case LY_STMT_CONFIG:
3441 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3442 break;
3443 case LY_STMT_CONTACT:
3444 case LY_STMT_DESCRIPTION:
3445 case LY_STMT_ORGANIZATION:
3446 case LY_STMT_REFERENCE:
3447 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3448 break;
3449 case LY_STMT_CONTAINER:
3450 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3451 break;
3452 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003453 ret = yin_parse_qname(ctx, kw, subelem, exts);
3454 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003455 case LY_STMT_ERROR_APP_TAG:
3456 case LY_STMT_KEY:
3457 case LY_STMT_PRESENCE:
3458 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3459 break;
3460 case LY_STMT_DEVIATE:
3461 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3462 break;
3463 case LY_STMT_DEVIATION:
3464 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3465 break;
3466 case LY_STMT_ENUM:
3467 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3468 break;
3469 case LY_STMT_ERROR_MESSAGE:
3470 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3471 break;
3472 case LY_STMT_EXTENSION:
3473 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3474 break;
3475 case LY_STMT_FEATURE:
3476 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3477 break;
3478 case LY_STMT_FRACTION_DIGITS:
3479 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3480 break;
3481 case LY_STMT_GROUPING:
3482 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3483 break;
3484 case LY_STMT_IDENTITY:
3485 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3486 break;
3487 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003488 ret = yin_parse_qname(ctx, kw, subelem, exts);
3489 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003490 case LY_STMT_UNITS:
3491 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3492 break;
3493 case LY_STMT_IMPORT:
3494 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3495 break;
3496 case LY_STMT_INCLUDE:
3497 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3498 break;
3499 case LY_STMT_INPUT:
3500 case LY_STMT_OUTPUT:
3501 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3502 break;
3503 case LY_STMT_LEAF:
3504 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3505 break;
3506 case LY_STMT_LEAF_LIST:
3507 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3508 break;
3509 case LY_STMT_LENGTH:
3510 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3511 break;
3512 case LY_STMT_LIST:
3513 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3514 break;
3515 case LY_STMT_MANDATORY:
3516 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3517 break;
3518 case LY_STMT_MAX_ELEMENTS:
3519 case LY_STMT_MIN_ELEMENTS:
3520 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3521 break;
3522 case LY_STMT_MODIFIER:
3523 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3524 break;
3525 case LY_STMT_MUST:
3526 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3527 break;
3528 case LY_STMT_NAMESPACE:
3529 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3530 break;
3531 case LY_STMT_NOTIFICATION:
3532 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3533 break;
3534 case LY_STMT_ORDERED_BY:
3535 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3536 break;
3537 case LY_STMT_PATH:
3538 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3539 break;
3540 case LY_STMT_PATTERN:
3541 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3542 break;
3543 case LY_STMT_VALUE:
3544 case LY_STMT_POSITION:
3545 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3546 break;
3547 case LY_STMT_PREFIX:
3548 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3549 break;
3550 case LY_STMT_RANGE:
3551 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3552 break;
3553 case LY_STMT_REFINE:
3554 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3555 break;
3556 case LY_STMT_REQUIRE_INSTANCE:
3557 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3558 break;
3559 case LY_STMT_REVISION:
3560 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3561 break;
3562 case LY_STMT_REVISION_DATE:
3563 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3564 break;
3565 case LY_STMT_STATUS:
3566 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3567 break;
3568 case LY_STMT_TYPE:
3569 ret = yin_parse_type(ctx, current_element, subelem);
3570 break;
3571 case LY_STMT_TYPEDEF:
3572 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3573 break;
3574 case LY_STMT_UNIQUE:
3575 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3576 break;
3577 case LY_STMT_USES:
3578 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3579 break;
3580 case LY_STMT_WHEN:
3581 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3582 break;
3583 case LY_STMT_YANG_VERSION:
3584 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3585 break;
3586 case LY_STMT_YIN_ELEMENT:
3587 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3588 break;
3589 case LY_STMT_ARG_TEXT:
3590 case LY_STMT_ARG_VALUE:
3591 /* TODO what to do with content/attributes? */
3592 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3593 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3594 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3595 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3596 }
3597 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3598 break;
3599 default:
3600 LOGINT(ctx->xmlctx->ctx);
3601 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003602 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003603 LY_CHECK_GOTO(ret, cleanup);
3604 subelem = NULL;
3605
3606 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003607 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003608 } else {
3609 LY_CHECK_RET(ret);
3610 /* elements with text or none content */
3611 /* save text content, if text_content isn't set, it's just ignored */
3612 /* no resources are allocated in this branch, no need to use cleanup label */
3613 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3614 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003615 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 +01003616 LY_CHECK_RET(!*text_content, LY_EMEM);
3617 }
3618
3619 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003620 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003621
David Sedlák8b754462019-07-25 16:22:13 +02003622 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3623 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003624
3625cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003626 return ret;
3627}
3628
David Sedlákaa98bba2019-09-12 11:52:14 +02003629/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003630 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003631 *
3632 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003633 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003634 *
3635 * @return LY_ERR values.
3636 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003637LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003638yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003639{
David Sedlák81497a32019-08-13 16:56:26 +02003640 LY_ERR ret = LY_SUCCESS;
3641 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003642 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003643
Michal Vaskoc3781c32020-10-06 14:04:08 +02003644 mod->is_submod = 0;
3645
Michal Vaskob36053d2020-03-26 15:49:30 +01003646 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3647 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003648 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003649 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3650 LY_STMT_ANYXML, &mod->data, 0,
3651 LY_STMT_AUGMENT, &mod->augments, 0,
3652 LY_STMT_CHOICE, &mod->data, 0,
3653 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3654 LY_STMT_CONTAINER, &mod->data, 0,
3655 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3656 LY_STMT_DEVIATION, &mod->deviations, 0,
3657 LY_STMT_EXTENSION, &mod->extensions, 0,
3658 LY_STMT_FEATURE, &mod->features, 0,
3659 LY_STMT_GROUPING, &mod->groupings, 0,
3660 LY_STMT_IDENTITY, &mod->identities, 0,
3661 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3662 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3663 LY_STMT_LEAF, &mod->data, 0,
3664 LY_STMT_LEAF_LIST, &mod->data, 0,
3665 LY_STMT_LIST, &mod->data, 0,
3666 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3667 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3668 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3669 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3670 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3671 LY_STMT_REVISION, &mod->revs, 0,
3672 LY_STMT_RPC, &mod->rpcs, 0,
3673 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3674 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003675 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003676 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003677
Michal Vaskob36053d2020-03-26 15:49:30 +01003678 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003679 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003680 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003681
David Sedláked809f12019-09-13 10:15:11 +02003682 /* finalize parent pointers to the reallocated items */
3683 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3684
3685 /* submodules share the namespace with the module names, so there must not be
3686 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003687 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003688 if (dup) {
3689 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3690 return LY_EVALID;
3691 }
3692
3693 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003694}
3695
Michal Vaskoafac7822020-10-20 14:22:26 +02003696/**
3697 * @brief Parse submodule element.
3698 *
3699 * @param[in,out] ctx Yin parser context for logging and to store current state.
3700 * @param[in] mod_attrs Attributes of submodule element.
3701 * @param[out] submod Parsed submodule structure.
3702 *
3703 * @return LY_ERR values.
3704 */
David Sedlák3b4db242018-10-19 16:11:01 +02003705LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003706yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003707{
David Sedlák81497a32019-08-13 16:56:26 +02003708 LY_ERR ret = LY_SUCCESS;
3709 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003710 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003711
Michal Vaskoc3781c32020-10-06 14:04:08 +02003712 submod->is_submod = 1;
3713
Michal Vaskob36053d2020-03-26 15:49:30 +01003714 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3715 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003716 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003717 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3718 LY_STMT_ANYXML, &submod->data, 0,
3719 LY_STMT_AUGMENT, &submod->augments, 0,
3720 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3721 LY_STMT_CHOICE, &submod->data, 0,
3722 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3723 LY_STMT_CONTAINER, &submod->data, 0,
3724 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3725 LY_STMT_DEVIATION, &submod->deviations, 0,
3726 LY_STMT_EXTENSION, &submod->extensions, 0,
3727 LY_STMT_FEATURE, &submod->features, 0,
3728 LY_STMT_GROUPING, &submod->groupings, 0,
3729 LY_STMT_IDENTITY, &submod->identities, 0,
3730 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3731 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3732 LY_STMT_LEAF, &submod->data, 0,
3733 LY_STMT_LEAF_LIST, &submod->data, 0,
3734 LY_STMT_LIST, &submod->data, 0,
3735 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3736 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3737 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3738 LY_STMT_REVISION, &submod->revs, 0,
3739 LY_STMT_RPC, &submod->rpcs, 0,
3740 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3741 LY_STMT_USES, &submod->data, 0,
3742 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3743 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003744
Michal Vaskob36053d2020-03-26 15:49:30 +01003745 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003746 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003747 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003748
David Sedláked809f12019-09-13 10:15:11 +02003749 /* finalize parent pointers to the reallocated items */
3750 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3751
3752 /* submodules share the namespace with the module names, so there must not be
3753 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003754 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003755 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
David Sedláked809f12019-09-13 10:15:11 +02003756 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3757 return LY_EVALID;
3758 }
3759
3760 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003761}
3762
3763LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003764yin_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 +02003765 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003766{
Radek Krejcid6b76452019-09-03 17:03:03 +02003767 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003768 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003769 struct lysp_submodule *mod_p = NULL;
3770
3771 /* create context */
3772 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003773 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003774 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003775 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003776
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003777 mod_p = calloc(1, sizeof *mod_p);
3778 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3779 mod_p->mod = main_ctx->parsed_mod->mod;
3780 mod_p->parsing = 1;
3781 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3782
David Sedlák1b623122019-08-05 15:27:49 +02003783 /* map the typedefs and groupings list from main context to the submodule's context */
3784 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3785 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3786
David Sedlák8985a142019-07-31 16:43:06 +02003787 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003788 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 +02003789 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003790 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003791 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3792 ret = LY_EINVAL;
3793 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003794 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003795 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003796 ret = LY_EVALID;
3797 goto cleanup;
3798 }
3799
Michal Vaskob36053d2020-03-26 15:49:30 +01003800 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003801 LY_CHECK_GOTO(ret, cleanup);
3802
David Sedlákbf8a2b72019-08-14 16:48:10 +02003803 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003804 while (isspace(in->current[0])) {
3805 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003806 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003807 if (in->current[0]) {
3808 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003809 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003810 ret = LY_EVALID;
3811 goto cleanup;
3812 }
3813
David Sedlák8985a142019-07-31 16:43:06 +02003814 mod_p->parsing = 0;
3815 *submod = mod_p;
3816
3817cleanup:
3818 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003819 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003820 yin_parser_ctx_free(*yin_ctx);
3821 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003822 }
David Sedlák8985a142019-07-31 16:43:06 +02003823 return ret;
3824}
3825
3826LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003827yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003828{
David Sedláke4889912018-11-02 09:52:40 +01003829 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003830 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003831 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003832
David Sedlák8985a142019-07-31 16:43:06 +02003833 /* create context */
3834 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003835 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003836 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003837 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003838
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003839 mod_p = calloc(1, sizeof *mod_p);
3840 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3841 mod_p->mod = mod;
3842 mod_p->parsing = 1;
3843 (*yin_ctx)->parsed_mod = mod_p;
3844
David Sedlák8985a142019-07-31 16:43:06 +02003845 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003846 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 +02003847 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003848 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003849 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 +01003850 ret = LY_EINVAL;
3851 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003852 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003853 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003854 ret = LY_EVALID;
3855 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003856 }
3857
David Sedlák00250342019-06-21 14:19:39 +02003858 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003859 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003860 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003861
David Sedlákbf8a2b72019-08-14 16:48:10 +02003862 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003863 while (isspace(in->current[0])) {
3864 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003865 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003866 if (in->current[0]) {
3867 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003868 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003869 ret = LY_EVALID;
3870 goto cleanup;
3871 }
3872
David Sedlák3017da42019-02-15 09:48:04 +01003873 mod_p->parsing = 0;
3874 mod->parsed = mod_p;
3875
3876cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003877 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003878 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003879 yin_parser_ctx_free(*yin_ctx);
3880 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003881 }
David Sedlák2e411422018-12-17 02:35:39 +01003882 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003883}