blob: 597fc6e13b133e4027ceafba230ffba77bf4e975 [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>
Radek Krejci47fab892020-11-05 17:02:41 +010019#include <stdint.h>
David Sedlák3b4db242018-10-19 16:11:01 +020020#include <stdio.h>
21#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020022#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020023
Radek Krejci535ea9f2020-05-29 16:01:05 +020024#include "common.h"
David Sedlákf824ad52018-10-14 23:58:15 +020025#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020026#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010027#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020028#include "in_internal.h"
Radek Krejci47fab892020-11-05 17:02:41 +010029#include "log.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020030#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020031#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020032#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020033#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020034#include "tree.h"
35#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020036#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020037#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020038
David Sedlák2b214ac2019-06-06 16:11:03 +020039/**
40 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020041 *
David Sedlák2b214ac2019-06-06 16:11:03 +020042 * @param ns Namespace URI to check.
43 *
44 * @return true if ns equals YIN_NS_URI false otherwise.
45 */
46#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
47
Michal Vaskoafac7822020-10-20 14:22:26 +020048enum yin_argument {
49 YIN_ARG_UNKNOWN = 0, /**< parsed argument can not be matched with any supported yin argument keyword */
50 YIN_ARG_NAME, /**< argument name */
51 YIN_ARG_TARGET_NODE, /**< argument target-node */
52 YIN_ARG_MODULE, /**< argument module */
53 YIN_ARG_VALUE, /**< argument value */
54 YIN_ARG_TEXT, /**< argument text */
55 YIN_ARG_CONDITION, /**< argument condition */
56 YIN_ARG_URI, /**< argument uri */
57 YIN_ARG_DATE, /**< argument data */
58 YIN_ARG_TAG, /**< argument tag */
59 YIN_ARG_NONE /**< empty (special value) */
60};
61
Michal Vasko22df3f02020-08-24 13:29:22 +020062const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020063 [YIN_ARG_NAME] = "name",
64 [YIN_ARG_TARGET_NODE] = "target-node",
65 [YIN_ARG_MODULE] = "module",
66 [YIN_ARG_VALUE] = "value",
67 [YIN_ARG_TEXT] = "text",
68 [YIN_ARG_CONDITION] = "condition",
69 [YIN_ARG_URI] = "uri",
70 [YIN_ARG_DATE] = "date",
71 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020072 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020073};
74
Michal Vaskoafac7822020-10-20 14:22:26 +020075#define yin_attr2str(STMT) yin_attr_list[STMT]
76
77#define VALID_VALS1 " Only valid value is \"%s\"."
78#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
79#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
80#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
81
82/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
83#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
84 kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS || \
85 kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE || \
86 kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
87
88/* flags to set constraints of subelements */
89#define YIN_SUBELEM_MANDATORY 0x01 /**< is set when subelement is mandatory */
90#define YIN_SUBELEM_UNIQUE 0x02 /**< is set when subelement is unique */
91#define YIN_SUBELEM_FIRST 0x04 /**< is set when subelement is actually yang argument mapped to yin element */
92#define YIN_SUBELEM_VER2 0x08 /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
93
94#define YIN_SUBELEM_PARSED 0x80 /**< is set during parsing when given subelement is encountered for the first
95 time to simply check validity of given constraints */
96
97struct yin_subelement {
98 enum ly_stmt type; /**< type of keyword */
99 void *dest; /**< meta infromation passed to responsible function (mostly information about where parsed subelement should be stored) */
100 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 */
101};
102
103/* Meta information passed to yin_parse_argument function,
104 holds information about where content of argument element will be stored. */
105struct yin_argument_meta {
106 uint16_t *flags; /**< Argument flags */
107 const char **argument; /**< Argument value */
108};
109
110/**
111 * @brief Meta information passed to functions working with tree_schema,
112 * that require additional information about parent node.
113 */
114struct tree_node_meta {
115 struct lysp_node *parent; /**< parent node */
116 struct lysp_node **nodes; /**< linked list of siblings */
117};
118
119/**
120 * @brief Meta information passed to yin_parse_import function.
121 */
122struct import_meta {
123 const char *prefix; /**< module prefix. */
124 struct lysp_import **imports; /**< imports to add to. */
125};
126
127/**
128 * @brief Meta information passed to yin_parse_include function.
129 */
130struct include_meta {
131 const char *name; /**< Module/submodule name. */
132 struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
133};
134
135/**
136 * @brief Meta information passed to yin_parse_inout function.
137 */
138struct inout_meta {
139 struct lysp_node *parent; /**< Parent node. */
Radek Krejci2a9fc652021-01-22 17:44:34 +0100140 struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
Michal Vaskoafac7822020-10-20 14:22:26 +0200141};
142
143/**
144 * @brief Meta information passed to yin_parse_minmax function.
145 */
146struct minmax_dev_meta {
147 uint32_t *lim; /**< min/max value to write to. */
148 uint16_t *flags; /**< min/max flags to write to. */
149 struct lysp_ext_instance **exts; /**< extension instances to add to. */
150};
151
152LY_ERR yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
153 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts);
154
155/**
156 * @brief Match yang keyword from yin data.
157 *
158 * @param[in,out] ctx Yin parser context for logging and to store current state.
159 * @param[in] name Start of keyword name
160 * @param[in] name_len Lenght of keyword name.
161 * @param[in] prefix Start of keyword prefix.
162 * @param[in] prefix_len Lenght of prefix.
163 * @param[in] parrent Identification of parrent element, use LY_STMT_NONE for elements without parrent.
164 *
165 * @return yang_keyword values.
166 */
Radek Krejcid6b76452019-09-03 17:03:03 +0200167enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +0100168yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +0200169 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +0200170{
David Sedlák8f7a1172019-06-20 14:42:18 +0200171 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +0200172 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200173 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +0200174 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +0200175
Michal Vasko69730152020-10-09 16:30:07 +0200176 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200177 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +0200178 }
179
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200180 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200181 if (ns) {
182 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200183 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200184 }
185 } else {
186 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +0200187 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200188 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200189
Michal Vasko63f3d842020-07-08 10:10:14 +0200190 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
191 start = in->current;
Radek Krejcid54412f2020-12-17 20:25:35 +0100192 kw = lysp_match_kw(in, NULL);
Michal Vasko63f3d842020-07-08 10:10:14 +0200193 name = in->current;
194 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +0200195
196 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +0200197 /* 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 +0200198 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200199 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +0200200 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200201 return kw;
202 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +0200203 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +0200204 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +0200205 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +0200206 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +0200207 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200208 }
209}
210
Michal Vaskoafac7822020-10-20 14:22:26 +0200211/**
212 * @brief Match argument name.
213 *
214 * @param[in] name String representing name.
215 * @param[in] len Lenght of the name.
216 *
217 * @return yin_argument values.
218 */
David Sedlákc5b20842019-08-13 10:18:31 +0200219enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200220yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200221{
David Sedlákc5b20842019-08-13 10:18:31 +0200222 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200223 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200224
David Sedlák7ff55a92019-06-17 11:11:41 +0200225 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200226
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200227#define READ_INC(LEN) already_read += LEN
228#define ARG_SET(STMT) arg=STMT
229#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100230
David Sedlák1c8b2702019-02-22 11:03:02 +0100231 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100232 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200233 READ_INC(1);
234 if (ARG_CHECK("ondition", 8)) {
235 ARG_SET(YIN_ARG_CONDITION);
236 }
David Sedlák3b4db242018-10-19 16:11:01 +0200237 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200238
David Sedlák94de2aa2019-02-15 12:42:11 +0100239 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200240 READ_INC(1);
241 if (ARG_CHECK("ate", 3)) {
242 ARG_SET(YIN_ARG_DATE);
243 }
David Sedlák3b4db242018-10-19 16:11:01 +0200244 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200245
David Sedlák94de2aa2019-02-15 12:42:11 +0100246 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200247 READ_INC(1);
248 if (ARG_CHECK("odule", 5)) {
249 ARG_SET(YIN_ARG_MODULE);
250 }
David Sedlák872c7b42018-10-26 13:15:20 +0200251 break;
252
David Sedlák94de2aa2019-02-15 12:42:11 +0100253 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200254 READ_INC(1);
255 if (ARG_CHECK("ame", 3)) {
256 ARG_SET(YIN_ARG_NAME);
257 }
David Sedlák872c7b42018-10-26 13:15:20 +0200258 break;
259
David Sedlák94de2aa2019-02-15 12:42:11 +0100260 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200261 READ_INC(1);
262 if (ARG_CHECK("a", 1)) {
263 if (ARG_CHECK("g", 1)) {
264 ARG_SET(YIN_ARG_TAG);
265 } else if (ARG_CHECK("rget-node", 9)) {
266 ARG_SET(YIN_ARG_TARGET_NODE);
267 }
268 } else if (ARG_CHECK("ext", 3)) {
269 ARG_SET(YIN_ARG_TEXT);
270 }
David Sedlák3b4db242018-10-19 16:11:01 +0200271 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200272
David Sedlák94de2aa2019-02-15 12:42:11 +0100273 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200274 READ_INC(1);
275 if (ARG_CHECK("ri", 2)) {
276 ARG_SET(YIN_ARG_URI);
277 }
David Sedlák3b4db242018-10-19 16:11:01 +0200278 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200279
David Sedlák94de2aa2019-02-15 12:42:11 +0100280 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200281 READ_INC(1);
282 if (ARG_CHECK("alue", 4)) {
283 ARG_SET(YIN_ARG_VALUE);
284 }
David Sedlák3b4db242018-10-19 16:11:01 +0200285 break;
286 }
287
David Sedlákc10e7902018-12-17 02:17:59 +0100288 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200289 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200290 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200291 }
292
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200293#undef ARG_CHECK
294#undef ARG_SET
295#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100296
David Sedlák872c7b42018-10-26 13:15:20 +0200297 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200298}
299
Radek Krejcid6b76452019-09-03 17:03:03 +0200300#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
301 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
302 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
303 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200304
Radek Krejcid6b76452019-09-03 17:03:03 +0200305#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 +0200306
David Sedlák26ea1432019-08-14 13:42:23 +0200307/**
308 * @brief Free subelems information allocated on heap.
309 *
310 * @param[in] count Size of subelems array.
311 * @param[in] subelems Subelems array to free.
312 */
David Sedlák81497a32019-08-13 16:56:26 +0200313static void
314subelems_deallocator(size_t count, struct yin_subelement *subelems)
315{
Michal Vaskod989ba02020-08-24 10:59:24 +0200316 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200317 if (HAS_META(subelems[i].type)) {
318 free(subelems[i].dest);
319 }
320 }
321
322 free(subelems);
323}
324
David Sedlák26ea1432019-08-14 13:42:23 +0200325/**
326 * @brief Allocate subelems information on heap.
327 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200328 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200329 * @param[in] count Number of subelements.
330 * @param[in] parent Parent node if any.
331 * @param[out] result Allocated subelems array.
332 *
333 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
334 */
David Sedlák81497a32019-08-13 16:56:26 +0200335static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100336subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200337 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200338{
339 va_list ap;
340
341 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200342 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200343
344 va_start(ap, result);
345 for (size_t i = 0; i < count; ++i) {
346 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200347 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200348 /* DEST */
349 if (IS_NODE_ELEM((*result)[i].type)) {
350 struct tree_node_meta *node_meta = NULL;
351 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200352 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200353 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200354 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200355 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200356 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200357 struct import_meta *imp_meta = NULL;
358 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200359 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200360 imp_meta->prefix = va_arg(ap, const char *);
361 imp_meta->imports = va_arg(ap, struct lysp_import **);
362 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200363 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200364 struct include_meta *inc_meta = NULL;
365 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200366 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200367 inc_meta->name = va_arg(ap, const char *);
368 inc_meta->includes = va_arg(ap, struct lysp_include **);
369 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200370 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200371 struct inout_meta *inout_meta = NULL;
372 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200373 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200374 inout_meta->parent = parent;
Radek Krejci2a9fc652021-01-22 17:44:34 +0100375 inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
David Sedlák81497a32019-08-13 16:56:26 +0200376 (*result)[i].dest = inout_meta;
377 } else {
378 (*result)[i].dest = va_arg(ap, void *);
379 }
380 /* FLAGS */
381 (*result)[i].flags = va_arg(ap, int);
382 }
383 va_end(ap);
384
385 return LY_SUCCESS;
386
David Sedlákbf8a2b72019-08-14 16:48:10 +0200387mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200388 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100389 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200390 return LY_EMEM;
391}
392
Michal Vaskoafac7822020-10-20 14:22:26 +0200393/**
394 * @brief Check that val is valid UTF8 character sequence of val_type.
395 * Doesn't check empty string, only character validity.
396 *
397 * @param[in] ctx Yin parser context for logging.
398 * @param[in] val_type Type of the input string to select method of checking character validity.
399 *
400 * @return LY_ERR values.
401 */
David Sedlák8f7a1172019-06-20 14:42:18 +0200402LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100403yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200404{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200405 uint8_t prefix = 0;
406 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100407 size_t utf8_char_len, already_read = 0;
408 const char *val;
409
410 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
411
412 val = ctx->xmlctx->value;
413 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200414 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200415 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200416 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100417 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200418
419 switch (val_type) {
420 case Y_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, NULL));
David Sedlák4a650532019-07-10 11:55:18 +0200422 break;
423 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200424 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 +0200425 break;
426 case Y_STR_ARG:
427 case Y_MAYBE_STR_ARG:
428 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
429 break;
430 }
431 }
432
433 return LY_SUCCESS;
434}
435
David Sedlákb4e44562019-07-04 15:42:12 +0200436/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100437 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200438 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200439 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200440 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
441 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200442 * @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 +0200443 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200444 * @param[in] current_element Identification of current element, used for logging.
445 *
446 * @return LY_ERR values.
447 */
448static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100449yin_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 +0200450 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200451{
David Sedlákc5b20842019-08-13 10:18:31 +0200452 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200453 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200454
David Sedlák1bccdfa2019-06-17 15:55:27 +0200455 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100456 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200457 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100458 if (!ctx->xmlctx->prefix) {
459 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200460 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100461 /* skip it */
462 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200463 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200464 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200465 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200466 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100467
468 /* go to value */
469 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
470 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200471 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 +0200472 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200473 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100474 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200475 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200476 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200477 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100478 } else {
479 /* skip it */
480 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200481 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100482
483 /* next attribute */
484 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200485 }
486
David Sedlák292763b2019-07-09 11:10:53 +0200487 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200488 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100489 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200490 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200491 return LY_EVALID;
492 }
493
494 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200495}
496
David Sedlákd6e56892019-07-01 15:40:24 +0200497/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200498 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200499 *
500 * @param[in] type Type of wanted record.
501 * @param[in] array_size Size of array.
502 * @param[in] array Searched array.
503 *
504 * @return Pointer to desired record on success, NULL if element is not in the array.
505 */
David Sedlákb4e44562019-07-04 15:42:12 +0200506static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200507get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200508{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200509 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200510 if (array[u].type == type) {
511 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200512 }
513 }
David Sedlákd6e56892019-07-01 15:40:24 +0200514 return NULL;
515}
516
David Sedlákbba38e52019-07-09 15:20:01 +0200517/**
518 * @brief Helper function to check mandatory constraint of subelement.
519 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200520 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200521 * @param[in] subelem_info Array of information about subelements.
522 * @param[in] subelem_info_size Size of subelem_info array.
523 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
524 *
525 * @return LY_ERR values.
526 */
527static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100528yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200529 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200530{
David Sedlákb0faad82019-07-04 14:28:59 +0200531 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200532 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200533 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200534 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200535 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200536 return LY_EVALID;
537 }
538 }
539
540 return LY_SUCCESS;
541}
542
David Sedlákbba38e52019-07-09 15:20:01 +0200543/**
544 * @brief Helper function to check "first" constraint of subelement.
545 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200546 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200547 * @param[in] subelem_info Array of information about subelements.
548 * @param[in] subelem_info_size Size of subelem_info array.
549 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200550 * @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 +0200551 *
552 * @return LY_ERR values.
553 */
554static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100555yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200556 signed char subelem_info_size, enum ly_stmt current_element,
557 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200558{
David Sedlákb0faad82019-07-04 14:28:59 +0200559 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200560 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200561 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200562 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200563 return LY_EVALID;
564 }
565 }
566
567 return LY_SUCCESS;
568}
569
David Sedlákbba38e52019-07-09 15:20:01 +0200570/**
David Sedlákb4e44562019-07-04 15:42:12 +0200571 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
572 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200573 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200574 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200575 * @param[in] kw Type of current element.
576 * @param[out] value Where value of attribute should be stored.
577 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200578 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200579 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200580 * @return LY_ERR values.
581 */
David Sedlákb4e44562019-07-04 15:42:12 +0200582static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100583yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200584 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200585{
Michal Vaskob36053d2020-03-26 15:49:30 +0100586 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
587 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
Radek Krejcif13b87b2020-12-01 22:02:17 +0100588 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200589 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
590 };
David Sedlákb4e44562019-07-04 15:42:12 +0200591
Radek Krejcif13b87b2020-12-01 22:02:17 +0100592 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200593}
594
595/**
David Sedlák6542aed2019-08-14 10:47:43 +0200596 * @brief Parse path element.
597 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200598 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200599 * @param[in] kw Type of current element.
600 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200601 * @return LY_ERR values.
602 */
603static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100604yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200605{
Michal Vasko004d3152020-06-11 19:59:22 +0200606 LY_ERR ret;
607 const char *str_path;
608
609 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 +0200610 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 +0200611 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200612 lydict_remove(ctx->xmlctx->ctx, str_path);
613 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200614 type->flags |= LYS_SET_PATH;
615
616 return LY_SUCCESS;
617}
618
619/**
David Sedlákd3983112019-07-12 11:20:56 +0200620 * @brief Parse pattern element.
621 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200622 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200623 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200624 * @return LY_ERR values.
625 */
626static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100627yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200628{
629 const char *real_value = NULL;
630 char *saved_value = NULL;
631 struct lysp_restr *restr;
632
Michal Vaskob36053d2020-03-26 15:49:30 +0100633 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
634 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
635 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 +0200636 size_t len = strlen(real_value);
637
638 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100639 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200640 memmove(saved_value + 1, real_value, len);
Michal Vaskoe180ed02021-02-05 16:31:20 +0100641 lydict_remove(ctx->xmlctx->ctx, real_value);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100642 saved_value[0] = LYSP_RESTR_PATTERN_ACK;
David Sedlákd3983112019-07-12 11:20:56 +0200643 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200644 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200645 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200646 type->flags |= LYS_SET_PATTERN;
647
Radek Krejcif13b87b2020-12-01 22:02:17 +0100648 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200649 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
650 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
651 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
652 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
653 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
654 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
655 };
Michal Vasko69730152020-10-09 16:30:07 +0200656
Radek Krejcif13b87b2020-12-01 22:02:17 +0100657 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200658}
659
David Sedlákc5b20842019-08-13 10:18:31 +0200660/**
661 * @brief Parse fraction-digits element.
662 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200663 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200664 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200665 * @return LY_ERR values.
666 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200667static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100668yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200669{
670 const char *temp_val = NULL;
671 char *ptr;
672 unsigned long int num;
673
Michal Vaskob36053d2020-03-26 15:49:30 +0100674 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
675 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 +0200676
Michal Vasko69730152020-10-09 16:30:07 +0200677 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200678 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100679 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200680 return LY_EVALID;
681 }
682
683 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100684 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlákf75d55e2019-07-12 16:52:50 +0200685 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200686 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100687 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200688 return LY_EVALID;
689 }
Radek Krejcif13b87b2020-12-01 22:02:17 +0100690 if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200691 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100692 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200693 return LY_EVALID;
694 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100695 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200696 type->fraction_digits = num;
697 type->flags |= LYS_SET_FRDIGITS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100698 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200699 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
700 };
Michal Vasko69730152020-10-09 16:30:07 +0200701
Radek Krejcif13b87b2020-12-01 22:02:17 +0100702 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200703}
704
David Sedlák07869a52019-07-12 14:28:19 +0200705/**
David Sedlák43801c92019-08-05 15:58:54 +0200706 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200707 *
708 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200709 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200710 * @return LY_ERR values.
711 */
David Sedlákca36c422019-07-12 12:47:55 +0200712static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100713yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200714{
David Sedlák07869a52019-07-12 14:28:19 +0200715 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200716
Michal Vaskob36053d2020-03-26 15:49:30 +0100717 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200718 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100719 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
720 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 +0200721 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100722 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200723 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200724
Radek Krejcif13b87b2020-12-01 22:02:17 +0100725 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200726 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
727 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
728 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
729 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
730 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
731 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
732 };
Michal Vasko69730152020-10-09 16:30:07 +0200733
Radek Krejcif13b87b2020-12-01 22:02:17 +0100734 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200735}
736
737/**
738 * @brief Parse bit element.
739 *
740 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200741 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200742 * @return LY_ERR values.
743 */
744static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100745yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200746{
747 struct lysp_type_enum *en;
748
Michal Vaskob36053d2020-03-26 15:49:30 +0100749 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200750 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100751 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
752 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 +0200753 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
754
Radek Krejcif13b87b2020-12-01 22:02:17 +0100755 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200756 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
757 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
758 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
759 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
760 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
761 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
762 };
Michal Vasko69730152020-10-09 16:30:07 +0200763
Radek Krejcif13b87b2020-12-01 22:02:17 +0100764 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200765}
766
David Sedlákd3983112019-07-12 11:20:56 +0200767/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200768 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
769 * more instances, such as base or if-feature.
770 *
771 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200772 * @param[in] kw Type of current element.
773 * @param[out] values Parsed values to add to.
774 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200775 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200776 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200777 * @return LY_ERR values.
778 */
779static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100780yin_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 +0200781 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200782{
783 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200784
Michal Vaskob36053d2020-03-26 15:49:30 +0100785 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200786 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100787 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200788 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
789 };
David Sedlák968ac342019-07-11 15:17:59 +0200790
Michal Vaskob36053d2020-03-26 15:49:30 +0100791 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
792 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200793
Radek Krejcif13b87b2020-12-01 22:02:17 +0100794 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200795}
796
797/**
David Sedlák6542aed2019-08-14 10:47:43 +0200798 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
799 *
800 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200801 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200802 * @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 +0200803 * @param[in] arg_type Expected type of attribute.
804 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200805 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200806 * @return LY_ERR values.
807 */
808static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100809yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200810 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200811{
812 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100813 LY_CHECK_RET(yin_parse_simple_element(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 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100816 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200817 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200818 }
819
820 return LY_SUCCESS;
821}
822
823/**
824 * @brief Parse base element.
825 *
826 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200827 * @param[in] parent Identification of parent element.
828 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200829 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200830 * @return LY_ERR values.
831 */
832static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100833yin_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 +0200834{
835 struct lysp_type *type = NULL;
836
Radek Krejcid6b76452019-09-03 17:03:03 +0200837 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200838 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100839 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200840 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200841 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200842 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100843 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200844 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200845 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100846 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200847 return LY_EINT;
848 }
849
850 return LY_SUCCESS;
851}
852
853/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200854 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200855 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200856 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100857 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200858 * @return LY_ERR values.
859 */
860static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100861yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200862{
863 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100864 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200865 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
866 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200867
868 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100869 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
870 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 +0200871 if (strcmp(temp_val, "true") == 0) {
872 type->require_instance = 1;
873 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200874 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200875 "require-instance", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100876 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200877 return LY_EVALID;
878 }
Michal Vaskoe180ed02021-02-05 16:31:20 +0100879 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200880
Radek Krejcif13b87b2020-12-01 22:02:17 +0100881 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200882}
883
884/**
David Sedlákce77bf52019-07-11 16:59:31 +0200885 * @brief Parse modifier element.
886 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200887 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200888 * @param[in,out] pat Value to write to.
889 * @param[in,out] exts Extension instances to add to.
890 *
891 * @return LY_ERR values.
892 */
893static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100894yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200895{
David Sedlákd3983112019-07-12 11:20:56 +0200896 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200897 const char *temp_val;
898 char *modified_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100899 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200900 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
901 };
David Sedlákce77bf52019-07-11 16:59:31 +0200902
Michal Vaskob36053d2020-03-26 15:49:30 +0100903 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
904 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 +0200905 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200906 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200907 "modifier", "invert-match");
Michal Vaskoe180ed02021-02-05 16:31:20 +0100908 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200909 return LY_EVALID;
910 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100911 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200912
913 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200914 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100915 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200916 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100917 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200918
919 /* modify the new value */
Radek Krejcif13b87b2020-12-01 22:02:17 +0100920 modified_val[0] = LYSP_RESTR_PATTERN_NACK;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200921 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200922
Radek Krejcif13b87b2020-12-01 22:02:17 +0100923 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200924}
925
926/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200927 * @brief Parse a restriction element (length, range or one instance of must).
928 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200929 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200930 * @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 +0200931 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200932 */
933static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100934yin_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 +0200935{
Radek Krejcid6b76452019-09-03 17:03:03 +0200936 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
Radek Krejcif13b87b2020-12-01 22:02:17 +0100937 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200938 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
939 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
940 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
941 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
942 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
943 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200944 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200945 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200946
Michal Vaskob36053d2020-03-26 15:49:30 +0100947 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200948 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200949 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100950
Radek Krejcif13b87b2020-12-01 22:02:17 +0100951 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200952}
953
954/**
David Sedlák6542aed2019-08-14 10:47:43 +0200955 * @brief Parse range element.
956 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200957 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200958 * @param[out] type Type structure to store parsed value and flags.
959 *
960 * @return LY_ERR values.
961 */
962static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100963yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200964{
965 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100966 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
967 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200968 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200969
970 return LY_SUCCESS;
971}
972
973/**
974 * @brief Parse length element.
975 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200976 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200977 * @param[out] type Type structure to store parsed value and flags.
978 *
979 * @return LY_ERR values.
980 */
981static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100982yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200983{
984 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100985 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
986 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200987 type->flags |= LYS_SET_LENGTH;
988
989 return LY_SUCCESS;
990}
991
992/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200993 * @brief Parse must element.
994 *
995 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200996 * @param[in,out] restrs Restrictions to add to.
997 *
998 * @return LY_ERR values.
999 */
1000static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001001yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001002{
1003 struct lysp_restr *restr;
1004
Michal Vaskob36053d2020-03-26 15:49:30 +01001005 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1006 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +02001007}
1008
1009/**
Michal Vasko7f45cf22020-10-01 12:49:44 +02001010 * @brief Parse a node id into an array.
1011 *
1012 * @param[in,out] ctx YIN parser context for logging and to store current state.
1013 * @param[in] kw Type of current element.
1014 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1015 * @param[in,out] exts Extension instances to add to.
1016 *
1017 * @return LY_ERR values.
1018 */
1019static LY_ERR
1020yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
1021 struct lysp_ext_instance **exts)
1022{
1023 struct lysp_qname *qname, **qnames;
1024
1025 switch (kw) {
1026 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001027 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1028 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +02001029 } else {
1030 qnames = (struct lysp_qname **)subinfo->dest;
1031 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001032 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001033 qname->mod = ctx->parsed_mod;
1034 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
1035 case LY_STMT_IF_FEATURE:
1036 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1037 qnames = (struct lysp_qname **)subinfo->dest;
1038 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1039 qname->mod = ctx->parsed_mod;
1040 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +02001041 default:
1042 break;
1043 }
1044
1045 LOGINT(ctx->xmlctx->ctx);
1046 return LY_EINT;
1047}
1048
1049/**
David Sedlák5545f5d2019-07-11 11:55:16 +02001050 * @brief Parse position or value element.
1051 *
1052 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001053 * @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 +02001054 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +02001055 *
1056 * @return LY_ERR values.
1057 */
1058static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001059yin_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 +02001060{
Radek Krejcid6b76452019-09-03 17:03:03 +02001061 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +02001062 const char *temp_val = NULL;
1063 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +02001064 long int num = 0;
1065 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +02001066
1067 /* set value flag */
1068 enm->flags |= LYS_SET_VALUE;
1069
1070 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +01001071 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1072 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +02001073 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +02001074 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +02001075 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 +02001076 goto error;
1077 }
1078
1079 /* convert value */
1080 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +02001081 if (kw == LY_STMT_VALUE) {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001082 num = strtol(temp_val, &ptr, LY_BASE_DEC);
Michal Vasko69730152020-10-09 16:30:07 +02001083 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +02001084 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 +02001085 goto error;
1086 }
1087 } else {
Radek Krejcif13b87b2020-12-01 22:02:17 +01001088 unum = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák5545f5d2019-07-11 11:55:16 +02001089 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +02001090 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 +02001091 goto error;
1092 }
1093 }
1094 /* check if whole argument value was converted */
1095 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001096 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +02001097 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +02001098 }
1099 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +02001100 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 +02001101 goto error;
1102 }
1103 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +02001104 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +02001105 enm->value = num;
1106 } else {
1107 enm->value = unum;
1108 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001109 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +02001110
1111 /* parse subelements */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001112 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001113 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1114 };
Michal Vasko69730152020-10-09 16:30:07 +02001115
Radek Krejcif13b87b2020-12-01 22:02:17 +01001116 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001117
David Sedlákbf8a2b72019-08-14 16:48:10 +02001118error:
Michal Vaskoe180ed02021-02-05 16:31:20 +01001119 lydict_remove(ctx->xmlctx->ctx, temp_val);
Michal Vaskob36053d2020-03-26 15:49:30 +01001120 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001121}
1122
David Sedlák05404f62019-07-24 14:11:53 +02001123/**
1124 * @brief Parse belongs-to element.
1125 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001126 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001127 * @param[out] submod Structure of submodule that is being parsed.
1128 * @param[in,out] exts Extension instances to add to.
1129 *
1130 * @return LY_ERR values
1131 */
1132static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001133yin_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 +02001134{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001135 const char *belongsto;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001136 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001137 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1138 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1139 };
David Sedlák05404f62019-07-24 14:11:53 +02001140
Michal Vaskob36053d2020-03-26 15:49:30 +01001141 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001142 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 +02001143 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001144 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 +02001145 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001146 lydict_remove(ctx->xmlctx->ctx, belongsto);
1147 return LY_EVALID;
1148 }
1149 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001150
Radek Krejcif13b87b2020-12-01 22:02:17 +01001151 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001152}
1153
David Sedlák5545f5d2019-07-11 11:55:16 +02001154/**
David Sedlákc1771b12019-07-10 15:55:46 +02001155 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001156 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001157 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001158 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001159 * @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 +02001160 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001161 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001162 *
1163 * @return LY_ERR values.
1164 */
1165static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001166yin_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 +02001167{
Radek Krejcid6b76452019-09-03 17:03:03 +02001168 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 +02001169
Radek Krejcif13b87b2020-12-01 22:02:17 +01001170 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001171 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1172 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1173 };
Michal Vasko69730152020-10-09 16:30:07 +02001174
David Sedlákdf2a9732019-08-07 13:23:16 +02001175 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001176 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1177 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 +02001178
David Sedlákdf2a9732019-08-07 13:23:16 +02001179 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001180 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001181}
1182
1183/**
David Sedlákc1771b12019-07-10 15:55:46 +02001184 * @brief Parse error-message element.
1185 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001186 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001187 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001188 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001189 *
1190 * @return LY_ERR values.
1191 */
1192static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001193yin_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 +02001194{
Radek Krejcif13b87b2020-12-01 22:02:17 +01001195 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001196 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1197 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1198 };
David Sedlákc1771b12019-07-10 15:55:46 +02001199
David Sedlákdf2a9732019-08-07 13:23:16 +02001200 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001201 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1202 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 +02001203
Radek Krejcif13b87b2020-12-01 22:02:17 +01001204 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001205}
1206
1207/**
David Sedlák6542aed2019-08-14 10:47:43 +02001208 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001209 *
1210 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001211 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001212 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001213 *
1214 * @return LY_ERR values.
1215 */
1216static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001217yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001218{
David Sedlák6542aed2019-08-14 10:47:43 +02001219 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001220
Radek Krejcid6b76452019-09-03 17:03:03 +02001221 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001222 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001223 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001224 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001225 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001226 type = (struct lysp_type *)subinfo->dest;
1227 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001228
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001229 type->pmod = ctx->parsed_mod;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001230
David Sedlák6542aed2019-08-14 10:47:43 +02001231 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001232 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001233 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001234 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001235 type->flags |= LYS_SET_TYPE;
1236 type = nested_type;
1237 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001238
Radek Krejcif13b87b2020-12-01 22:02:17 +01001239 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001240 {LY_STMT_BASE, type, 0},
1241 {LY_STMT_BIT, type, 0},
1242 {LY_STMT_ENUM, type, 0},
1243 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1244 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1245 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1246 {LY_STMT_PATTERN, type, 0},
1247 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1248 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1249 {LY_STMT_TYPE, type},
1250 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1251 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001252
1253 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1254 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01001255 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001256}
1257
David Sedlák1af868e2019-07-17 17:03:14 +02001258/**
1259 * @brief Parse max-elements element.
1260 *
1261 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001262 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001263 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001264 * @param[in,out] exts Extension instances to add to.
1265 *
1266 * @return LY_ERR values.
1267 */
1268static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001269yin_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 +02001270{
1271 const char *temp_val = NULL;
1272 char *ptr;
1273 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001274 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001275 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1276 };
David Sedlák374d2b32019-07-17 15:06:55 +02001277
David Sedlák1af868e2019-07-17 17:03:14 +02001278 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001279 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1280 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 +02001281 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 +02001282 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001283 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001284 return LY_EVALID;
1285 }
1286
1287 if (strcmp(temp_val, "unbounded")) {
1288 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001289 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák1af868e2019-07-17 17:03:14 +02001290 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001291 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001292 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001293 return LY_EVALID;
1294 }
1295 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001296 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001297 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001298 return LY_EVALID;
1299 }
1300 *max = num;
1301 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001302 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001303 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001304}
David Sedlák374d2b32019-07-17 15:06:55 +02001305
1306/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001307 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001308 *
1309 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001310 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001311 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001312 * @param[in,out] exts Extension instances to add to.
1313 *
1314 * @return LY_ERR values.
1315 */
1316static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001317yin_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 +02001318{
1319 const char *temp_val = NULL;
1320 char *ptr;
1321 unsigned long int num;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001322 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001323 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1324 };
David Sedlák09e18c92019-07-18 11:17:11 +02001325
1326 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001327 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1328 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 +02001329
Michal Vasko69730152020-10-09 16:30:07 +02001330 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001331 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001332 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001333 return LY_EVALID;
1334 }
1335
1336 errno = 0;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001337 num = strtoul(temp_val, &ptr, LY_BASE_DEC);
David Sedlák09e18c92019-07-18 11:17:11 +02001338 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001339 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001340 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001341 return LY_EVALID;
1342 }
Michal Vasko69730152020-10-09 16:30:07 +02001343 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001345 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001346 return LY_EVALID;
1347 }
1348 *min = num;
Michal Vaskoe180ed02021-02-05 16:31:20 +01001349 lydict_remove(ctx->xmlctx->ctx, temp_val);
Radek Krejcif13b87b2020-12-01 22:02:17 +01001350 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001351}
1352
David Sedláka2dad212019-07-18 12:45:19 +02001353/**
1354 * @brief Parse min-elements or max-elements element.
1355 *
1356 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001357 * @param[in] parent Identification of parent element.
1358 * @param[in] current Identification of current element.
1359 * @param[in] dest Where the parsed value and flags should be stored.
1360 *
1361 * @return LY_ERR values.
1362 */
David Sedlák09e18c92019-07-18 11:17:11 +02001363static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001364yin_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 +02001365{
Radek Krejcid6b76452019-09-03 17:03:03 +02001366 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1367 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 +02001368 uint32_t *lim;
1369 uint16_t *flags;
1370 struct lysp_ext_instance **exts;
1371
Radek Krejcid6b76452019-09-03 17:03:03 +02001372 if (parent == LY_STMT_LEAF_LIST) {
1373 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 +02001374 flags = &((struct lysp_node_leaflist *)dest)->flags;
1375 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001376 } else if (parent == LY_STMT_REFINE) {
1377 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001378 flags = &((struct lysp_refine *)dest)->flags;
1379 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001380 } else if (parent == LY_STMT_LIST) {
1381 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 +02001382 flags = &((struct lysp_node_list *)dest)->flags;
1383 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001384 } else {
1385 lim = ((struct minmax_dev_meta *)dest)->lim;
1386 flags = ((struct minmax_dev_meta *)dest)->flags;
1387 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001388 }
1389
Radek Krejcid6b76452019-09-03 17:03:03 +02001390 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001391 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001392 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001393 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001394 }
1395
1396 return LY_SUCCESS;
1397}
1398
1399/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001400 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001401 *
1402 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001403 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001404 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001405 *
1406 * @return LY_ERR values.
1407 */
1408static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001409yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001410{
1411 const char *temp_val;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001412 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001413 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1414 };
David Sedláka2dad212019-07-18 12:45:19 +02001415
Michal Vaskob36053d2020-03-26 15:49:30 +01001416 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1417 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 +02001418 if (strcmp(temp_val, "system") == 0) {
1419 *flags |= LYS_ORDBY_SYSTEM;
1420 } else if (strcmp(temp_val, "user") == 0) {
1421 *flags |= LYS_ORDBY_USER;
1422 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001423 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001424 "ordered-by", "system", "user");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001425 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001426 return LY_EVALID;
1427 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001428 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001429
Radek Krejcif13b87b2020-12-01 22:02:17 +01001430 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001431}
1432
1433/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001434 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001435 *
1436 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001437 * @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 +02001438 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001439 *
1440 * @return LY_ERR values.
1441 */
1442static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001443yin_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 +02001444{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001445 struct lysp_node_anydata *any;
1446
David Sedlák8d552d62019-08-06 15:29:05 +02001447 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001448 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001449 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001450 any->parent = node_meta->parent;
1451
David Sedlákbf8a2b72019-08-14 16:48:10 +02001452 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001453 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1454 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 +02001455
Radek Krejcif13b87b2020-12-01 22:02:17 +01001456 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001457 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1458 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1459 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1460 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1461 {LY_STMT_MUST, &any->musts, 0},
1462 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1463 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1466 };
Michal Vasko69730152020-10-09 16:30:07 +02001467
Radek Krejcif13b87b2020-12-01 22:02:17 +01001468 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001469}
1470
1471/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001472 * @brief parse leaf element.
1473 *
1474 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001475 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001476 *
1477 * @return LY_ERR values.
1478 */
1479static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001480yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001481{
David Sedlák203ca3a2019-07-18 15:26:25 +02001482 struct lysp_node_leaf *leaf;
1483
David Sedlák8d552d62019-08-06 15:29:05 +02001484 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001485 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001486 leaf->nodetype = LYS_LEAF;
1487 leaf->parent = node_meta->parent;
1488
David Sedlák203ca3a2019-07-18 15:26:25 +02001489 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001490 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1491 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 +02001492
1493 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001494 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001495 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1496 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1497 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1498 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1499 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1500 {LY_STMT_MUST, &leaf->musts, 0},
1501 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1502 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1503 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1504 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1505 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1506 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1507 };
Michal Vasko69730152020-10-09 16:30:07 +02001508
Radek Krejcif13b87b2020-12-01 22:02:17 +01001509 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001510}
1511
1512/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001513 * @brief Parse leaf-list element.
1514 *
1515 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001516 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001517 *
1518 * @return LY_ERR values.
1519 */
1520static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001521yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001522{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001523 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001524
Michal Vaskob36053d2020-03-26 15:49:30 +01001525 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001526
David Sedlákc3da3ef2019-07-19 12:56:08 +02001527 llist->nodetype = LYS_LEAFLIST;
1528 llist->parent = node_meta->parent;
1529
David Sedlákc3da3ef2019-07-19 12:56:08 +02001530 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001531 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1532 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 +02001533
1534 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001535 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001536 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1537 {LY_STMT_DEFAULT, &llist->dflts, 0},
1538 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1539 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1540 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1541 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1542 {LY_STMT_MUST, &llist->musts, 0},
1543 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1544 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1545 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1546 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1547 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1548 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1550 };
Michal Vasko69730152020-10-09 16:30:07 +02001551
Radek Krejcif13b87b2020-12-01 22:02:17 +01001552 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001553
David Sedlákbf8a2b72019-08-14 16:48:10 +02001554 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001555 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001556 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001557 return LY_EVALID;
1558 }
Michal Vasko69730152020-10-09 16:30:07 +02001559 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001560 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001561 return LY_EVALID;
1562 }
1563
1564 return LY_SUCCESS;
1565}
1566
1567/**
David Sedlák04e17b22019-07-19 15:29:48 +02001568 * @brief Parse typedef element.
1569 *
1570 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001571 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001572 *
1573 * @return LY_ERR values.
1574 */
1575static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001576yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001577{
1578 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001579 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001580
Michal Vaskob36053d2020-03-26 15:49:30 +01001581 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001582
1583 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001584 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1585 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 +02001586
1587 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001588 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001589 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1590 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1591 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1592 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1593 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1594 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1596 };
Michal Vasko69730152020-10-09 16:30:07 +02001597
Radek Krejcif13b87b2020-12-01 22:02:17 +01001598 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001599
1600 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001601 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1602 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001603 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001604 }
1605
1606 return LY_SUCCESS;
1607}
1608
1609/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001610 * @brief Parse refine element.
1611 *
1612 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001613 * @param[in,out] refines Refines to add to.
1614 *
1615 * @return LY_ERR values.
1616 */
1617static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001618yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001619{
1620 struct lysp_refine *rf;
1621
1622 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001623 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001624
1625 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001626 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1627 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1628 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001629
1630 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001631 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001632 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001633 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001634 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001635 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001636 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1637 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1638 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1639 {LY_STMT_MUST, &rf->musts, 0},
1640 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1641 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1642 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1643 };
Michal Vasko69730152020-10-09 16:30:07 +02001644
Radek Krejcif13b87b2020-12-01 22:02:17 +01001645 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001646}
1647
1648/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001649 * @brief Parse uses element.
1650 *
1651 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001652 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001653 *
1654 * @return LY_ERR values.
1655 */
1656static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001657yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001658{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001659 struct lysp_node_uses *uses;
1660
David Sedlák8d552d62019-08-06 15:29:05 +02001661 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001662 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001663 uses->nodetype = LYS_USES;
1664 uses->parent = node_meta->parent;
1665
David Sedlák0d6de5a2019-07-22 13:25:44 +02001666 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001667 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1668 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 +02001669
1670 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001671 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
Radek Krejcif13b87b2020-12-01 22:02:17 +01001672 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001673 {LY_STMT_AUGMENT, &augments, 0},
1674 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1675 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1676 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1677 {LY_STMT_REFINE, &uses->refines, 0},
1678 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1679 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1680 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1681 };
Michal Vasko69730152020-10-09 16:30:07 +02001682
Radek Krejcif13b87b2020-12-01 22:02:17 +01001683 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001684
1685 return LY_SUCCESS;
1686}
1687
1688/**
David Sedlákaa854b02019-07-22 14:17:10 +02001689 * @brief Parse revision element.
1690 *
1691 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001692 * @param[in,out] revs Parsed revisions to add to.
1693 *
1694 * @return LY_ERR values.
1695 */
1696static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001697yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001698{
1699 struct lysp_revision *rev;
1700 const char *temp_date = NULL;
1701
1702 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001703 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001704
1705 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001706 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1707 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 +02001708 /* check value */
1709 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskoe180ed02021-02-05 16:31:20 +01001710 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001711 return LY_EVALID;
1712 }
Radek Krejci36642162021-01-12 16:49:22 +01001713 memcpy(rev->date, temp_date, LY_REV_SIZE);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001714 lydict_remove(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001715
1716 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001717 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001718 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1719 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1720 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1721 };
Michal Vasko69730152020-10-09 16:30:07 +02001722
Radek Krejcif13b87b2020-12-01 22:02:17 +01001723 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001724}
1725
David Sedlák5e13dea2019-07-22 16:06:45 +02001726/**
1727 * @brief Parse include element.
1728 *
1729 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001730 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1731 *
1732 * @return LY_ERR values.
1733 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001734static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001735yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001736{
1737 struct lysp_include *inc;
1738
1739 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001740 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001741
1742 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001743 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1744 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 +02001745
1746 /* submodules share the namespace with the module names, so there must not be
1747 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001748 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01001749 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001750 return LY_EVALID;
1751 }
1752
1753 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01001754 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001755 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1756 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1757 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1758 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1759 };
Michal Vasko69730152020-10-09 16:30:07 +02001760
Radek Krejcif13b87b2020-12-01 22:02:17 +01001761 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001762}
1763
David Sedlákaa854b02019-07-22 14:17:10 +02001764/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001765 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001766 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001767 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001768 * @param[in,out] rev Array to store the parsed value in.
1769 * @param[in,out] exts Extension instances to add to.
1770 *
1771 * @return LY_ERR values.
1772 */
1773static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001774yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001775{
1776 const char *temp_rev;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001777 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001778 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1779 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001780
Michal Vaskob36053d2020-03-26 15:49:30 +01001781 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1782 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 +02001783 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskoe180ed02021-02-05 16:31:20 +01001784 lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001785
1786 strcpy(rev, temp_rev);
Michal Vaskoe180ed02021-02-05 16:31:20 +01001787 lydict_remove(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001788
Radek Krejcif13b87b2020-12-01 22:02:17 +01001789 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001790}
1791
1792/**
1793 * @brief Parse config element.
1794 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001795 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001796 * @param[in,out] flags Flags to add to.
1797 * @param[in,out] exts Extension instances to add to.
1798 *
1799 * @return LY_ERR values.
1800 */
1801static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001802yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001803{
1804 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001805 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001806 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1807 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001808
Michal Vaskob36053d2020-03-26 15:49:30 +01001809 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1810 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 +02001811 if (strcmp(temp_val, "true") == 0) {
1812 *flags |= LYS_CONFIG_W;
1813 } else if (strcmp(temp_val, "false") == 0) {
1814 *flags |= LYS_CONFIG_R;
1815 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001816 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001817 "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001818 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001819 return LY_EVALID;
1820 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001821 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001822
Radek Krejcif13b87b2020-12-01 22:02:17 +01001823 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001824}
1825
1826/**
1827 * @brief Parse yang-version element.
1828 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001829 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001830 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001831 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001832 *
1833 * @return LY_ERR values.
1834 */
1835static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001836yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001837{
1838 const char *temp_version = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001839 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001840 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1841 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001842
Michal Vaskob36053d2020-03-26 15:49:30 +01001843 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1844 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 +02001845 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001846 *version = LYS_VERSION_1_0;
1847 } else if (strcmp(temp_version, "1.1") == 0) {
1848 *version = LYS_VERSION_1_1;
1849 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001850 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001851 "yang-version", "1", "1.1");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001852 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001853 return LY_EVALID;
1854 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001855 lydict_remove(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001856
Radek Krejcif13b87b2020-12-01 22:02:17 +01001857 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001858}
1859
1860/**
1861 * @brief Parse import element.
1862 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001863 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001864 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1865 *
1866 * @return LY_ERR values.
1867 */
1868static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001869yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001870{
1871 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001872
David Sedlákdfbbb442019-08-06 16:33:21 +02001873 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001874 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001875
Radek Krejcif13b87b2020-12-01 22:02:17 +01001876 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001877 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1878 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1879 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1880 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1881 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1882 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001883
1884 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001885 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1886 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
Radek Krejcif13b87b2020-12-01 22:02:17 +01001887 LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001888 /* check prefix validity */
1889 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1890
1891 return LY_SUCCESS;
1892}
1893
1894/**
1895 * @brief Parse mandatory element.
1896 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001897 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001898 * @param[in,out] flags Flags to add to.
1899 * @param[in,out] exts Extension instances to add to.
1900 *
1901 * @return LY_ERR values.
1902 */
1903static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001904yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001905{
1906 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001907 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001908 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1909 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001910
Michal Vaskob36053d2020-03-26 15:49:30 +01001911 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1912 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 +02001913 if (strcmp(temp_val, "true") == 0) {
1914 *flags |= LYS_MAND_TRUE;
1915 } else if (strcmp(temp_val, "false") == 0) {
1916 *flags |= LYS_MAND_FALSE;
1917 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001918 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001919 "mandatory", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001920 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001921 return LY_EVALID;
1922 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001923 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001924
Radek Krejcif13b87b2020-12-01 22:02:17 +01001925 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001926}
1927
1928/**
1929 * @brief Parse status element.
1930 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001931 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001932 * @param[in,out] flags Flags to add to.
1933 * @param[in,out] exts Extension instances to add to.
1934 *
1935 * @return LY_ERR values.
1936 */
1937static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001938yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001939{
1940 const char *value = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001941 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001942 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1943 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001944
Michal Vaskob36053d2020-03-26 15:49:30 +01001945 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1946 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 +02001947 if (strcmp(value, "current") == 0) {
1948 *flags |= LYS_STATUS_CURR;
1949 } else if (strcmp(value, "deprecated") == 0) {
1950 *flags |= LYS_STATUS_DEPRC;
1951 } else if (strcmp(value, "obsolete") == 0) {
1952 *flags |= LYS_STATUS_OBSLT;
1953 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001954 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001955 "status", "current", "deprecated", "obsolete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01001956 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001957 return LY_EVALID;
1958 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01001959 lydict_remove(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001960
Radek Krejcif13b87b2020-12-01 22:02:17 +01001961 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001962}
1963
1964/**
1965 * @brief Parse when element.
1966 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001967 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001968 * @param[out] when_p When pointer to parse to.
1969 */
1970static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001971yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001972{
1973 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001974 LY_ERR ret = LY_SUCCESS;
1975
David Sedlákdfbbb442019-08-06 16:33:21 +02001976 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001977 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001978
1979 ret = lyxml_ctx_next(ctx->xmlctx);
1980 LY_CHECK_ERR_RET(ret, free(when), ret);
1981
Michal Vaskob36053d2020-03-26 15:49:30 +01001982 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001983 LY_CHECK_ERR_RET(ret, free(when), ret);
1984
David Sedlákdfbbb442019-08-06 16:33:21 +02001985 *when_p = when;
Radek Krejcif13b87b2020-12-01 22:02:17 +01001986 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001987 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1988 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1989 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1990 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001991
Radek Krejcif13b87b2020-12-01 22:02:17 +01001992 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001993}
1994
1995/**
1996 * @brief Parse yin-elemenet element.
1997 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001998 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001999 * @param[in,out] data Data to read from, always moved to currently handled position.
2000 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002001 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002002 *
2003 * @return LY_ERR values.
2004 */
2005static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002006yin_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 +02002007{
2008 const char *temp_val = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002009 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002010 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2011 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002012
Michal Vaskob36053d2020-03-26 15:49:30 +01002013 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2014 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 +02002015 if (strcmp(temp_val, "true") == 0) {
2016 *flags |= LYS_YINELEM_TRUE;
2017 } else if (strcmp(temp_val, "false") == 0) {
2018 *flags |= LYS_YINELEM_FALSE;
2019 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002020 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02002021 "yin-element", "true", "false");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002022 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002023 return LY_EVALID;
2024 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002025 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02002026
Radek Krejcif13b87b2020-12-01 22:02:17 +01002027 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002028}
2029
2030/**
2031 * @brief Parse argument element.
2032 *
Michal Vaskob36053d2020-03-26 15:49:30 +01002033 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002034 * @param[in,out] arg_meta Meta information about destionation of parsed data.
2035 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02002036 *
2037 * @return LY_ERR values.
2038 */
2039static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002040yin_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 +02002041{
Radek Krejcif13b87b2020-12-01 22:02:17 +01002042 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002043 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2044 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2045 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002046
Michal Vaskob36053d2020-03-26 15:49:30 +01002047 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2048 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 +02002049
Radek Krejcif13b87b2020-12-01 22:02:17 +01002050 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002051}
2052
2053/**
2054 * @brief Parse the extension statement.
2055 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002056 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02002057 * @param[in,out] extensions Extensions to add to.
2058 *
2059 * @return LY_ERR values.
2060 */
2061static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002062yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02002063{
2064 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02002065
Michal Vaskob36053d2020-03-26 15:49:30 +01002066 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2067 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2068 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 +02002069
2070 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002071 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002072 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2073 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2074 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2075 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2076 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2077 };
David Sedlákdfbbb442019-08-06 16:33:21 +02002078
Radek Krejcif13b87b2020-12-01 22:02:17 +01002079 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02002080}
2081
2082/**
David Sedlák5e13dea2019-07-22 16:06:45 +02002083 * @brief Parse feature element.
2084 *
2085 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02002086 * @param[in,out] features Features to add to.
2087 *
2088 * @return LY_ERR values.
2089 */
2090static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002091yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02002092{
2093 struct lysp_feature *feat;
2094
2095 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01002096 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02002097
2098 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002099 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2100 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 +02002101
2102 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002103 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002104 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2105 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2106 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2107 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2108 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2109 };
Michal Vasko69730152020-10-09 16:30:07 +02002110
Radek Krejcif13b87b2020-12-01 22:02:17 +01002111 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002112}
2113
2114/**
David Sedlák28794f22019-07-22 16:45:00 +02002115 * @brief Parse identity element.
2116 *
2117 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002118 * @param[in,out] identities Identities to add to.
2119 *
2120 * @return LY_ERR values.
2121 */
2122static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002123yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002124{
2125 struct lysp_ident *ident;
2126
2127 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002128 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002129
2130 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002131 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2132 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 +02002133
2134 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002135 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002136 {LY_STMT_BASE, &ident->bases, 0},
2137 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2138 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2139 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2140 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2141 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2142 };
Michal Vasko69730152020-10-09 16:30:07 +02002143
Radek Krejcif13b87b2020-12-01 22:02:17 +01002144 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002145}
2146
2147/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002148 * @brief Parse list element.
2149 *
2150 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002151 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002152 *
2153 * @return LY_ERR values.
2154 */
2155static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002156yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002157{
David Sedlákaf536aa2019-07-23 13:42:23 +02002158 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002159 LY_ERR ret = LY_SUCCESS;
2160 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002161 size_t subelems_size;
David Sedlákaf536aa2019-07-23 13:42:23 +02002162
Michal Vaskob36053d2020-03-26 15:49:30 +01002163 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002164 list->nodetype = LYS_LIST;
2165 list->parent = node_meta->parent;
2166
David Sedlákaf536aa2019-07-23 13:42:23 +02002167 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002168 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2169 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 +02002170
2171 /* parse list content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002172 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002173 LY_STMT_ACTION, &list->actions, 0,
2174 LY_STMT_ANYDATA, &list->child, 0,
2175 LY_STMT_ANYXML, &list->child, 0,
2176 LY_STMT_CHOICE, &list->child, 0,
2177 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2178 LY_STMT_CONTAINER, &list->child, 0,
2179 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2180 LY_STMT_GROUPING, &list->groupings, 0,
2181 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2182 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2183 LY_STMT_LEAF, &list->child, 0,
2184 LY_STMT_LEAF_LIST, &list->child, 0,
2185 LY_STMT_LIST, &list->child, 0,
2186 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2187 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2188 LY_STMT_MUST, &list->musts, 0,
2189 LY_STMT_NOTIFICATION, &list->notifs, 0,
2190 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2191 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2192 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2193 LY_STMT_TYPEDEF, &list->typedefs, 0,
2194 LY_STMT_UNIQUE, &list->uniques, 0,
2195 LY_STMT_USES, &list->child, 0,
2196 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2197 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002198 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_LIST, NULL, &list->exts);
2199 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002200 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002201
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{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002221 struct lysp_node_notif *notif;
2222 struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002223 LY_ERR ret = LY_SUCCESS;
2224 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002225 size_t subelems_size;
David Sedlák031b9e72019-07-23 15:19:37 +02002226
2227 /* allocate new notification */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002228 LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002229 notif->nodetype = LYS_NOTIF;
2230 notif->parent = notif_meta->parent;
2231
2232 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002233 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2234 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 +02002235
2236 /* parse notification content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002237 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002238 LY_STMT_ANYDATA, &notif->child, 0,
2239 LY_STMT_ANYXML, &notif->child, 0,
2240 LY_STMT_CHOICE, &notif->child, 0,
2241 LY_STMT_CONTAINER, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002242 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2243 LY_STMT_GROUPING, &notif->groupings, 0,
2244 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002245 LY_STMT_LEAF, &notif->child, 0,
2246 LY_STMT_LEAF_LIST, &notif->child, 0,
2247 LY_STMT_LIST, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002248 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2249 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2250 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2251 LY_STMT_TYPEDEF, &notif->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002252 LY_STMT_USES, &notif->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002253 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002254
Radek Krejcif13b87b2020-12-01 22:02:17 +01002255 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2256 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002257 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002258
David Sedlák031b9e72019-07-23 15:19:37 +02002259 return LY_SUCCESS;
2260}
2261
2262/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002263 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002264 *
2265 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002266 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002267 *
2268 * @return LY_ERR values.
2269 */
2270static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002271yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002272{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002273 struct lysp_node_grp *grp;
2274 struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002275 LY_ERR ret = LY_SUCCESS;
2276 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002277 size_t subelems_size;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002278
2279 /* create new grouping */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002280 LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002281 grp->nodetype = LYS_GROUPING;
2282 grp->parent = gr_meta->parent;
2283
2284 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002285 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2286 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 +02002287
2288 /* parse grouping content */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002289 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002290 LY_STMT_ACTION, &grp->actions, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002291 LY_STMT_ANYDATA, &grp->child, 0,
2292 LY_STMT_ANYXML, &grp->child, 0,
2293 LY_STMT_CHOICE, &grp->child, 0,
2294 LY_STMT_CONTAINER, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002295 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2296 LY_STMT_GROUPING, &grp->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002297 LY_STMT_LEAF, &grp->child, 0,
2298 LY_STMT_LEAF_LIST, &grp->child, 0,
2299 LY_STMT_LIST, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002300 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2301 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2302 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2303 LY_STMT_TYPEDEF, &grp->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002304 LY_STMT_USES, &grp->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002305 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002306 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_GROUPING, NULL, &grp->exts);
2307 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002308
Radek Krejci2a9fc652021-01-22 17:44:34 +01002309 return ret;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002310}
2311
2312/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002313 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002314 *
2315 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002316 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002317 *
2318 * @return LY_ERR values.
2319 */
2320static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002321yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002322{
David Sedlákf111bcb2019-07-23 17:15:51 +02002323 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002324 LY_ERR ret = LY_SUCCESS;
2325 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002326 size_t subelems_size;
David Sedlákf111bcb2019-07-23 17:15:51 +02002327
2328 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002329 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002330 cont->nodetype = LYS_CONTAINER;
2331 cont->parent = node_meta->parent;
2332
David Sedlákf111bcb2019-07-23 17:15:51 +02002333 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002334 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2335 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 +02002336
2337 /* parse container content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002338 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002339 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2340 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2341 LY_STMT_ANYXML, &cont->child, 0,
2342 LY_STMT_CHOICE, &cont->child, 0,
2343 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2344 LY_STMT_CONTAINER, &cont->child, 0,
2345 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2346 LY_STMT_GROUPING, &cont->groupings, 0,
2347 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2348 LY_STMT_LEAF, &cont->child, 0,
2349 LY_STMT_LEAF_LIST, &cont->child, 0,
2350 LY_STMT_LIST, &cont->child, 0,
2351 LY_STMT_MUST, &cont->musts, 0,
2352 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2353 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2354 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2355 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2356 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2357 LY_STMT_USES, &cont->child, 0,
2358 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2359 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002360 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CONTAINER, NULL, &cont->exts);
2361 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002362
Radek Krejci2a9fc652021-01-22 17:44:34 +01002363 return ret;
David Sedlákf111bcb2019-07-23 17:15:51 +02002364}
2365
2366/**
David Sedlák5379d392019-07-24 10:42:03 +02002367 * @brief Parse case element.
2368 *
2369 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002370 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002371 *
2372 * @return LY_ERR values.
2373 */
2374static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002375yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002376{
David Sedlák5379d392019-07-24 10:42:03 +02002377 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002378 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002379 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002380 size_t subelems_size;
David Sedlák5379d392019-07-24 10:42:03 +02002381
2382 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002383 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002384 cas->nodetype = LYS_CASE;
2385 cas->parent = node_meta->parent;
2386
David Sedlák5379d392019-07-24 10:42:03 +02002387 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002388 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2389 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 +02002390
2391 /* parse case content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002392 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002393 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2394 LY_STMT_ANYXML, &cas->child, 0,
2395 LY_STMT_CHOICE, &cas->child, 0,
2396 LY_STMT_CONTAINER, &cas->child, 0,
2397 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2398 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2399 LY_STMT_LEAF, &cas->child, 0,
2400 LY_STMT_LEAF_LIST, &cas->child, 0,
2401 LY_STMT_LIST, &cas->child, 0,
2402 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2403 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2404 LY_STMT_USES, &cas->child, 0,
2405 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2406 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002407 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CASE, NULL, &cas->exts);
2408 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002409
2410 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002411}
2412
2413/**
David Sedlák05404f62019-07-24 14:11:53 +02002414 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002415 *
2416 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002417 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002418 *
2419 * @return LY_ERR values.
2420 */
2421LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002422yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002423{
David Sedlák81497a32019-08-13 16:56:26 +02002424 LY_ERR ret = LY_SUCCESS;
2425 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002426 struct lysp_node_choice *choice;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002427 size_t subelems_size;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002428
2429 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002430 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002431
David Sedlákb7abcfa2019-07-24 12:33:35 +02002432 choice->nodetype = LYS_CHOICE;
2433 choice->parent = node_meta->parent;
2434
David Sedlákb7abcfa2019-07-24 12:33:35 +02002435 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002436 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2437 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 +02002438
2439 /* parse choice content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002440 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002441 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2442 LY_STMT_ANYXML, &choice->child, 0,
2443 LY_STMT_CASE, &choice->child, 0,
2444 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2445 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2446 LY_STMT_CONTAINER, &choice->child, 0,
2447 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2448 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2449 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2450 LY_STMT_LEAF, &choice->child, 0,
2451 LY_STMT_LEAF_LIST, &choice->child, 0,
2452 LY_STMT_LIST, &choice->child, 0,
2453 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2454 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2455 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2456 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2457 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002458 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_CHOICE, NULL, &choice->exts);
2459 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002460 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002461}
2462
2463/**
David Sedlák05404f62019-07-24 14:11:53 +02002464 * @brief Parse input or output element.
2465 *
2466 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002467 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002468 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2469 *
2470 * @return LY_ERR values.
2471 */
2472static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002473yin_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 +02002474{
David Sedlák81497a32019-08-13 16:56:26 +02002475 LY_ERR ret = LY_SUCCESS;
2476 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002477 size_t subelems_size;
David Sedlák81497a32019-08-13 16:56:26 +02002478
David Sedlák05404f62019-07-24 14:11:53 +02002479 /* initiate structure */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002480 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name));
Radek Krejcid6b76452019-09-03 17:03:03 +02002481 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002482 inout_meta->inout_p->parent = inout_meta->parent;
2483
2484 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002485 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2486 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 +02002487
2488 /* parser input/output content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002489 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejci01180ac2021-01-27 08:48:22 +01002490 LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2491 LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2492 LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2493 LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002494 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002495 LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2496 LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2497 LY_STMT_LIST, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002498 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2499 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
Radek Krejci01180ac2021-01-27 08:48:22 +01002500 LY_STMT_USES, &inout_meta->inout_p->child, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002501 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002502 ret = yin_parse_content(ctx, subelems, subelems_size, inout_kw, NULL, &inout_meta->inout_p->exts);
2503 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002504 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002505
Radek Krejci01180ac2021-01-27 08:48:22 +01002506 if (!inout_meta->inout_p->child) {
Michal Vaskob83af8a2020-01-06 09:49:22 +01002507 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2508 return LY_EVALID;
2509 }
2510
David Sedlák05404f62019-07-24 14:11:53 +02002511 return LY_SUCCESS;
2512}
2513
David Sedlák992fb7c2019-07-24 16:51:01 +02002514/**
2515 * @brief Parse action element.
2516 *
2517 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002518 * @param[in] act_meta Meta information about parent node and actions to add to.
2519 *
2520 * @return LY_ERR values.
2521 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002522static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002523yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002524{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002525 struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002526 LY_ERR ret = LY_SUCCESS;
2527 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002528 size_t subelems_size;
David Sedlák85d0eca2019-07-24 15:15:21 +02002529
2530 /* create new action */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002531 LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002532 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002533 act->parent = act_meta->parent;
2534
2535 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002536 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2537 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 +02002538
2539 /* parse content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002540 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002541 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2542 LY_STMT_GROUPING, &act->groupings, 0,
2543 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2544 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2545 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2546 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2547 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2548 LY_STMT_TYPEDEF, &act->typedefs, 0,
2549 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002550 ret = (yin_parse_content(ctx, subelems, subelems_size, LY_STMT_ACTION, NULL, &act->exts));
2551 subelems_deallocator(subelems_size, subelems);
David Sedlák81497a32019-08-13 16:56:26 +02002552 LY_CHECK_RET(ret);
2553
Michal Vasko7f45cf22020-10-01 12:49:44 +02002554 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2555 if (!act->input.nodetype) {
2556 act->input.nodetype = LYS_INPUT;
2557 act->input.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002558 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002559 }
2560 if (!act->output.nodetype) {
2561 act->output.nodetype = LYS_OUTPUT;
2562 act->output.parent = (struct lysp_node *)act;
Radek Krejci2a9fc652021-01-22 17:44:34 +01002563 LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
Michal Vasko7f45cf22020-10-01 12:49:44 +02002564 }
2565
David Sedlák85d0eca2019-07-24 15:15:21 +02002566 return LY_SUCCESS;
2567}
2568
David Sedlák05404f62019-07-24 14:11:53 +02002569/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002570 * @brief Parse augment element.
2571 *
2572 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002573 * @param[in] aug_meta Meta information about parent node and augments to add to.
2574 *
2575 * @return LY_ERR values.
2576 */
2577static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002578yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002579{
Radek Krejci2a9fc652021-01-22 17:44:34 +01002580 struct lysp_node_augment *aug;
2581 struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002582 LY_ERR ret = LY_SUCCESS;
2583 struct yin_subelement *subelems = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002584 size_t subelems_size;
David Sedlák992fb7c2019-07-24 16:51:01 +02002585
2586 /* create new augment */
Radek Krejci2a9fc652021-01-22 17:44:34 +01002587 LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002588 aug->nodetype = LYS_AUGMENT;
2589 aug->parent = aug_meta->parent;
2590
2591 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002592 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2593 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2594 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002595
2596 /* parser augment content */
Radek Krejcif13b87b2020-12-01 22:02:17 +01002597 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002598 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2599 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2600 LY_STMT_ANYXML, &aug->child, 0,
2601 LY_STMT_CASE, &aug->child, 0,
2602 LY_STMT_CHOICE, &aug->child, 0,
2603 LY_STMT_CONTAINER, &aug->child, 0,
2604 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002605 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002606 LY_STMT_LEAF, &aug->child, 0,
2607 LY_STMT_LEAF_LIST, &aug->child, 0,
2608 LY_STMT_LIST, &aug->child, 0,
2609 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2610 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2611 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2612 LY_STMT_USES, &aug->child, 0,
2613 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2614 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Radek Krejcif13b87b2020-12-01 22:02:17 +01002615 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_AUGMENT, NULL, &aug->exts);
2616 subelems_deallocator(subelems_size, subelems);
David Sedlák992fb7c2019-07-24 16:51:01 +02002617
Radek Krejci2a9fc652021-01-22 17:44:34 +01002618 return ret;
David Sedlák992fb7c2019-07-24 16:51:01 +02002619}
2620
David Sedlák8b754462019-07-25 16:22:13 +02002621/**
2622 * @brief Parse deviate element.
2623 *
2624 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002625 * @param[in] deviates Deviates to add to.
2626 *
2627 * @return LY_ERR values.
2628 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002629static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002630yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002631{
2632 LY_ERR ret = LY_SUCCESS;
2633 uint8_t dev_mod;
2634 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002635 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002636 struct lysp_deviate_add *d_add = NULL;
2637 struct lysp_deviate_rpl *d_rpl = NULL;
2638 struct lysp_deviate_del *d_del = NULL;
2639
2640 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002641 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2642 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 +02002643
2644 if (strcmp(temp_val, "not-supported") == 0) {
2645 dev_mod = LYS_DEV_NOT_SUPPORTED;
2646 } else if (strcmp(temp_val, "add") == 0) {
2647 dev_mod = LYS_DEV_ADD;
2648 } else if (strcmp(temp_val, "replace") == 0) {
2649 dev_mod = LYS_DEV_REPLACE;
2650 } else if (strcmp(temp_val, "delete") == 0) {
2651 dev_mod = LYS_DEV_DELETE;
2652 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002653 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002654 "not-supported", "add", "replace", "delete");
Michal Vaskoe180ed02021-02-05 16:31:20 +01002655 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002656 return LY_EVALID;
2657 }
Michal Vaskoe180ed02021-02-05 16:31:20 +01002658 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002659
2660 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2661 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002662 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif13b87b2020-12-01 22:02:17 +01002663 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002664 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2665 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002666 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002667
2668 } else if (dev_mod == LYS_DEV_ADD) {
2669 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002670 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002671 d = (struct lysp_deviate *)d_add;
2672 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2673 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002674 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002675 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002676 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002677 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2678 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2679 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2680 {LY_STMT_MUST, &d_add->musts, 0},
2681 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2682 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2683 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2684 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002685 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002686
2687 } else if (dev_mod == LYS_DEV_REPLACE) {
2688 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002689 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002690 d = (struct lysp_deviate *)d_rpl;
2691 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2692 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
Radek Krejcif13b87b2020-12-01 22:02:17 +01002693 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002694 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002695 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002696 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2697 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2698 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2699 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2700 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2701 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2702 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002703 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002704
2705 } else {
2706 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002707 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002708 d = (struct lysp_deviate *)d_del;
Radek Krejcif13b87b2020-12-01 22:02:17 +01002709 struct yin_subelement subelems[] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002710 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002711 {LY_STMT_MUST, &d_del->musts, 0},
2712 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2713 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2714 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2715 };
Radek Krejcif13b87b2020-12-01 22:02:17 +01002716 ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002717 }
2718 LY_CHECK_GOTO(ret, cleanup);
2719
2720 d->mod = dev_mod;
2721 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002722 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002723
2724 return ret;
2725
2726cleanup:
2727 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002728 return ret;
2729}
2730
David Sedlák992fb7c2019-07-24 16:51:01 +02002731/**
David Sedlák8b754462019-07-25 16:22:13 +02002732 * @brief Parse deviation element.
2733 *
2734 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002735 * @param[in] deviations Deviations to add to.
2736 *
2737 * @return LY_ERR values.
2738 */
2739static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002740yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002741{
2742 struct lysp_deviation *dev;
2743
2744 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002745 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002746
2747 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002748 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2749 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2750 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
Radek Krejcif13b87b2020-12-01 22:02:17 +01002751 struct yin_subelement subelems[] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002752 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2753 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2754 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2755 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2756 };
Michal Vasko69730152020-10-09 16:30:07 +02002757
Radek Krejcif13b87b2020-12-01 22:02:17 +01002758 return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002759}
2760
2761/**
David Sedlákb4e44562019-07-04 15:42:12 +02002762 * @brief Map keyword type to substatement info.
2763 *
2764 * @param[in] kw Keyword type.
2765 *
2766 * @return correct LYEXT_SUBSTMT information.
2767 */
2768static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002769kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002770{
2771 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002772 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002773 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002774 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002775 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002776 case LY_STMT_BELONGS_TO:
Radek Krejcieccf6602021-02-05 19:42:54 +01002777 return LYEXT_SUBSTMT_BELONGS_TO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002778 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002779 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002780 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002781 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002782 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002783 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002784 case LY_STMT_ERROR_APP_TAG:
Radek Krejcieccf6602021-02-05 19:42:54 +01002785 return LYEXT_SUBSTMT_ERROR_APP_TAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002786 case LY_STMT_ERROR_MESSAGE:
Radek Krejcieccf6602021-02-05 19:42:54 +01002787 return LYEXT_SUBSTMT_ERROR_MESSAGE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002788 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002789 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002790 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002791 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002792 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002793 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002794 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002795 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002796 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002797 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002798 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002799 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002800 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002801 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002802 case LY_STMT_REVISION_DATE:
Radek Krejcieccf6602021-02-05 19:42:54 +01002803 return LYEXT_SUBSTMT_REVISION_DATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002804 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002805 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002806 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002807 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002808 case LY_STMT_YANG_VERSION:
Radek Krejcieccf6602021-02-05 19:42:54 +01002809 return LYEXT_SUBSTMT_YANG_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002810 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002811 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002812 case LY_STMT_REQUIRE_INSTANCE:
Radek Krejcieccf6602021-02-05 19:42:54 +01002813 return LYEXT_SUBSTMT_REQUIRE_INSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002814 case LY_STMT_YIN_ELEMENT:
Radek Krejcieccf6602021-02-05 19:42:54 +01002815 return LYEXT_SUBSTMT_YIN_ELEMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002816 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002817 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002818 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002819 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002820 case LY_STMT_ORDERED_BY:
Radek Krejcieccf6602021-02-05 19:42:54 +01002821 return LYEXT_SUBSTMT_ORDERED_BY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002822 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002823 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002824 case LY_STMT_FRACTION_DIGITS:
Radek Krejcieccf6602021-02-05 19:42:54 +01002825 return LYEXT_SUBSTMT_FRACTION_DIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002826 case LY_STMT_MAX_ELEMENTS:
Radek Krejcieccf6602021-02-05 19:42:54 +01002827 return LYEXT_SUBSTMT_MAX_ELEMENTS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002828 case LY_STMT_MIN_ELEMENTS:
Radek Krejcieccf6602021-02-05 19:42:54 +01002829 return LYEXT_SUBSTMT_MIN_ELEMENTS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002830 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002831 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002832 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002833 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002834 case LY_STMT_IF_FEATURE:
Radek Krejcieccf6602021-02-05 19:42:54 +01002835 return LYEXT_SUBSTMT_IF_FEATURE;
David Sedlákb4e44562019-07-04 15:42:12 +02002836 default:
2837 return LYEXT_SUBSTMT_SELF;
2838 }
2839}
2840
David Sedlákc5b20842019-08-13 10:18:31 +02002841/**
2842 * @brief map keyword to keyword-group.
2843 *
2844 * @param[in] ctx YIN parser context used for logging.
2845 * @param[in] kw Keyword that is child of module or submodule.
2846 * @param[out] group Group of keyword.
2847 *
2848 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2849 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002850static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002851kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002852{
2853 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002854 /* module header */
2855 case LY_STMT_NONE:
2856 case LY_STMT_NAMESPACE:
2857 case LY_STMT_PREFIX:
2858 case LY_STMT_BELONGS_TO:
2859 case LY_STMT_YANG_VERSION:
2860 *group = Y_MOD_MODULE_HEADER;
2861 break;
2862 /* linkage */
2863 case LY_STMT_INCLUDE:
2864 case LY_STMT_IMPORT:
2865 *group = Y_MOD_LINKAGE;
2866 break;
2867 /* meta */
2868 case LY_STMT_ORGANIZATION:
2869 case LY_STMT_CONTACT:
2870 case LY_STMT_DESCRIPTION:
2871 case LY_STMT_REFERENCE:
2872 *group = Y_MOD_META;
2873 break;
2874 /* revision */
2875 case LY_STMT_REVISION:
2876 *group = Y_MOD_REVISION;
2877 break;
2878 /* body */
2879 case LY_STMT_ANYDATA:
2880 case LY_STMT_ANYXML:
2881 case LY_STMT_AUGMENT:
2882 case LY_STMT_CHOICE:
2883 case LY_STMT_CONTAINER:
2884 case LY_STMT_DEVIATION:
2885 case LY_STMT_EXTENSION:
2886 case LY_STMT_FEATURE:
2887 case LY_STMT_GROUPING:
2888 case LY_STMT_IDENTITY:
2889 case LY_STMT_LEAF:
2890 case LY_STMT_LEAF_LIST:
2891 case LY_STMT_LIST:
2892 case LY_STMT_NOTIFICATION:
2893 case LY_STMT_RPC:
2894 case LY_STMT_TYPEDEF:
2895 case LY_STMT_USES:
2896 case LY_STMT_EXTENSION_INSTANCE:
2897 *group = Y_MOD_BODY;
2898 break;
2899 default:
2900 LOGINT(ctx->xmlctx->ctx);
2901 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002902 }
2903
2904 return LY_SUCCESS;
2905}
2906
David Sedlákc5b20842019-08-13 10:18:31 +02002907/**
2908 * @brief Check if relative order of two keywords is valid.
2909 *
2910 * @param[in] ctx YIN parser context used for logging.
2911 * @param[in] kw Current keyword.
2912 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002913 * @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 +02002914 * because relative order is required only in module and submodule sub-elements, used for logging.
2915 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002916 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002917 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002918static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002919yin_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 +02002920{
Radek Krejcid6b76452019-09-03 17:03:03 +02002921 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002922 enum yang_module_stmt gr, next_gr;
2923
2924 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2925 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2926
2927 if (gr > next_gr) {
2928 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2929 return LY_EVALID;
2930 }
2931
2932 return LY_SUCCESS;
2933}
2934
David Sedlákc5dd0942019-09-13 10:23:59 +02002935/**
2936 * @brief Get element name prefixed by full URI of xml namespace.
2937 *
2938 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2939 * @param[in] name Name of element.
2940 * @param[in] name_len Length of element name.
2941 * @param[in] prefix Prefix of element.
2942 * @param[in] prefix_len Length of element prefix.
2943 *
2944 * @return Element name prefixed by URI on success, NULL on failure.
2945 */
2946static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002947name2nsname(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 +02002948{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002949 const char *ename = NULL;
Michal Vaskoc8a230d2020-08-14 12:17:10 +02002950 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002951
Michal Vaskob36053d2020-03-26 15:49:30 +01002952 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002953
Radek Krejci02728562019-09-18 14:13:05 +02002954 if (!strcmp(ns->uri, YIN_NS_URI)) {
2955 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002956 lydict_insert(ctx->xmlctx->ctx, name, name_len, &ename);
2957 return ename;
Radek Krejci02728562019-09-18 14:13:05 +02002958 }
2959 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002960 size_t ns_len = strlen(ns->uri);
2961 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2962
2963 char *result;
2964 char *temp;
Michal Vasko69730152020-10-09 16:30:07 +02002965
David Sedláke0ef1c62019-09-13 10:05:55 +02002966 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002967 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002968
2969 strcpy(result, ns->uri);
2970 result[ns_len] = ':';
2971 temp = &result[ns_len + 1];
2972 strncpy(temp, name, name_len);
2973 result[len] = '\0';
2974
Radek Krejci011e4aa2020-09-04 15:22:31 +02002975 lydict_insert_zc(ctx->xmlctx->ctx, result, &ename);
2976 return ename;
David Sedlák068dd352019-09-13 09:08:22 +02002977}
2978
Michal Vaskoafac7822020-10-20 14:22:26 +02002979/**
2980 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
2981 *
2982 * @param[in,out] ctx Yin parser context for logging and to store current state.
2983 * @param[in] elem_type Type of element that is currently being parsed.
2984 * @param[out] arg Value to write to.
2985 *
2986 * @return LY_ERR values.
2987 */
2988static LY_ERR
2989yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
2990{
2991 enum ly_stmt child;
2992
2993 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2994
2995 switch (elem_type) {
2996 case LY_STMT_ACTION:
2997 case LY_STMT_ANYDATA:
2998 case LY_STMT_ANYXML:
2999 case LY_STMT_ARGUMENT:
3000 case LY_STMT_BASE:
3001 case LY_STMT_BIT:
3002 case LY_STMT_CASE:
3003 case LY_STMT_CHOICE:
3004 case LY_STMT_CONTAINER:
3005 case LY_STMT_ENUM:
3006 case LY_STMT_EXTENSION:
3007 case LY_STMT_FEATURE:
3008 case LY_STMT_GROUPING:
3009 case LY_STMT_IDENTITY:
3010 case LY_STMT_IF_FEATURE:
3011 case LY_STMT_LEAF:
3012 case LY_STMT_LEAF_LIST:
3013 case LY_STMT_LIST:
3014 case LY_STMT_MODULE:
3015 case LY_STMT_NOTIFICATION:
3016 case LY_STMT_RPC:
3017 case LY_STMT_SUBMODULE:
3018 case LY_STMT_TYPE:
3019 case LY_STMT_TYPEDEF:
3020 case LY_STMT_UNITS:
3021 case LY_STMT_USES:
3022 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
3023 break;
3024 case LY_STMT_AUGMENT:
3025 case LY_STMT_DEVIATION:
3026 case LY_STMT_REFINE:
3027 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
3028 break;
3029 case LY_STMT_CONFIG:
3030 case LY_STMT_DEFAULT:
3031 case LY_STMT_DEVIATE:
3032 case LY_STMT_ERROR_APP_TAG:
3033 case LY_STMT_FRACTION_DIGITS:
3034 case LY_STMT_KEY:
3035 case LY_STMT_LENGTH:
3036 case LY_STMT_MANDATORY:
3037 case LY_STMT_MAX_ELEMENTS:
3038 case LY_STMT_MIN_ELEMENTS:
3039 case LY_STMT_MODIFIER:
3040 case LY_STMT_ORDERED_BY:
3041 case LY_STMT_PATH:
3042 case LY_STMT_PATTERN:
3043 case LY_STMT_POSITION:
3044 case LY_STMT_PREFIX:
3045 case LY_STMT_PRESENCE:
3046 case LY_STMT_RANGE:
3047 case LY_STMT_REQUIRE_INSTANCE:
3048 case LY_STMT_STATUS:
3049 case LY_STMT_VALUE:
3050 case LY_STMT_YANG_VERSION:
3051 case LY_STMT_YIN_ELEMENT:
3052 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
3053 break;
3054 case LY_STMT_IMPORT:
3055 case LY_STMT_INCLUDE:
3056 case LY_STMT_BELONGS_TO:
3057 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
3058 break;
3059 case LY_STMT_INPUT:
3060 case LY_STMT_OUTPUT:
3061 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3062 break;
3063 case LY_STMT_MUST:
3064 case LY_STMT_WHEN:
3065 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
3066 break;
3067 case LY_STMT_NAMESPACE:
3068 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
3069 break;
3070 case LY_STMT_REVISION:
3071 case LY_STMT_REVISION_DATE:
3072 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
3073 break;
3074 case LY_STMT_UNIQUE:
3075 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
3076 break;
3077 /* argument is mapped to yin element */
3078 case LY_STMT_CONTACT:
3079 case LY_STMT_DESCRIPTION:
3080 case LY_STMT_ORGANIZATION:
3081 case LY_STMT_REFERENCE:
3082 case LY_STMT_ERROR_MESSAGE:
3083 /* there shouldn't be any attribute, argument is supposed to be first subelement */
3084 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3085
3086 /* no content */
3087 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3088 if (ctx->xmlctx->ws_only) {
3089 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3090 }
3091 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3092 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3093 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
3094 return LY_EVALID;
3095 }
3096
3097 /* parse child element */
3098 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3099 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3100 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
3101 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3102 ly_stmt2str(elem_type));
3103 return LY_EVALID;
3104 }
3105 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3106
3107 /* no attributes expected? TODO */
3108 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3109 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3110 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3111 }
3112
3113 /* load and save content */
3114 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3115 LY_CHECK_RET(!*arg, LY_EMEM);
3116
3117 /* load closing tag of subelement */
3118 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3119
3120 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3121 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3122 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3123 }*/
3124 break;
3125 default:
3126 LOGINT(ctx->xmlctx->ctx);
3127 return LY_EINT;
3128 }
3129
3130 return LY_SUCCESS;
3131}
3132
3133/**
3134 * @brief Parse yin element into generic structure.
3135 *
3136 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3137 * @param[in] parent Identification of parent element.
3138 * @param[out] element Where the element structure should be stored.
3139 *
3140 * @return LY_ERR values.
3141 */
3142LY_ERR
3143yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
3144{
3145 LY_ERR ret = LY_SUCCESS;
3146 struct lysp_stmt *last = NULL, *new = NULL;
3147
3148 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3149
3150 /* allocate new structure for element */
3151 *element = calloc(1, sizeof(**element));
3152 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3153 (*element)->stmt = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
3154 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
3155
3156 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3157 ctx->xmlctx->prefix_len, parent);
3158
3159 last = (*element)->child;
3160 if ((*element)->kw == LY_STMT_NONE) {
3161 /* unrecognized element */
3162 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3163 ly_stmt2str(parent));
3164 ret = LY_EVALID;
3165 goto cleanup;
3166 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3167 /* element is known yang keyword, which means argument can be parsed correctly. */
3168 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3169 LY_CHECK_GOTO(ret, cleanup);
3170 } else {
3171 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3172
3173 /* load attributes in generic way, save all attributes in linked list */
3174 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3175 new = calloc(1, sizeof(*last));
3176 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3177 if (!(*element)->child) {
3178 /* save first */
3179 (*element)->child = new;
3180 } else {
3181 last->next = new;
3182 }
3183 last = new;
3184
3185 last->flags |= LYS_YIN_ATTR;
3186 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3187 last->kw = LY_STMT_NONE;
3188 /* attributes with prefix are ignored */
3189 if (!ctx->xmlctx->prefix) {
3190 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3191
3192 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3193 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3194 } else {
3195 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3196 }
3197 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3198 }
3199 }
3200
3201 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3202 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3203 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3204 /* parse subelements */
3205 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3206 LY_CHECK_GOTO(ret, cleanup);
3207 if (!(*element)->child) {
3208 /* save first */
3209 (*element)->child = new;
3210 } else {
3211 last->next = new;
3212 }
3213 last = new;
3214
3215 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3216 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3217 }
3218 } else {
3219 /* save element content */
3220 if (ctx->xmlctx->value_len) {
3221 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3222 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3223 }
3224
3225 /* read closing tag */
3226 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3227 }
3228
3229cleanup:
3230 return ret;
3231}
3232
3233/**
3234 * @brief Parse instance of extension.
3235 *
3236 * @param[in,out] ctx Yin parser context for logging and to store current state.
3237 * @param[in] subelem Type of the keyword this extension instance is a subelement of.
3238 * @param[in] subelem_index Index of the keyword instance this extension instance is a subelement of
3239 * @param[in,out] exts Extension instance to add to.
3240 *
3241 * @return LY_ERR values.
3242 */
3243LY_ERR
3244yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, LY_ARRAY_COUNT_TYPE subelem_index,
3245 struct lysp_ext_instance **exts)
3246{
3247 struct lysp_ext_instance *e;
3248 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3249
3250 assert(ctx->xmlctx->status == LYXML_ELEMENT);
Radek Krejci3aac9a72020-12-01 12:24:26 +01003251 assert(exts);
Michal Vaskoafac7822020-10-20 14:22:26 +02003252
3253 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3254
3255 e->yin = 0;
3256 /* store name and insubstmt info */
3257 e->name = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
3258 LY_CHECK_RET(!e->name, LY_EMEM);
3259 e->insubstmt = subelem;
3260 e->insubstmt_index = subelem_index;
3261 e->yin |= LYS_YIN;
3262 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3263
3264 /* store attributes as subelements */
3265 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3266 if (!ctx->xmlctx->prefix) {
3267 new_subelem = calloc(1, sizeof(*new_subelem));
3268 if (!e->child) {
3269 e->child = new_subelem;
3270 } else {
3271 last_subelem->next = new_subelem;
3272 }
3273 last_subelem = new_subelem;
3274
3275 last_subelem->flags |= LYS_YIN_ATTR;
3276 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3277 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3278 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3279
3280 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last_subelem->arg);
3281 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3282 } else {
3283 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3284 }
3285
3286 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3287 }
3288
3289 /* parse subelements */
3290 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3291 if (ctx->xmlctx->ws_only) {
3292 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3293 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3294 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3295 if (!e->child) {
3296 e->child = new_subelem;
3297 } else {
3298 last_subelem->next = new_subelem;
3299 }
3300 last_subelem = new_subelem;
3301
3302 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3303 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3304 }
3305 } else if (ctx->xmlctx->value_len) {
3306 /* save text content */
3307 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
3308 LY_CHECK_RET(!e->argument, LY_EMEM);
3309
3310 /* parser next */
3311 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3312 }
3313
3314 return LY_SUCCESS;
3315}
3316
3317/**
3318 * @brief Generic function for content parsing
3319 *
3320 * @param[in,out] ctx Yin parser context for logging and to store current state.
3321 * @param[in] subelem_info array of valid subelement types and meta information
3322 * @param[in] subelem_info_size Size of subelem_info array.
3323 * @param[in] current_element Type of current element.
3324 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3325 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3326 *
3327 * @return LY_ERR values.
3328 */
David Sedlákd6e56892019-07-01 15:40:24 +02003329LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003330yin_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 +02003331 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02003332{
3333 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01003334 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02003335 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02003336 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02003337
Michal Vaskob36053d2020-03-26 15:49:30 +01003338 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02003339
Michal Vaskob36053d2020-03-26 15:49:30 +01003340 if (ctx->xmlctx->ws_only) {
3341 /* check whether there are any children */
3342 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3343 } else {
3344 /* we want to parse the value */
3345 next_status = LYXML_ELEM_CLOSE;
3346 }
3347
3348 if (next_status == LYXML_ELEMENT) {
3349 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3350
3351 /* current element has subelements as content */
3352 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3353 /* match keyword */
3354 last_kw = kw;
3355 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003356 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01003357
3358 /* check if this element can be child of current element */
3359 subelem = get_record(kw, subelem_info_size, subelem_info);
3360 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02003361 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003362 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
3363 } else {
3364 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02003365 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003366 }
3367 ret = LY_EVALID;
3368 goto cleanup;
3369 }
3370
3371 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02003372 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003373 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
3374 LY_CHECK_GOTO(ret, cleanup);
3375 }
3376
3377 /* flag check */
3378 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3379 /* subelement uniquenes */
3380 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
3381 return LY_EVALID;
3382 }
3383 if (subelem->flags & YIN_SUBELEM_FIRST) {
3384 /* subelement is supposed to be defined as first subelement */
3385 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
3386 LY_CHECK_GOTO(ret, cleanup);
3387 }
3388 if (subelem->flags & YIN_SUBELEM_VER2) {
3389 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003390 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003391 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 +02003392 ret = LY_EVALID;
3393 goto cleanup;
3394 }
David Sedlákd6e56892019-07-01 15:40:24 +02003395 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003396 /* note that element was parsed for easy uniqueness check in next iterations */
3397 subelem->flags |= YIN_SUBELEM_PARSED;
3398
3399 switch (kw) {
3400 /* call responsible function */
3401 case LY_STMT_EXTENSION_INSTANCE:
3402 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vasko69730152020-10-09 16:30:07 +02003403 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01003404 break;
3405 case LY_STMT_ACTION:
3406 case LY_STMT_RPC:
3407 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3408 break;
3409 case LY_STMT_ANYDATA:
3410 case LY_STMT_ANYXML:
3411 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
3412 break;
3413 case LY_STMT_ARGUMENT:
3414 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
3415 break;
3416 case LY_STMT_AUGMENT:
3417 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3418 break;
3419 case LY_STMT_BASE:
3420 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
3421 break;
3422 case LY_STMT_BELONGS_TO:
3423 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3424 break;
3425 case LY_STMT_BIT:
3426 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3427 break;
3428 case LY_STMT_CASE:
3429 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3430 break;
3431 case LY_STMT_CHOICE:
3432 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3433 break;
3434 case LY_STMT_CONFIG:
3435 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3436 break;
3437 case LY_STMT_CONTACT:
3438 case LY_STMT_DESCRIPTION:
3439 case LY_STMT_ORGANIZATION:
3440 case LY_STMT_REFERENCE:
3441 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
3442 break;
3443 case LY_STMT_CONTAINER:
3444 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3445 break;
3446 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003447 ret = yin_parse_qname(ctx, kw, subelem, exts);
3448 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003449 case LY_STMT_ERROR_APP_TAG:
3450 case LY_STMT_KEY:
3451 case LY_STMT_PRESENCE:
3452 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3453 break;
3454 case LY_STMT_DEVIATE:
3455 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3456 break;
3457 case LY_STMT_DEVIATION:
3458 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3459 break;
3460 case LY_STMT_ENUM:
3461 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3462 break;
3463 case LY_STMT_ERROR_MESSAGE:
3464 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3465 break;
3466 case LY_STMT_EXTENSION:
3467 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3468 break;
3469 case LY_STMT_FEATURE:
3470 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3471 break;
3472 case LY_STMT_FRACTION_DIGITS:
3473 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3474 break;
3475 case LY_STMT_GROUPING:
3476 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3477 break;
3478 case LY_STMT_IDENTITY:
3479 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3480 break;
3481 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003482 ret = yin_parse_qname(ctx, kw, subelem, exts);
3483 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003484 case LY_STMT_UNITS:
3485 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3486 break;
3487 case LY_STMT_IMPORT:
3488 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3489 break;
3490 case LY_STMT_INCLUDE:
Radek Krejcieeee95c2021-01-19 10:57:22 +01003491 if ((current_element == LY_STMT_SUBMODULE) && (ctx->parsed_mod->version == LYS_VERSION_1_1)) {
3492 LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in submodules (%s) are not necessary.",
3493 ((struct lysp_submodule *)(ctx->parsed_mod))->name);
3494 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003495 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3496 break;
3497 case LY_STMT_INPUT:
3498 case LY_STMT_OUTPUT:
3499 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3500 break;
3501 case LY_STMT_LEAF:
3502 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3503 break;
3504 case LY_STMT_LEAF_LIST:
3505 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3506 break;
3507 case LY_STMT_LENGTH:
3508 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3509 break;
3510 case LY_STMT_LIST:
3511 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3512 break;
3513 case LY_STMT_MANDATORY:
3514 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3515 break;
3516 case LY_STMT_MAX_ELEMENTS:
3517 case LY_STMT_MIN_ELEMENTS:
3518 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3519 break;
3520 case LY_STMT_MODIFIER:
3521 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3522 break;
3523 case LY_STMT_MUST:
3524 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3525 break;
3526 case LY_STMT_NAMESPACE:
3527 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3528 break;
3529 case LY_STMT_NOTIFICATION:
3530 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3531 break;
3532 case LY_STMT_ORDERED_BY:
3533 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3534 break;
3535 case LY_STMT_PATH:
3536 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3537 break;
3538 case LY_STMT_PATTERN:
3539 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3540 break;
3541 case LY_STMT_VALUE:
3542 case LY_STMT_POSITION:
3543 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3544 break;
3545 case LY_STMT_PREFIX:
3546 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3547 break;
3548 case LY_STMT_RANGE:
3549 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3550 break;
3551 case LY_STMT_REFINE:
3552 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3553 break;
3554 case LY_STMT_REQUIRE_INSTANCE:
3555 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3556 break;
3557 case LY_STMT_REVISION:
3558 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3559 break;
3560 case LY_STMT_REVISION_DATE:
3561 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3562 break;
3563 case LY_STMT_STATUS:
3564 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3565 break;
3566 case LY_STMT_TYPE:
3567 ret = yin_parse_type(ctx, current_element, subelem);
3568 break;
3569 case LY_STMT_TYPEDEF:
3570 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3571 break;
3572 case LY_STMT_UNIQUE:
3573 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3574 break;
3575 case LY_STMT_USES:
3576 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3577 break;
3578 case LY_STMT_WHEN:
3579 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3580 break;
3581 case LY_STMT_YANG_VERSION:
3582 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3583 break;
3584 case LY_STMT_YIN_ELEMENT:
3585 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3586 break;
3587 case LY_STMT_ARG_TEXT:
3588 case LY_STMT_ARG_VALUE:
3589 /* TODO what to do with content/attributes? */
3590 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3591 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3592 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3593 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3594 }
3595 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3596 break;
3597 default:
3598 LOGINT(ctx->xmlctx->ctx);
3599 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003600 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003601 LY_CHECK_GOTO(ret, cleanup);
3602 subelem = NULL;
3603
3604 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003605 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003606 } else {
3607 LY_CHECK_RET(ret);
3608 /* elements with text or none content */
3609 /* save text content, if text_content isn't set, it's just ignored */
3610 /* no resources are allocated in this branch, no need to use cleanup label */
3611 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3612 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003613 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 +01003614 LY_CHECK_RET(!*text_content, LY_EMEM);
3615 }
3616
3617 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003618 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003619
David Sedlák8b754462019-07-25 16:22:13 +02003620 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3621 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003622
3623cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003624 return ret;
3625}
3626
David Sedlákaa98bba2019-09-12 11:52:14 +02003627/**
Michal Vaskoafac7822020-10-20 14:22:26 +02003628 * @brief Parse module element.
David Sedlákaa98bba2019-09-12 11:52:14 +02003629 *
3630 * @param[in,out] ctx Yin parser context for logging and to store current state.
Michal Vaskoafac7822020-10-20 14:22:26 +02003631 * @param[out] mod Parsed module structure.
David Sedlákaa98bba2019-09-12 11:52:14 +02003632 *
3633 * @return LY_ERR values.
3634 */
David Sedlák1e2cdd02019-06-27 14:17:43 +02003635LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003636yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003637{
David Sedlák81497a32019-08-13 16:56:26 +02003638 LY_ERR ret = LY_SUCCESS;
3639 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003640 struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003641 size_t subelems_size;
David Sedlák3b4db242018-10-19 16:11:01 +02003642
Michal Vaskoc3781c32020-10-06 14:04:08 +02003643 mod->is_submod = 0;
3644
Michal Vaskob36053d2020-03-26 15:49:30 +01003645 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3646 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01003647 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003648 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3649 LY_STMT_ANYXML, &mod->data, 0,
3650 LY_STMT_AUGMENT, &mod->augments, 0,
3651 LY_STMT_CHOICE, &mod->data, 0,
3652 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3653 LY_STMT_CONTAINER, &mod->data, 0,
3654 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3655 LY_STMT_DEVIATION, &mod->deviations, 0,
3656 LY_STMT_EXTENSION, &mod->extensions, 0,
3657 LY_STMT_FEATURE, &mod->features, 0,
3658 LY_STMT_GROUPING, &mod->groupings, 0,
3659 LY_STMT_IDENTITY, &mod->identities, 0,
3660 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3661 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3662 LY_STMT_LEAF, &mod->data, 0,
3663 LY_STMT_LEAF_LIST, &mod->data, 0,
3664 LY_STMT_LIST, &mod->data, 0,
3665 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3666 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3667 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3668 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3669 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3670 LY_STMT_REVISION, &mod->revs, 0,
3671 LY_STMT_RPC, &mod->rpcs, 0,
3672 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3673 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003674 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003675 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003676
Radek Krejcif13b87b2020-12-01 22:02:17 +01003677 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_MODULE, NULL, &mod->exts);
3678 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003679 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003680
David Sedláked809f12019-09-13 10:15:11 +02003681 /* submodules share the namespace with the module names, so there must not be
3682 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003683 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003684 if (dup) {
Radek Krejci854e1552020-12-21 15:05:23 +01003685 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
David Sedláked809f12019-09-13 10:15:11 +02003686 return LY_EVALID;
3687 }
3688
3689 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003690}
3691
Michal Vaskoafac7822020-10-20 14:22:26 +02003692/**
3693 * @brief Parse submodule element.
3694 *
3695 * @param[in,out] ctx Yin parser context for logging and to store current state.
3696 * @param[in] mod_attrs Attributes of submodule element.
3697 * @param[out] submod Parsed submodule structure.
3698 *
3699 * @return LY_ERR values.
3700 */
David Sedlák3b4db242018-10-19 16:11:01 +02003701LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003702yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003703{
David Sedlák81497a32019-08-13 16:56:26 +02003704 LY_ERR ret = LY_SUCCESS;
3705 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003706 struct lysp_submodule *dup;
Radek Krejcif13b87b2020-12-01 22:02:17 +01003707 size_t subelems_size;
David Sedlák298ff6d2019-07-26 14:29:03 +02003708
Michal Vaskoc3781c32020-10-06 14:04:08 +02003709 submod->is_submod = 1;
3710
Michal Vaskob36053d2020-03-26 15:49:30 +01003711 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3712 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
Radek Krejcif13b87b2020-12-01 22:02:17 +01003713 LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003714 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3715 LY_STMT_ANYXML, &submod->data, 0,
3716 LY_STMT_AUGMENT, &submod->augments, 0,
3717 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3718 LY_STMT_CHOICE, &submod->data, 0,
3719 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3720 LY_STMT_CONTAINER, &submod->data, 0,
3721 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3722 LY_STMT_DEVIATION, &submod->deviations, 0,
3723 LY_STMT_EXTENSION, &submod->extensions, 0,
3724 LY_STMT_FEATURE, &submod->features, 0,
3725 LY_STMT_GROUPING, &submod->groupings, 0,
3726 LY_STMT_IDENTITY, &submod->identities, 0,
3727 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3728 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3729 LY_STMT_LEAF, &submod->data, 0,
3730 LY_STMT_LEAF_LIST, &submod->data, 0,
3731 LY_STMT_LIST, &submod->data, 0,
3732 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3733 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3734 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3735 LY_STMT_REVISION, &submod->revs, 0,
3736 LY_STMT_RPC, &submod->rpcs, 0,
3737 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3738 LY_STMT_USES, &submod->data, 0,
3739 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3740 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003741
Radek Krejcif13b87b2020-12-01 22:02:17 +01003742 ret = yin_parse_content(ctx, subelems, subelems_size, LY_STMT_SUBMODULE, NULL, &submod->exts);
3743 subelems_deallocator(subelems_size, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003744 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003745
David Sedláked809f12019-09-13 10:15:11 +02003746 /* submodules share the namespace with the module names, so there must not be
3747 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003748 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003749 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
Radek Krejci854e1552020-12-21 15:05:23 +01003750 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
David Sedláked809f12019-09-13 10:15:11 +02003751 return LY_EVALID;
3752 }
3753
3754 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003755}
3756
3757LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003758yin_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 +02003759 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003760{
Radek Krejcid6b76452019-09-03 17:03:03 +02003761 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003762 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003763 struct lysp_submodule *mod_p = NULL;
3764
3765 /* create context */
3766 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003767 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003768 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003769 (*yin_ctx)->unres = main_ctx->unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003770 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003771
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003772 mod_p = calloc(1, sizeof *mod_p);
3773 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3774 mod_p->mod = main_ctx->parsed_mod->mod;
3775 mod_p->parsing = 1;
3776 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3777
David Sedlák1b623122019-08-05 15:27:49 +02003778 /* map the typedefs and groupings list from main context to the submodule's context */
3779 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3780 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3781
David Sedlák8985a142019-07-31 16:43:06 +02003782 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003783 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 +02003784 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003785 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003786 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3787 ret = LY_EINVAL;
3788 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003789 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003790 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003791 ret = LY_EVALID;
3792 goto cleanup;
3793 }
3794
Michal Vaskob36053d2020-03-26 15:49:30 +01003795 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003796 LY_CHECK_GOTO(ret, cleanup);
3797
David Sedlákbf8a2b72019-08-14 16:48:10 +02003798 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003799 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003800 if (in->current[0] == '\n') {
3801 LY_IN_NEW_LINE(in);
3802 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003803 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003804 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003805 if (in->current[0]) {
3806 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003807 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003808 ret = LY_EVALID;
3809 goto cleanup;
3810 }
3811
David Sedlák8985a142019-07-31 16:43:06 +02003812 mod_p->parsing = 0;
3813 *submod = mod_p;
3814
3815cleanup:
3816 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003817 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003818 yin_parser_ctx_free(*yin_ctx);
3819 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003820 }
David Sedlák8985a142019-07-31 16:43:06 +02003821 return ret;
3822}
3823
3824LY_ERR
Michal Vasko405cc9e2020-12-01 12:01:27 +01003825yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod, struct lys_glob_unres *unres)
David Sedlák3b4db242018-10-19 16:11:01 +02003826{
David Sedláke4889912018-11-02 09:52:40 +01003827 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003828 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003829 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003830
David Sedlák8985a142019-07-31 16:43:06 +02003831 /* create context */
3832 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003833 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003834 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko405cc9e2020-12-01 12:01:27 +01003835 (*yin_ctx)->unres = unres;
Michal Vasko63f3d842020-07-08 10:10:14 +02003836 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003837
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003838 mod_p = calloc(1, sizeof *mod_p);
3839 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3840 mod_p->mod = mod;
3841 mod_p->parsing = 1;
3842 (*yin_ctx)->parsed_mod = mod_p;
3843
David Sedlák8985a142019-07-31 16:43:06 +02003844 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003845 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 +02003846 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003847 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003848 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 +01003849 ret = LY_EINVAL;
3850 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003851 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003852 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003853 ret = LY_EVALID;
3854 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003855 }
3856
David Sedlák00250342019-06-21 14:19:39 +02003857 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003858 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003859 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003860
David Sedlákbf8a2b72019-08-14 16:48:10 +02003861 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003862 while (isspace(in->current[0])) {
Radek Krejcidd713ce2021-01-04 23:12:12 +01003863 if (in->current[0] == '\n') {
3864 LY_IN_NEW_LINE(in);
3865 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003866 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003867 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003868 if (in->current[0]) {
3869 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003870 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003871 ret = LY_EVALID;
3872 goto cleanup;
3873 }
3874
David Sedlák3017da42019-02-15 09:48:04 +01003875 mod_p->parsing = 0;
3876 mod->parsed = mod_p;
3877
3878cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003879 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003880 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003881 yin_parser_ctx_free(*yin_ctx);
3882 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003883 }
David Sedlák2e411422018-12-17 02:35:39 +01003884 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003885}