blob: 407c3250d16abe172b538eae7eef611bafebc427 [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 */
Radek Krejci535ea9f2020-05-29 16:01:05 +020014#include "parser_yin.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020015
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
Radek Krejci535ea9f2020-05-29 16:01:05 +020017#include <ctype.h>
18#include <errno.h>
19#include <stdarg.h>
20#include <stdbool.h>
David Sedlák3b4db242018-10-19 16:11:01 +020021#include <stdio.h>
22#include <stdlib.h>
David Sedlák872c7b42018-10-26 13:15:20 +020023#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020024
Radek Krejci535ea9f2020-05-29 16:01:05 +020025#include "common.h"
David Sedlákf824ad52018-10-14 23:58:15 +020026#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "dict.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020028#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020029#include "parser_schema.h"
Michal Vasko69730152020-10-09 16:30:07 +020030#include "path.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020031#include "set.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020032#include "tree.h"
33#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020034#include "tree_schema_internal.h"
Radek Krejci535ea9f2020-05-29 16:01:05 +020035#include "xml.h"
David Sedlák00250342019-06-21 14:19:39 +020036
David Sedlák2b214ac2019-06-06 16:11:03 +020037/**
38 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020039 *
David Sedlák2b214ac2019-06-06 16:11:03 +020040 * @param ns Namespace URI to check.
41 *
42 * @return true if ns equals YIN_NS_URI false otherwise.
43 */
44#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
45
Michal Vasko22df3f02020-08-24 13:29:22 +020046const char * const yin_attr_list[] = {
David Sedlákf6251182019-06-06 10:22:13 +020047 [YIN_ARG_NAME] = "name",
48 [YIN_ARG_TARGET_NODE] = "target-node",
49 [YIN_ARG_MODULE] = "module",
50 [YIN_ARG_VALUE] = "value",
51 [YIN_ARG_TEXT] = "text",
52 [YIN_ARG_CONDITION] = "condition",
53 [YIN_ARG_URI] = "uri",
54 [YIN_ARG_DATE] = "date",
55 [YIN_ARG_TAG] = "tag",
David Sedlák071f7662019-09-12 02:02:51 +020056 [YIN_ARG_NONE] = "none",
David Sedlákf6251182019-06-06 10:22:13 +020057};
58
Radek Krejcid6b76452019-09-03 17:03:03 +020059enum ly_stmt
Michal Vaskob36053d2020-03-26 15:49:30 +010060yin_match_keyword(struct lys_yin_parser_ctx *ctx, const char *name, size_t name_len,
Radek Krejci0f969882020-08-21 16:56:47 +020061 const char *prefix, size_t prefix_len, enum ly_stmt parent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020062{
David Sedlák8f7a1172019-06-20 14:42:18 +020063 const char *start = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +020064 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020065 const struct lyxml_ns *ns = NULL;
Michal Vasko63f3d842020-07-08 10:10:14 +020066 struct ly_in *in;
David Sedlák8f7a1172019-06-20 14:42:18 +020067
Michal Vasko69730152020-10-09 16:30:07 +020068 if (!name || (name_len == 0)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020069 return LY_STMT_NONE;
David Sedlák1bccdfa2019-06-17 15:55:27 +020070 }
71
Michal Vaskoc8a230d2020-08-14 12:17:10 +020072 ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020073 if (ns) {
74 if (!IS_YIN_NS(ns->uri)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020075 return LY_STMT_EXTENSION_INSTANCE;
David Sedlák8f7a1172019-06-20 14:42:18 +020076 }
77 } else {
78 /* elements without namespace are automatically unknown */
Radek Krejcid6b76452019-09-03 17:03:03 +020079 return LY_STMT_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +020080 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020081
Michal Vasko63f3d842020-07-08 10:10:14 +020082 LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
83 start = in->current;
84 kw = lysp_match_kw(NULL, in);
85 name = in->current;
86 ly_in_free(in, 0);
David Sedlák8f7a1172019-06-20 14:42:18 +020087
88 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020089 /* 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 +020090 if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
Radek Krejcid6b76452019-09-03 17:03:03 +020091 return LY_STMT_ARG_VALUE;
David Sedlákc1771b12019-07-10 15:55:46 +020092 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020093 return kw;
94 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020095 if (strncmp(start, "text", name_len) == 0) {
Radek Krejcid6b76452019-09-03 17:03:03 +020096 return LY_STMT_ARG_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020097 } else {
Radek Krejcid6b76452019-09-03 17:03:03 +020098 return LY_STMT_NONE;
David Sedlák3ffbc522019-07-02 17:49:28 +020099 }
David Sedlák1bccdfa2019-06-17 15:55:27 +0200100 }
101}
102
David Sedlákc5b20842019-08-13 10:18:31 +0200103enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +0200104yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200105{
David Sedlákc5b20842019-08-13 10:18:31 +0200106 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200107 size_t already_read = 0;
Michal Vasko69730152020-10-09 16:30:07 +0200108
David Sedlák7ff55a92019-06-17 11:11:41 +0200109 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200110
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200111#define READ_INC(LEN) already_read += LEN
112#define ARG_SET(STMT) arg=STMT
113#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100114
David Sedlák1c8b2702019-02-22 11:03:02 +0100115 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100116 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200117 READ_INC(1);
118 if (ARG_CHECK("ondition", 8)) {
119 ARG_SET(YIN_ARG_CONDITION);
120 }
David Sedlák3b4db242018-10-19 16:11:01 +0200121 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200122
David Sedlák94de2aa2019-02-15 12:42:11 +0100123 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200124 READ_INC(1);
125 if (ARG_CHECK("ate", 3)) {
126 ARG_SET(YIN_ARG_DATE);
127 }
David Sedlák3b4db242018-10-19 16:11:01 +0200128 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200129
David Sedlák94de2aa2019-02-15 12:42:11 +0100130 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200131 READ_INC(1);
132 if (ARG_CHECK("odule", 5)) {
133 ARG_SET(YIN_ARG_MODULE);
134 }
David Sedlák872c7b42018-10-26 13:15:20 +0200135 break;
136
David Sedlák94de2aa2019-02-15 12:42:11 +0100137 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200138 READ_INC(1);
139 if (ARG_CHECK("ame", 3)) {
140 ARG_SET(YIN_ARG_NAME);
141 }
David Sedlák872c7b42018-10-26 13:15:20 +0200142 break;
143
David Sedlák94de2aa2019-02-15 12:42:11 +0100144 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200145 READ_INC(1);
146 if (ARG_CHECK("a", 1)) {
147 if (ARG_CHECK("g", 1)) {
148 ARG_SET(YIN_ARG_TAG);
149 } else if (ARG_CHECK("rget-node", 9)) {
150 ARG_SET(YIN_ARG_TARGET_NODE);
151 }
152 } else if (ARG_CHECK("ext", 3)) {
153 ARG_SET(YIN_ARG_TEXT);
154 }
David Sedlák3b4db242018-10-19 16:11:01 +0200155 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200156
David Sedlák94de2aa2019-02-15 12:42:11 +0100157 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200158 READ_INC(1);
159 if (ARG_CHECK("ri", 2)) {
160 ARG_SET(YIN_ARG_URI);
161 }
David Sedlák3b4db242018-10-19 16:11:01 +0200162 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200163
David Sedlák94de2aa2019-02-15 12:42:11 +0100164 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200165 READ_INC(1);
166 if (ARG_CHECK("alue", 4)) {
167 ARG_SET(YIN_ARG_VALUE);
168 }
David Sedlák3b4db242018-10-19 16:11:01 +0200169 break;
170 }
171
David Sedlákc10e7902018-12-17 02:17:59 +0100172 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200173 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200174 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200175 }
176
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200177#undef ARG_CHECK
178#undef ARG_SET
179#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100180
David Sedlák872c7b42018-10-26 13:15:20 +0200181 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200182}
183
Radek Krejcid6b76452019-09-03 17:03:03 +0200184#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
185 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
186 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
187 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200188
Radek Krejcid6b76452019-09-03 17:03:03 +0200189#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 +0200190
David Sedlák26ea1432019-08-14 13:42:23 +0200191/**
192 * @brief Free subelems information allocated on heap.
193 *
194 * @param[in] count Size of subelems array.
195 * @param[in] subelems Subelems array to free.
196 */
David Sedlák81497a32019-08-13 16:56:26 +0200197static void
198subelems_deallocator(size_t count, struct yin_subelement *subelems)
199{
Michal Vaskod989ba02020-08-24 10:59:24 +0200200 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200201 if (HAS_META(subelems[i].type)) {
202 free(subelems[i].dest);
203 }
204 }
205
206 free(subelems);
207}
208
David Sedlák26ea1432019-08-14 13:42:23 +0200209/**
210 * @brief Allocate subelems information on heap.
211 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200212 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200213 * @param[in] count Number of subelements.
214 * @param[in] parent Parent node if any.
215 * @param[out] result Allocated subelems array.
216 *
217 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
218 */
David Sedlák81497a32019-08-13 16:56:26 +0200219static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100220subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200221 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200222{
223 va_list ap;
224
225 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200226 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200227
228 va_start(ap, result);
229 for (size_t i = 0; i < count; ++i) {
230 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200231 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200232 /* DEST */
233 if (IS_NODE_ELEM((*result)[i].type)) {
234 struct tree_node_meta *node_meta = NULL;
235 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200236 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200237 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200238 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200239 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200240 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200241 struct import_meta *imp_meta = NULL;
242 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200243 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200244 imp_meta->prefix = va_arg(ap, const char *);
245 imp_meta->imports = va_arg(ap, struct lysp_import **);
246 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200247 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200248 struct include_meta *inc_meta = NULL;
249 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200250 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200251 inc_meta->name = va_arg(ap, const char *);
252 inc_meta->includes = va_arg(ap, struct lysp_include **);
253 (*result)[i].dest = inc_meta;
Michal Vasko69730152020-10-09 16:30:07 +0200254 } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
David Sedlák81497a32019-08-13 16:56:26 +0200255 struct inout_meta *inout_meta = NULL;
256 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200257 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200258 inout_meta->parent = parent;
259 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
260 (*result)[i].dest = inout_meta;
261 } else {
262 (*result)[i].dest = va_arg(ap, void *);
263 }
264 /* FLAGS */
265 (*result)[i].flags = va_arg(ap, int);
266 }
267 va_end(ap);
268
269 return LY_SUCCESS;
270
David Sedlákbf8a2b72019-08-14 16:48:10 +0200271mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200272 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100273 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200274 return LY_EMEM;
275}
276
David Sedlák8f7a1172019-06-20 14:42:18 +0200277LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100278yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200279{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200280 uint8_t prefix = 0;
281 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100282 size_t utf8_char_len, already_read = 0;
283 const char *val;
284
285 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
286
287 val = ctx->xmlctx->value;
288 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200289 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
Michal Vasko69730152020-10-09 16:30:07 +0200290 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
David Sedlák4a650532019-07-10 11:55:18 +0200291 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100292 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200293
294 switch (val_type) {
295 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200296 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 +0200297 break;
298 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200299 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 +0200300 break;
301 case Y_STR_ARG:
302 case Y_MAYBE_STR_ARG:
303 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
304 break;
305 }
306 }
307
308 return LY_SUCCESS;
309}
310
David Sedlákb4e44562019-07-04 15:42:12 +0200311/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100312 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200313 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200314 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200315 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
316 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200317 * @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 +0200318 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200319 * @param[in] current_element Identification of current element, used for logging.
320 *
321 * @return LY_ERR values.
322 */
323static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100324yin_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 +0200325 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200326{
David Sedlákc5b20842019-08-13 10:18:31 +0200327 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200328 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200329
David Sedlák1bccdfa2019-06-17 15:55:27 +0200330 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100331 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200332 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100333 if (!ctx->xmlctx->prefix) {
334 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200335 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100336 /* skip it */
337 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200338 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200339 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
Michal Vasko69730152020-10-09 16:30:07 +0200340 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200341 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100342
343 /* go to value */
344 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
345 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200346 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 +0200347 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200348 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100349 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +0200350 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200351 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200352 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100353 } else {
354 /* skip it */
355 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200356 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100357
358 /* next attribute */
359 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200360 }
361
David Sedlák292763b2019-07-09 11:10:53 +0200362 /* anything else than Y_MAYBE_STR_ARG is mandatory */
Michal Vasko69730152020-10-09 16:30:07 +0200363 if ((val_type != Y_MAYBE_STR_ARG) && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100364 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
Michal Vasko69730152020-10-09 16:30:07 +0200365 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200366 return LY_EVALID;
367 }
368
369 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200370}
371
David Sedlákd6e56892019-07-01 15:40:24 +0200372/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200373 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200374 *
375 * @param[in] type Type of wanted record.
376 * @param[in] array_size Size of array.
377 * @param[in] array Searched array.
378 *
379 * @return Pointer to desired record on success, NULL if element is not in the array.
380 */
David Sedlákb4e44562019-07-04 15:42:12 +0200381static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200382get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200383{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200384 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200385 if (array[u].type == type) {
386 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200387 }
388 }
David Sedlákd6e56892019-07-01 15:40:24 +0200389 return NULL;
390}
391
David Sedlákbba38e52019-07-09 15:20:01 +0200392/**
393 * @brief Helper function to check mandatory constraint of subelement.
394 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200395 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200396 * @param[in] subelem_info Array of information about subelements.
397 * @param[in] subelem_info_size Size of subelem_info array.
398 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
399 *
400 * @return LY_ERR values.
401 */
402static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100403yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200404 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200405{
David Sedlákb0faad82019-07-04 14:28:59 +0200406 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200407 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200408 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200409 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200410 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200411 return LY_EVALID;
412 }
413 }
414
415 return LY_SUCCESS;
416}
417
David Sedlákbba38e52019-07-09 15:20:01 +0200418/**
419 * @brief Helper function to check "first" constraint of subelement.
420 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200421 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200422 * @param[in] subelem_info Array of information about subelements.
423 * @param[in] subelem_info_size Size of subelem_info array.
424 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200425 * @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 +0200426 *
427 * @return LY_ERR values.
428 */
429static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100430yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200431 signed char subelem_info_size, enum ly_stmt current_element,
432 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200433{
David Sedlákb0faad82019-07-04 14:28:59 +0200434 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200435 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200436 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +0200437 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200438 return LY_EVALID;
439 }
440 }
441
442 return LY_SUCCESS;
443}
444
David Sedlákbba38e52019-07-09 15:20:01 +0200445/**
David Sedlákb4e44562019-07-04 15:42:12 +0200446 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
447 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200448 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200449 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200450 * @param[in] kw Type of current element.
451 * @param[out] value Where value of attribute should be stored.
452 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200453 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200454 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200455 * @return LY_ERR values.
456 */
David Sedlákb4e44562019-07-04 15:42:12 +0200457static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100458yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200459 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200460{
Michal Vaskob36053d2020-03-26 15:49:30 +0100461 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
462 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200463 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200464 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
465 };
David Sedlákb4e44562019-07-04 15:42:12 +0200466
Michal Vaskob36053d2020-03-26 15:49:30 +0100467 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200468}
469
470/**
David Sedlák6542aed2019-08-14 10:47:43 +0200471 * @brief Parse path element.
472 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200473 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200474 * @param[in] kw Type of current element.
475 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200476 * @return LY_ERR values.
477 */
478static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100479yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200480{
Michal Vasko004d3152020-06-11 19:59:22 +0200481 LY_ERR ret;
482 const char *str_path;
483
484 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 +0200485 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 +0200486 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
Michal Vasko004d3152020-06-11 19:59:22 +0200487 lydict_remove(ctx->xmlctx->ctx, str_path);
488 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200489 type->flags |= LYS_SET_PATH;
490
491 return LY_SUCCESS;
492}
493
494/**
David Sedlákd3983112019-07-12 11:20:56 +0200495 * @brief Parse pattern element.
496 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200497 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200498 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200499 * @return LY_ERR values.
500 */
501static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100502yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200503{
504 const char *real_value = NULL;
505 char *saved_value = NULL;
506 struct lysp_restr *restr;
507
Michal Vaskob36053d2020-03-26 15:49:30 +0100508 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
509 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
510 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 +0200511 size_t len = strlen(real_value);
512
513 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100514 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200515 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100516 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200517 saved_value[0] = 0x06;
518 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200519 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200520 restr->arg.mod = ctx->parsed_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200521 type->flags |= LYS_SET_PATTERN;
522
523 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200524 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
525 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
526 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
527 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
528 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
529 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
530 };
Michal Vasko69730152020-10-09 16:30:07 +0200531
Michal Vaskob36053d2020-03-26 15:49:30 +0100532 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200533}
534
David Sedlákc5b20842019-08-13 10:18:31 +0200535/**
536 * @brief Parse fraction-digits element.
537 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200538 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200539 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200540 * @return LY_ERR values.
541 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200542static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100543yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200544{
545 const char *temp_val = NULL;
546 char *ptr;
547 unsigned long int num;
548
Michal Vaskob36053d2020-03-26 15:49:30 +0100549 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
550 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 +0200551
Michal Vasko69730152020-10-09 16:30:07 +0200552 if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200553 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100554 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200555 return LY_EVALID;
556 }
557
558 errno = 0;
559 num = strtoul(temp_val, &ptr, 10);
560 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200561 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100562 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200563 return LY_EVALID;
564 }
565 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200566 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100567 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200568 return LY_EVALID;
569 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100570 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200571 type->fraction_digits = num;
572 type->flags |= LYS_SET_FRDIGITS;
573 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200574 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
575 };
Michal Vasko69730152020-10-09 16:30:07 +0200576
Michal Vaskob36053d2020-03-26 15:49:30 +0100577 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200578}
579
David Sedlák07869a52019-07-12 14:28:19 +0200580/**
David Sedlák43801c92019-08-05 15:58:54 +0200581 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200582 *
583 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200584 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200585 * @return LY_ERR values.
586 */
David Sedlákca36c422019-07-12 12:47:55 +0200587static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100588yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200589{
David Sedlák07869a52019-07-12 14:28:19 +0200590 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200591
Michal Vaskob36053d2020-03-26 15:49:30 +0100592 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200593 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100594 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
595 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 +0200596 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100597 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200598 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200599
600 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200601 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
602 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
603 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
604 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
605 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
606 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
607 };
Michal Vasko69730152020-10-09 16:30:07 +0200608
Michal Vaskob36053d2020-03-26 15:49:30 +0100609 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200610}
611
612/**
613 * @brief Parse bit element.
614 *
615 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200616 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200617 * @return LY_ERR values.
618 */
619static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100620yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200621{
622 struct lysp_type_enum *en;
623
Michal Vaskob36053d2020-03-26 15:49:30 +0100624 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200625 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100626 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
627 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 +0200628 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
629
630 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200631 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
632 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
633 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
634 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
635 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
636 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
637 };
Michal Vasko69730152020-10-09 16:30:07 +0200638
Michal Vaskob36053d2020-03-26 15:49:30 +0100639 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200640}
641
David Sedlákd3983112019-07-12 11:20:56 +0200642/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200643 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
644 * more instances, such as base or if-feature.
645 *
646 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200647 * @param[in] kw Type of current element.
648 * @param[out] values Parsed values to add to.
649 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200650 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200651 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200652 * @return LY_ERR values.
653 */
654static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100655yin_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 +0200656 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200657{
658 const char **value;
Michal Vasko69730152020-10-09 16:30:07 +0200659
Michal Vaskob36053d2020-03-26 15:49:30 +0100660 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200661 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200662 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200663 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
664 };
David Sedlák968ac342019-07-11 15:17:59 +0200665
Michal Vaskob36053d2020-03-26 15:49:30 +0100666 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
667 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200668
Michal Vaskob36053d2020-03-26 15:49:30 +0100669 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200670}
671
672/**
David Sedlák6542aed2019-08-14 10:47:43 +0200673 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
674 *
675 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200676 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200677 * @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 +0200678 * @param[in] arg_type Expected type of attribute.
679 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200680 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200681 * @return LY_ERR values.
682 */
683static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100684yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200685 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200686{
687 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100688 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200689 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200690 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100691 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
Michal Vasko69730152020-10-09 16:30:07 +0200692 arg_type, arg_val_type, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200693 }
694
695 return LY_SUCCESS;
696}
697
698/**
699 * @brief Parse base element.
700 *
701 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200702 * @param[in] parent Identification of parent element.
703 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200704 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200705 * @return LY_ERR values.
706 */
707static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100708yin_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 +0200709{
710 struct lysp_type *type = NULL;
711
Radek Krejcid6b76452019-09-03 17:03:03 +0200712 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200713 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100714 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
Michal Vasko69730152020-10-09 16:30:07 +0200715 Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200716 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200717 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100718 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
Michal Vasko69730152020-10-09 16:30:07 +0200719 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
David Sedlák6542aed2019-08-14 10:47:43 +0200720 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100721 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200722 return LY_EINT;
723 }
724
725 return LY_SUCCESS;
726}
727
728/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200729 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200730 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200731 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100732 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200733 * @return LY_ERR values.
734 */
735static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100736yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200737{
738 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200739 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200740 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
741 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200742
743 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100744 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
745 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 +0200746 if (strcmp(temp_val, "true") == 0) {
747 type->require_instance = 1;
748 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200749 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200750 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100751 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200752 return LY_EVALID;
753 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100754 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200755
Michal Vaskob36053d2020-03-26 15:49:30 +0100756 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200757}
758
759/**
David Sedlákce77bf52019-07-11 16:59:31 +0200760 * @brief Parse modifier element.
761 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200762 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200763 * @param[in,out] pat Value to write to.
764 * @param[in,out] exts Extension instances to add to.
765 *
766 * @return LY_ERR values.
767 */
768static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100769yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200770{
David Sedlákd3983112019-07-12 11:20:56 +0200771 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200772 const char *temp_val;
773 char *modified_val;
774 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200775 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
776 };
David Sedlákce77bf52019-07-11 16:59:31 +0200777
Michal Vaskob36053d2020-03-26 15:49:30 +0100778 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
779 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 +0200780 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200781 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +0200782 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100783 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200784 return LY_EVALID;
785 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100786 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200787
788 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200789 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100790 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200791 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100792 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200793
794 /* modify the new value */
795 modified_val[0] = 0x15;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200796 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200797
Michal Vaskob36053d2020-03-26 15:49:30 +0100798 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200799}
800
801/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200802 * @brief Parse a restriction element (length, range or one instance of must).
803 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200804 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200805 * @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 +0200806 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200807 */
808static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100809yin_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 +0200810{
Radek Krejcid6b76452019-09-03 17:03:03 +0200811 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200812 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200813 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
814 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
815 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
816 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
817 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
818 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200819 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200820 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200821
Michal Vaskob36053d2020-03-26 15:49:30 +0100822 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200823 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200824 restr->arg.mod = ctx->parsed_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100825
826 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200827}
828
829/**
David Sedlák6542aed2019-08-14 10:47:43 +0200830 * @brief Parse range element.
831 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200832 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200833 * @param[out] type Type structure to store parsed value and flags.
834 *
835 * @return LY_ERR values.
836 */
837static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100838yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200839{
840 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100841 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
842 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200843 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200844
845 return LY_SUCCESS;
846}
847
848/**
849 * @brief Parse length element.
850 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200851 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200852 * @param[out] type Type structure to store parsed value and flags.
853 *
854 * @return LY_ERR values.
855 */
856static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100857yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200858{
859 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100860 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
861 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200862 type->flags |= LYS_SET_LENGTH;
863
864 return LY_SUCCESS;
865}
866
867/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200868 * @brief Parse must element.
869 *
870 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200871 * @param[in,out] restrs Restrictions to add to.
872 *
873 * @return LY_ERR values.
874 */
875static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100876yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200877{
878 struct lysp_restr *restr;
879
Michal Vaskob36053d2020-03-26 15:49:30 +0100880 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
881 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200882}
883
884/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200885 * @brief Parse a node id into an array.
886 *
887 * @param[in,out] ctx YIN parser context for logging and to store current state.
888 * @param[in] kw Type of current element.
889 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
890 * @param[in,out] exts Extension instances to add to.
891 *
892 * @return LY_ERR values.
893 */
894static LY_ERR
895yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
896 struct lysp_ext_instance **exts)
897{
898 struct lysp_qname *qname, **qnames;
899
900 switch (kw) {
901 case LY_STMT_DEFAULT:
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200902 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
903 qname = (struct lysp_qname *)subinfo->dest;
Michal Vasko7f45cf22020-10-01 12:49:44 +0200904 } else {
905 qnames = (struct lysp_qname **)subinfo->dest;
906 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200907 }
Michal Vasko5d24f6c2020-10-13 13:49:06 +0200908 qname->mod = ctx->parsed_mod;
909 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
910 case LY_STMT_IF_FEATURE:
911 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
912 qnames = (struct lysp_qname **)subinfo->dest;
913 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
914 qname->mod = ctx->parsed_mod;
915 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
Michal Vasko7f45cf22020-10-01 12:49:44 +0200916 default:
917 break;
918 }
919
920 LOGINT(ctx->xmlctx->ctx);
921 return LY_EINT;
922}
923
924/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200925 * @brief Parse position or value element.
926 *
927 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200928 * @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 +0200929 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200930 *
931 * @return LY_ERR values.
932 */
933static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100934yin_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 +0200935{
Radek Krejcid6b76452019-09-03 17:03:03 +0200936 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200937 const char *temp_val = NULL;
938 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200939 long int num = 0;
940 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +0200941
942 /* set value flag */
943 enm->flags |= LYS_SET_VALUE;
944
945 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100946 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
947 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +0200948 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +0200949 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200950 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 +0200951 goto error;
952 }
953
954 /* convert value */
955 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200956 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200957 num = strtol(temp_val, &ptr, 10);
Michal Vasko69730152020-10-09 16:30:07 +0200958 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
David Sedlák1538a842019-08-08 15:38:51 +0200959 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 +0200960 goto error;
961 }
962 } else {
963 unum = strtoul(temp_val, &ptr, 10);
964 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200965 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 +0200966 goto error;
967 }
968 }
969 /* check if whole argument value was converted */
970 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200971 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 +0200972 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200973 }
974 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200975 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 +0200976 goto error;
977 }
978 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200979 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200980 enm->value = num;
981 } else {
982 enm->value = unum;
983 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100984 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200985
986 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200987 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200988 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
989 };
Michal Vasko69730152020-10-09 16:30:07 +0200990
Michal Vaskob36053d2020-03-26 15:49:30 +0100991 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200992
David Sedlákbf8a2b72019-08-14 16:48:10 +0200993error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100994 FREE_STRING(ctx->xmlctx->ctx, temp_val);
995 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +0200996}
997
David Sedlák05404f62019-07-24 14:11:53 +0200998/**
999 * @brief Parse belongs-to element.
1000 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001001 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001002 * @param[out] submod Structure of submodule that is being parsed.
1003 * @param[in,out] exts Extension instances to add to.
1004 *
1005 * @return LY_ERR values
1006 */
1007static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001008yin_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 +02001009{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001010 const char *belongsto;
David Sedlák05404f62019-07-24 14:11:53 +02001011 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001012 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1013 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1014 };
David Sedlák05404f62019-07-24 14:11:53 +02001015
Michal Vaskob36053d2020-03-26 15:49:30 +01001016 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001017 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 +02001018 if (ctx->parsed_mod->mod->name != belongsto) {
Michal Vaskoc3781c32020-10-06 14:04:08 +02001019 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 +02001020 belongsto, ctx->parsed_mod->mod->name);
Michal Vaskoc3781c32020-10-06 14:04:08 +02001021 lydict_remove(ctx->xmlctx->ctx, belongsto);
1022 return LY_EVALID;
1023 }
1024 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001025
1026 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001027}
1028
David Sedlák5545f5d2019-07-11 11:55:16 +02001029/**
David Sedlákc1771b12019-07-10 15:55:46 +02001030 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001031 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001032 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001033 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001034 * @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 +02001035 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001036 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001037 *
1038 * @return LY_ERR values.
1039 */
1040static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001041yin_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 +02001042{
Radek Krejcid6b76452019-09-03 17:03:03 +02001043 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 +02001044
David Sedlák968ac342019-07-11 15:17:59 +02001045 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001046 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1047 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1048 };
Michal Vasko69730152020-10-09 16:30:07 +02001049
David Sedlákdf2a9732019-08-07 13:23:16 +02001050 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001051 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1052 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 +02001053
David Sedlákdf2a9732019-08-07 13:23:16 +02001054 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +01001055 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001056}
1057
1058/**
David Sedlákc1771b12019-07-10 15:55:46 +02001059 * @brief Parse error-message element.
1060 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001061 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001062 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001063 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001064 *
1065 * @return LY_ERR values.
1066 */
1067static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001068yin_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 +02001069{
David Sedlák968ac342019-07-11 15:17:59 +02001070 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001071 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1072 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1073 };
David Sedlákc1771b12019-07-10 15:55:46 +02001074
David Sedlákdf2a9732019-08-07 13:23:16 +02001075 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001076 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1077 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
David Sedlákdf2a9732019-08-07 13:23:16 +02001078
Michal Vaskob36053d2020-03-26 15:49:30 +01001079 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001080}
1081
1082/**
David Sedlák6542aed2019-08-14 10:47:43 +02001083 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001084 *
1085 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001086 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001087 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001088 *
1089 * @return LY_ERR values.
1090 */
1091static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001092yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001093{
David Sedlák6542aed2019-08-14 10:47:43 +02001094 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001095
Radek Krejcid6b76452019-09-03 17:03:03 +02001096 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001097 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001098 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001099 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001100 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001101 type = (struct lysp_type *)subinfo->dest;
1102 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001103
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001104 type->pmod = ctx->parsed_mod;
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001105
David Sedlák6542aed2019-08-14 10:47:43 +02001106 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001107 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001108 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001109 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001110 type->flags |= LYS_SET_TYPE;
1111 type = nested_type;
1112 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001113
David Sedlák374d2b32019-07-17 15:06:55 +02001114 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001115 {LY_STMT_BASE, type, 0},
1116 {LY_STMT_BIT, type, 0},
1117 {LY_STMT_ENUM, type, 0},
1118 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1119 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1120 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1121 {LY_STMT_PATTERN, type, 0},
1122 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1123 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1124 {LY_STMT_TYPE, type},
1125 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1126 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001127
1128 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1129 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1130 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001131}
1132
David Sedlák1af868e2019-07-17 17:03:14 +02001133/**
1134 * @brief Parse max-elements element.
1135 *
1136 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001137 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001138 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001139 * @param[in,out] exts Extension instances to add to.
1140 *
1141 * @return LY_ERR values.
1142 */
1143static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001144yin_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 +02001145{
1146 const char *temp_val = NULL;
1147 char *ptr;
1148 unsigned long int num;
1149 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001150 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1151 };
David Sedlák374d2b32019-07-17 15:06:55 +02001152
David Sedlák1af868e2019-07-17 17:03:14 +02001153 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001154 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1155 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 +02001156 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 +02001157 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001158 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001159 return LY_EVALID;
1160 }
1161
1162 if (strcmp(temp_val, "unbounded")) {
1163 errno = 0;
1164 num = strtoul(temp_val, &ptr, 10);
1165 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001166 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001167 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001168 return LY_EVALID;
1169 }
1170 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001171 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001172 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001173 return LY_EVALID;
1174 }
1175 *max = num;
1176 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001177 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1178 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001179}
David Sedlák374d2b32019-07-17 15:06:55 +02001180
1181/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001182 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001183 *
1184 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001185 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001186 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001187 * @param[in,out] exts Extension instances to add to.
1188 *
1189 * @return LY_ERR values.
1190 */
1191static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001192yin_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 +02001193{
1194 const char *temp_val = NULL;
1195 char *ptr;
1196 unsigned long int num;
1197 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001198 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1199 };
David Sedlák09e18c92019-07-18 11:17:11 +02001200
1201 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001202 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1203 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 +02001204
Michal Vasko69730152020-10-09 16:30:07 +02001205 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001206 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001207 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001208 return LY_EVALID;
1209 }
1210
1211 errno = 0;
1212 num = strtoul(temp_val, &ptr, 10);
1213 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001214 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001215 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001216 return LY_EVALID;
1217 }
Michal Vasko69730152020-10-09 16:30:07 +02001218 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001219 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001220 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001221 return LY_EVALID;
1222 }
1223 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001224 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1225 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001226}
1227
David Sedláka2dad212019-07-18 12:45:19 +02001228/**
1229 * @brief Parse min-elements or max-elements element.
1230 *
1231 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001232 * @param[in] parent Identification of parent element.
1233 * @param[in] current Identification of current element.
1234 * @param[in] dest Where the parsed value and flags should be stored.
1235 *
1236 * @return LY_ERR values.
1237 */
David Sedlák09e18c92019-07-18 11:17:11 +02001238static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001239yin_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 +02001240{
Radek Krejcid6b76452019-09-03 17:03:03 +02001241 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1242 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 +02001243 uint32_t *lim;
1244 uint16_t *flags;
1245 struct lysp_ext_instance **exts;
1246
Radek Krejcid6b76452019-09-03 17:03:03 +02001247 if (parent == LY_STMT_LEAF_LIST) {
1248 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 +02001249 flags = &((struct lysp_node_leaflist *)dest)->flags;
1250 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001251 } else if (parent == LY_STMT_REFINE) {
1252 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001253 flags = &((struct lysp_refine *)dest)->flags;
1254 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001255 } else if (parent == LY_STMT_LIST) {
1256 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 +02001257 flags = &((struct lysp_node_list *)dest)->flags;
1258 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001259 } else {
1260 lim = ((struct minmax_dev_meta *)dest)->lim;
1261 flags = ((struct minmax_dev_meta *)dest)->flags;
1262 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001263 }
1264
Radek Krejcid6b76452019-09-03 17:03:03 +02001265 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001266 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001267 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001268 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001269 }
1270
1271 return LY_SUCCESS;
1272}
1273
1274/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001275 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001276 *
1277 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001278 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001279 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001280 *
1281 * @return LY_ERR values.
1282 */
1283static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001284yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001285{
1286 const char *temp_val;
1287 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001288 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1289 };
David Sedláka2dad212019-07-18 12:45:19 +02001290
Michal Vaskob36053d2020-03-26 15:49:30 +01001291 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1292 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 +02001293 if (strcmp(temp_val, "system") == 0) {
1294 *flags |= LYS_ORDBY_SYSTEM;
1295 } else if (strcmp(temp_val, "user") == 0) {
1296 *flags |= LYS_ORDBY_USER;
1297 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001298 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001299 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001300 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001301 return LY_EVALID;
1302 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001303 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001304
Michal Vaskob36053d2020-03-26 15:49:30 +01001305 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001306}
1307
1308/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001309 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001310 *
1311 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001312 * @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 +02001313 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001314 *
1315 * @return LY_ERR values.
1316 */
1317static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001318yin_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 +02001319{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001320 struct lysp_node_anydata *any;
1321
David Sedlák8d552d62019-08-06 15:29:05 +02001322 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001323 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001324 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001325 any->parent = node_meta->parent;
1326
David Sedlákbf8a2b72019-08-14 16:48:10 +02001327 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001328 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1329 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 +02001330
1331 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001332 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1333 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1335 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_MUST, &any->musts, 0},
1337 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1338 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1339 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1340 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1341 };
Michal Vasko69730152020-10-09 16:30:07 +02001342
Michal Vaskob36053d2020-03-26 15:49:30 +01001343 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001344}
1345
1346/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001347 * @brief parse leaf element.
1348 *
1349 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001350 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001351 *
1352 * @return LY_ERR values.
1353 */
1354static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001355yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001356{
David Sedlák203ca3a2019-07-18 15:26:25 +02001357 struct lysp_node_leaf *leaf;
1358
David Sedlák8d552d62019-08-06 15:29:05 +02001359 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001360 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001361 leaf->nodetype = LYS_LEAF;
1362 leaf->parent = node_meta->parent;
1363
David Sedlák203ca3a2019-07-18 15:26:25 +02001364 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001365 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1366 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 +02001367
1368 /* parse content */
1369 struct yin_subelement subelems[12] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001370 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1371 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1372 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1373 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1374 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1375 {LY_STMT_MUST, &leaf->musts, 0},
1376 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1377 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1378 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1379 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1380 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1381 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1382 };
Michal Vasko69730152020-10-09 16:30:07 +02001383
Michal Vaskob36053d2020-03-26 15:49:30 +01001384 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001385}
1386
1387/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001388 * @brief Parse leaf-list element.
1389 *
1390 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001391 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001392 *
1393 * @return LY_ERR values.
1394 */
1395static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001396yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001397{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001398 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001399
Michal Vaskob36053d2020-03-26 15:49:30 +01001400 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001401
David Sedlákc3da3ef2019-07-19 12:56:08 +02001402 llist->nodetype = LYS_LEAFLIST;
1403 llist->parent = node_meta->parent;
1404
David Sedlákc3da3ef2019-07-19 12:56:08 +02001405 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001406 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1407 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 +02001408
1409 /* parse content */
1410 struct yin_subelement subelems[14] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001411 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1412 {LY_STMT_DEFAULT, &llist->dflts, 0},
1413 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1414 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1415 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1416 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1417 {LY_STMT_MUST, &llist->musts, 0},
1418 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1419 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1420 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1421 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1422 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1423 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1425 };
Michal Vasko69730152020-10-09 16:30:07 +02001426
Michal Vaskob36053d2020-03-26 15:49:30 +01001427 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001428
David Sedlákbf8a2b72019-08-14 16:48:10 +02001429 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001430 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001431 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001432 return LY_EVALID;
1433 }
Michal Vasko69730152020-10-09 16:30:07 +02001434 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001435 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001436 return LY_EVALID;
1437 }
1438
1439 return LY_SUCCESS;
1440}
1441
1442/**
David Sedlák04e17b22019-07-19 15:29:48 +02001443 * @brief Parse typedef element.
1444 *
1445 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001446 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001447 *
1448 * @return LY_ERR values.
1449 */
1450static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001451yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001452{
1453 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001454 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001455
Michal Vaskob36053d2020-03-26 15:49:30 +01001456 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001457
1458 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001459 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1460 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 +02001461
1462 /* parse content */
1463 struct yin_subelement subelems[7] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001464 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1466 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1467 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1468 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1469 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1470 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1471 };
Michal Vasko69730152020-10-09 16:30:07 +02001472
Michal Vaskob36053d2020-03-26 15:49:30 +01001473 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001474
1475 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001476 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1477 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001478 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001479 }
1480
1481 return LY_SUCCESS;
1482}
1483
1484/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001485 * @brief Parse refine element.
1486 *
1487 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001488 * @param[in,out] refines Refines to add to.
1489 *
1490 * @return LY_ERR values.
1491 */
1492static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001493yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001494{
1495 struct lysp_refine *rf;
1496
1497 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001498 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001499
1500 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001501 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1502 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1503 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001504
1505 /* parse content */
1506 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001507 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001508 {LY_STMT_DEFAULT, &rf->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001509 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02001510 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02001511 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1512 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1513 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1514 {LY_STMT_MUST, &rf->musts, 0},
1515 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1516 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1517 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1518 };
Michal Vasko69730152020-10-09 16:30:07 +02001519
Michal Vaskob36053d2020-03-26 15:49:30 +01001520 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001521}
1522
1523/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001524 * @brief Parse uses element.
1525 *
1526 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001527 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001528 *
1529 * @return LY_ERR values.
1530 */
1531static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001532yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001533{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001534 struct lysp_node_uses *uses;
1535
David Sedlák8d552d62019-08-06 15:29:05 +02001536 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001537 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001538 uses->nodetype = LYS_USES;
1539 uses->parent = node_meta->parent;
1540
David Sedlák0d6de5a2019-07-22 13:25:44 +02001541 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001542 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1543 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 +02001544
1545 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001546 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001547 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001548 {LY_STMT_AUGMENT, &augments, 0},
1549 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1550 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1551 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1552 {LY_STMT_REFINE, &uses->refines, 0},
1553 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1554 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1555 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1556 };
Michal Vasko69730152020-10-09 16:30:07 +02001557
Michal Vaskob36053d2020-03-26 15:49:30 +01001558 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001559 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1560
1561 return LY_SUCCESS;
1562}
1563
1564/**
David Sedlákaa854b02019-07-22 14:17:10 +02001565 * @brief Parse revision element.
1566 *
1567 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001568 * @param[in,out] revs Parsed revisions to add to.
1569 *
1570 * @return LY_ERR values.
1571 */
1572static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001573yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001574{
1575 struct lysp_revision *rev;
1576 const char *temp_date = NULL;
1577
1578 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001579 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001580
1581 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001582 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1583 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 +02001584 /* check value */
1585 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001586 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001587 return LY_EVALID;
1588 }
1589 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001590 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001591
1592 /* parse content */
1593 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001594 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1595 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1596 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1597 };
Michal Vasko69730152020-10-09 16:30:07 +02001598
Michal Vaskob36053d2020-03-26 15:49:30 +01001599 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001600}
1601
David Sedlák5e13dea2019-07-22 16:06:45 +02001602/**
1603 * @brief Parse include element.
1604 *
1605 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001606 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1607 *
1608 * @return LY_ERR values.
1609 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001610static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001611yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001612{
1613 struct lysp_include *inc;
1614
1615 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001616 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001617
1618 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001619 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1620 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 +02001621
1622 /* submodules share the namespace with the module names, so there must not be
1623 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001624 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
David Sedlák1538a842019-08-08 15:38:51 +02001625 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001626 return LY_EVALID;
1627 }
1628
1629 /* parse content */
1630 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001631 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1632 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1633 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1634 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1635 };
Michal Vasko69730152020-10-09 16:30:07 +02001636
Michal Vaskob36053d2020-03-26 15:49:30 +01001637 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001638}
1639
David Sedlákaa854b02019-07-22 14:17:10 +02001640/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001641 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001642 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001643 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001644 * @param[in,out] rev Array to store the parsed value in.
1645 * @param[in,out] exts Extension instances to add to.
1646 *
1647 * @return LY_ERR values.
1648 */
1649static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001650yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001651{
1652 const char *temp_rev;
1653 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001654 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1655 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001656
Michal Vaskob36053d2020-03-26 15:49:30 +01001657 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1658 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 +02001659 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vasko69730152020-10-09 16:30:07 +02001660 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001661
1662 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001663 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001664
Michal Vaskob36053d2020-03-26 15:49:30 +01001665 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001666}
1667
1668/**
1669 * @brief Parse config element.
1670 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001671 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001672 * @param[in,out] flags Flags to add to.
1673 * @param[in,out] exts Extension instances to add to.
1674 *
1675 * @return LY_ERR values.
1676 */
1677static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001678yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001679{
1680 const char *temp_val = NULL;
1681 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001682 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1683 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001684
Michal Vaskob36053d2020-03-26 15:49:30 +01001685 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1686 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 +02001687 if (strcmp(temp_val, "true") == 0) {
1688 *flags |= LYS_CONFIG_W;
1689 } else if (strcmp(temp_val, "false") == 0) {
1690 *flags |= LYS_CONFIG_R;
1691 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001692 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001693 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001694 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001695 return LY_EVALID;
1696 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001697 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001698
Michal Vaskob36053d2020-03-26 15:49:30 +01001699 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001700}
1701
1702/**
1703 * @brief Parse yang-version element.
1704 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001705 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001706 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001707 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001708 *
1709 * @return LY_ERR values.
1710 */
1711static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001712yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001713{
1714 const char *temp_version = NULL;
1715 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001716 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1717 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001718
Michal Vaskob36053d2020-03-26 15:49:30 +01001719 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1720 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 +02001721 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001722 *version = LYS_VERSION_1_0;
1723 } else if (strcmp(temp_version, "1.1") == 0) {
1724 *version = LYS_VERSION_1_1;
1725 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001726 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001727 "yang-version", "1", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001728 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001729 return LY_EVALID;
1730 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001731 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001732
Michal Vaskob36053d2020-03-26 15:49:30 +01001733 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001734}
1735
1736/**
1737 * @brief Parse import element.
1738 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001739 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001740 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1741 *
1742 * @return LY_ERR values.
1743 */
1744static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001745yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001746{
1747 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001748
David Sedlákdfbbb442019-08-06 16:33:21 +02001749 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001750 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001751
1752 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001753 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1754 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1755 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1756 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1757 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1758 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001759
1760 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001761 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1762 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1763 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001764 /* check prefix validity */
1765 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1766
1767 return LY_SUCCESS;
1768}
1769
1770/**
1771 * @brief Parse mandatory element.
1772 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001773 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001774 * @param[in,out] flags Flags to add to.
1775 * @param[in,out] exts Extension instances to add to.
1776 *
1777 * @return LY_ERR values.
1778 */
1779static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001780yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001781{
1782 const char *temp_val = NULL;
1783 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001784 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1785 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001786
Michal Vaskob36053d2020-03-26 15:49:30 +01001787 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1788 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 +02001789 if (strcmp(temp_val, "true") == 0) {
1790 *flags |= LYS_MAND_TRUE;
1791 } else if (strcmp(temp_val, "false") == 0) {
1792 *flags |= LYS_MAND_FALSE;
1793 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001794 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001795 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001796 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001797 return LY_EVALID;
1798 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001799 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001800
Michal Vaskob36053d2020-03-26 15:49:30 +01001801 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001802}
1803
1804/**
1805 * @brief Parse status element.
1806 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001807 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001808 * @param[in,out] flags Flags to add to.
1809 * @param[in,out] exts Extension instances to add to.
1810 *
1811 * @return LY_ERR values.
1812 */
1813static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001814yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001815{
1816 const char *value = NULL;
1817 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001818 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1819 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001820
Michal Vaskob36053d2020-03-26 15:49:30 +01001821 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1822 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 +02001823 if (strcmp(value, "current") == 0) {
1824 *flags |= LYS_STATUS_CURR;
1825 } else if (strcmp(value, "deprecated") == 0) {
1826 *flags |= LYS_STATUS_DEPRC;
1827 } else if (strcmp(value, "obsolete") == 0) {
1828 *flags |= LYS_STATUS_OBSLT;
1829 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001830 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001831 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001832 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001833 return LY_EVALID;
1834 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001835 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001836
Michal Vaskob36053d2020-03-26 15:49:30 +01001837 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001838}
1839
1840/**
1841 * @brief Parse when element.
1842 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001843 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001844 * @param[out] when_p When pointer to parse to.
1845 */
1846static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001847yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001848{
1849 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001850 LY_ERR ret = LY_SUCCESS;
1851
David Sedlákdfbbb442019-08-06 16:33:21 +02001852 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001853 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001854
1855 ret = lyxml_ctx_next(ctx->xmlctx);
1856 LY_CHECK_ERR_RET(ret, free(when), ret);
1857
Michal Vaskob36053d2020-03-26 15:49:30 +01001858 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001859 LY_CHECK_ERR_RET(ret, free(when), ret);
1860
David Sedlákdfbbb442019-08-06 16:33:21 +02001861 *when_p = when;
1862 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001863 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1864 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1865 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1866 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001867
Michal Vaskob36053d2020-03-26 15:49:30 +01001868 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001869}
1870
1871/**
1872 * @brief Parse yin-elemenet element.
1873 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001874 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001875 * @param[in,out] data Data to read from, always moved to currently handled position.
1876 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001877 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001878 *
1879 * @return LY_ERR values.
1880 */
1881static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001882yin_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 +02001883{
1884 const char *temp_val = NULL;
1885 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001886 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1887 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001888
Michal Vaskob36053d2020-03-26 15:49:30 +01001889 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1890 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 +02001891 if (strcmp(temp_val, "true") == 0) {
1892 *flags |= LYS_YINELEM_TRUE;
1893 } else if (strcmp(temp_val, "false") == 0) {
1894 *flags |= LYS_YINELEM_FALSE;
1895 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001896 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001897 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001898 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001899 return LY_EVALID;
1900 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001901 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001902
Michal Vaskob36053d2020-03-26 15:49:30 +01001903 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001904}
1905
1906/**
1907 * @brief Parse argument element.
1908 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001909 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001910 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1911 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001912 *
1913 * @return LY_ERR values.
1914 */
1915static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001916yin_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 +02001917{
1918 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001919 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1920 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1921 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001922
Michal Vaskob36053d2020-03-26 15:49:30 +01001923 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1924 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 +02001925
Michal Vaskob36053d2020-03-26 15:49:30 +01001926 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001927}
1928
1929/**
1930 * @brief Parse the extension statement.
1931 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001932 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001933 * @param[in,out] extensions Extensions to add to.
1934 *
1935 * @return LY_ERR values.
1936 */
1937static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001938yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001939{
1940 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02001941
Michal Vaskob36053d2020-03-26 15:49:30 +01001942 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1943 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1944 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 +02001945
1946 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1947 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001948 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1949 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1950 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1951 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1952 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1953 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001954
Michal Vaskob36053d2020-03-26 15:49:30 +01001955 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001956}
1957
1958/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001959 * @brief Parse feature element.
1960 *
1961 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001962 * @param[in,out] features Features to add to.
1963 *
1964 * @return LY_ERR values.
1965 */
1966static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001967yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001968{
1969 struct lysp_feature *feat;
1970
1971 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001972 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001973
1974 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001975 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1976 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 +02001977
1978 /* parse content */
1979 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001980 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1981 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1982 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1983 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1984 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1985 };
Michal Vasko69730152020-10-09 16:30:07 +02001986
Michal Vaskob36053d2020-03-26 15:49:30 +01001987 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001988}
1989
1990/**
David Sedlák28794f22019-07-22 16:45:00 +02001991 * @brief Parse identity element.
1992 *
1993 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001994 * @param[in,out] identities Identities to add to.
1995 *
1996 * @return LY_ERR values.
1997 */
1998static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001999yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002000{
2001 struct lysp_ident *ident;
2002
2003 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002004 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002005
2006 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002007 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2008 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 +02002009
2010 /* parse content */
2011 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002012 {LY_STMT_BASE, &ident->bases, 0},
2013 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2014 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2015 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2016 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2017 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2018 };
Michal Vasko69730152020-10-09 16:30:07 +02002019
Michal Vaskob36053d2020-03-26 15:49:30 +01002020 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002021}
2022
2023/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002024 * @brief Parse list element.
2025 *
2026 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002027 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002028 *
2029 * @return LY_ERR values.
2030 */
2031static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002032yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002033{
David Sedlákaf536aa2019-07-23 13:42:23 +02002034 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002035 LY_ERR ret = LY_SUCCESS;
2036 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002037
Michal Vaskob36053d2020-03-26 15:49:30 +01002038 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002039 list->nodetype = LYS_LIST;
2040 list->parent = node_meta->parent;
2041
David Sedlákaf536aa2019-07-23 13:42:23 +02002042 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002043 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2044 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 +02002045
2046 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002047 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002048 LY_STMT_ACTION, &list->actions, 0,
2049 LY_STMT_ANYDATA, &list->child, 0,
2050 LY_STMT_ANYXML, &list->child, 0,
2051 LY_STMT_CHOICE, &list->child, 0,
2052 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2053 LY_STMT_CONTAINER, &list->child, 0,
2054 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2055 LY_STMT_GROUPING, &list->groupings, 0,
2056 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2057 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2058 LY_STMT_LEAF, &list->child, 0,
2059 LY_STMT_LEAF_LIST, &list->child, 0,
2060 LY_STMT_LIST, &list->child, 0,
2061 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2062 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2063 LY_STMT_MUST, &list->musts, 0,
2064 LY_STMT_NOTIFICATION, &list->notifs, 0,
2065 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2066 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2067 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2068 LY_STMT_TYPEDEF, &list->typedefs, 0,
2069 LY_STMT_UNIQUE, &list->uniques, 0,
2070 LY_STMT_USES, &list->child, 0,
2071 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2072 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002073 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002074 subelems_deallocator(25, subelems);
2075 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002076
2077 /* finalize parent pointers to the reallocated items */
2078 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2079
Michal Vasko69730152020-10-09 16:30:07 +02002080 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002081 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002082 return LY_EVALID;
2083 }
2084
2085 return LY_SUCCESS;
2086}
2087
2088/**
David Sedlák031b9e72019-07-23 15:19:37 +02002089 * @brief Parse notification element.
2090 *
2091 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002092 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002093 *
2094 * @return LY_ERR values.
2095 */
2096static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002097yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002098{
2099 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002100 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002101 LY_ERR ret = LY_SUCCESS;
2102 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002103
2104 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002105 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002106 notif->nodetype = LYS_NOTIF;
2107 notif->parent = notif_meta->parent;
2108
2109 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002110 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2111 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 +02002112
2113 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002114 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002115 LY_STMT_ANYDATA, &notif->data, 0,
2116 LY_STMT_ANYXML, &notif->data, 0,
2117 LY_STMT_CHOICE, &notif->data, 0,
2118 LY_STMT_CONTAINER, &notif->data, 0,
2119 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2120 LY_STMT_GROUPING, &notif->groupings, 0,
2121 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2122 LY_STMT_LEAF, &notif->data, 0,
2123 LY_STMT_LEAF_LIST, &notif->data, 0,
2124 LY_STMT_LIST, &notif->data, 0,
2125 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2126 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2127 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2128 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2129 LY_STMT_USES, &notif->data, 0,
2130 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002131
Michal Vaskob36053d2020-03-26 15:49:30 +01002132 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002133 subelems_deallocator(16, subelems);
2134 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002135
2136 /* finalize parent pointers to the reallocated items */
2137 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2138
2139 return LY_SUCCESS;
2140}
2141
2142/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002143 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002144 *
2145 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002146 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002147 *
2148 * @return LY_ERR values.
2149 */
2150static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002151yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002152{
2153 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002154 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002155 LY_ERR ret = LY_SUCCESS;
2156 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002157
2158 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002159 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002160 grp->nodetype = LYS_GROUPING;
2161 grp->parent = gr_meta->parent;
2162
2163 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002164 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2165 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 +02002166
2167 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002168 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002169 LY_STMT_ACTION, &grp->actions, 0,
2170 LY_STMT_ANYDATA, &grp->data, 0,
2171 LY_STMT_ANYXML, &grp->data, 0,
2172 LY_STMT_CHOICE, &grp->data, 0,
2173 LY_STMT_CONTAINER, &grp->data, 0,
2174 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2175 LY_STMT_GROUPING, &grp->groupings, 0,
2176 LY_STMT_LEAF, &grp->data, 0,
2177 LY_STMT_LEAF_LIST, &grp->data, 0,
2178 LY_STMT_LIST, &grp->data, 0,
2179 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2180 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2181 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2182 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2183 LY_STMT_USES, &grp->data, 0,
2184 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002185 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002186 subelems_deallocator(16, subelems);
2187 LY_CHECK_RET(ret);
2188
David Sedláke3ce9ef2019-07-23 16:34:30 +02002189 /* finalize parent pointers to the reallocated items */
2190 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2191
2192 return LY_SUCCESS;
2193}
2194
2195/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002196 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002197 *
2198 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002199 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002200 *
2201 * @return LY_ERR values.
2202 */
2203static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002204yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002205{
David Sedlákf111bcb2019-07-23 17:15:51 +02002206 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002207 LY_ERR ret = LY_SUCCESS;
2208 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002209
2210 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002211 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002212 cont->nodetype = LYS_CONTAINER;
2213 cont->parent = node_meta->parent;
2214
David Sedlákf111bcb2019-07-23 17:15:51 +02002215 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002216 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2217 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 +02002218
2219 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002220 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002221 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2222 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2223 LY_STMT_ANYXML, &cont->child, 0,
2224 LY_STMT_CHOICE, &cont->child, 0,
2225 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2226 LY_STMT_CONTAINER, &cont->child, 0,
2227 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2228 LY_STMT_GROUPING, &cont->groupings, 0,
2229 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2230 LY_STMT_LEAF, &cont->child, 0,
2231 LY_STMT_LEAF_LIST, &cont->child, 0,
2232 LY_STMT_LIST, &cont->child, 0,
2233 LY_STMT_MUST, &cont->musts, 0,
2234 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2235 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2236 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2237 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2238 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2239 LY_STMT_USES, &cont->child, 0,
2240 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2241 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002242 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002243 subelems_deallocator(21, subelems);
2244 LY_CHECK_RET(ret);
2245
David Sedlákf111bcb2019-07-23 17:15:51 +02002246 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2247
2248 return LY_SUCCESS;
2249}
2250
2251/**
David Sedlák5379d392019-07-24 10:42:03 +02002252 * @brief Parse case element.
2253 *
2254 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002255 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002256 *
2257 * @return LY_ERR values.
2258 */
2259static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002260yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002261{
David Sedlák5379d392019-07-24 10:42:03 +02002262 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002263 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002264 struct yin_subelement *subelems = NULL;
David Sedlák5379d392019-07-24 10:42:03 +02002265
2266 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002267 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002268 cas->nodetype = LYS_CASE;
2269 cas->parent = node_meta->parent;
2270
David Sedlák5379d392019-07-24 10:42:03 +02002271 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002272 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2273 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 +02002274
2275 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002276 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002277 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2278 LY_STMT_ANYXML, &cas->child, 0,
2279 LY_STMT_CHOICE, &cas->child, 0,
2280 LY_STMT_CONTAINER, &cas->child, 0,
2281 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2282 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2283 LY_STMT_LEAF, &cas->child, 0,
2284 LY_STMT_LEAF_LIST, &cas->child, 0,
2285 LY_STMT_LIST, &cas->child, 0,
2286 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2287 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2288 LY_STMT_USES, &cas->child, 0,
2289 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2290 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002291 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002292 subelems_deallocator(14, subelems);
2293
2294 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002295}
2296
2297/**
David Sedlák05404f62019-07-24 14:11:53 +02002298 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002299 *
2300 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002301 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002302 *
2303 * @return LY_ERR values.
2304 */
2305LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002306yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002307{
David Sedlák81497a32019-08-13 16:56:26 +02002308 LY_ERR ret = LY_SUCCESS;
2309 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002310 struct lysp_node_choice *choice;
2311
2312 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002313 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002314
David Sedlákb7abcfa2019-07-24 12:33:35 +02002315 choice->nodetype = LYS_CHOICE;
2316 choice->parent = node_meta->parent;
2317
David Sedlákb7abcfa2019-07-24 12:33:35 +02002318 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002319 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2320 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 +02002321
2322 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002323 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002324 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2325 LY_STMT_ANYXML, &choice->child, 0,
2326 LY_STMT_CASE, &choice->child, 0,
2327 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2328 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2329 LY_STMT_CONTAINER, &choice->child, 0,
2330 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2331 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2332 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2333 LY_STMT_LEAF, &choice->child, 0,
2334 LY_STMT_LEAF_LIST, &choice->child, 0,
2335 LY_STMT_LIST, &choice->child, 0,
2336 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2337 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2338 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2339 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2340 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002341 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002342 subelems_deallocator(17, subelems);
2343 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002344}
2345
2346/**
David Sedlák05404f62019-07-24 14:11:53 +02002347 * @brief Parse input or output element.
2348 *
2349 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002350 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002351 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2352 *
2353 * @return LY_ERR values.
2354 */
2355static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002356yin_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 +02002357{
David Sedlák81497a32019-08-13 16:56:26 +02002358 LY_ERR ret = LY_SUCCESS;
2359 struct yin_subelement *subelems = NULL;
2360
David Sedlák05404f62019-07-24 14:11:53 +02002361 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002362 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002363 inout_meta->inout_p->parent = inout_meta->parent;
2364
2365 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002366 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2367 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 +02002368
2369 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002370 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002371 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2372 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2373 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2374 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2375 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2376 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2377 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2378 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2379 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2380 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2381 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2382 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002383 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002384 subelems_deallocator(12, subelems);
2385 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002386
Michal Vaskob83af8a2020-01-06 09:49:22 +01002387 if (!inout_meta->inout_p->data) {
2388 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2389 return LY_EVALID;
2390 }
2391
David Sedlák05404f62019-07-24 14:11:53 +02002392 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002393 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings, NULL, NULL, NULL));
David Sedlák05404f62019-07-24 14:11:53 +02002394
2395 return LY_SUCCESS;
2396}
2397
David Sedlák992fb7c2019-07-24 16:51:01 +02002398/**
2399 * @brief Parse action element.
2400 *
2401 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002402 * @param[in] act_meta Meta information about parent node and actions to add to.
2403 *
2404 * @return LY_ERR values.
2405 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002406static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002407yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002408{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002409 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002410 LY_ERR ret = LY_SUCCESS;
2411 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002412
2413 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002414 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002415 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002416 act->parent = act_meta->parent;
2417
2418 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002419 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2420 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 +02002421
2422 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002423 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002424 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2425 LY_STMT_GROUPING, &act->groupings, 0,
2426 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2427 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2428 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2429 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2430 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2431 LY_STMT_TYPEDEF, &act->typedefs, 0,
2432 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002433 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002434 subelems_deallocator(9, subelems);
2435 LY_CHECK_RET(ret);
2436
Michal Vasko7f45cf22020-10-01 12:49:44 +02002437 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2438 if (!act->input.nodetype) {
2439 act->input.nodetype = LYS_INPUT;
2440 act->input.parent = (struct lysp_node *)act;
2441 }
2442 if (!act->output.nodetype) {
2443 act->output.nodetype = LYS_OUTPUT;
2444 act->output.parent = (struct lysp_node *)act;
2445 }
2446
David Sedlák85d0eca2019-07-24 15:15:21 +02002447 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2448
2449 return LY_SUCCESS;
2450}
2451
David Sedlák05404f62019-07-24 14:11:53 +02002452/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002453 * @brief Parse augment element.
2454 *
2455 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002456 * @param[in] aug_meta Meta information about parent node and augments to add to.
2457 *
2458 * @return LY_ERR values.
2459 */
2460static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002461yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002462{
2463 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002464 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002465 LY_ERR ret = LY_SUCCESS;
2466 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002467
2468 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002469 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002470 aug->nodetype = LYS_AUGMENT;
2471 aug->parent = aug_meta->parent;
2472
2473 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002474 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2475 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2476 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002477
2478 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002479 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002480 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2481 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2482 LY_STMT_ANYXML, &aug->child, 0,
2483 LY_STMT_CASE, &aug->child, 0,
2484 LY_STMT_CHOICE, &aug->child, 0,
2485 LY_STMT_CONTAINER, &aug->child, 0,
2486 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002487 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
Michal Vasko69730152020-10-09 16:30:07 +02002488 LY_STMT_LEAF, &aug->child, 0,
2489 LY_STMT_LEAF_LIST, &aug->child, 0,
2490 LY_STMT_LIST, &aug->child, 0,
2491 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2492 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2493 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2494 LY_STMT_USES, &aug->child, 0,
2495 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2496 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002497 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002498 subelems_deallocator(17, subelems);
2499 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002500
2501 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2502
2503 return LY_SUCCESS;
2504}
2505
David Sedlák8b754462019-07-25 16:22:13 +02002506/**
2507 * @brief Parse deviate element.
2508 *
2509 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002510 * @param[in] deviates Deviates to add to.
2511 *
2512 * @return LY_ERR values.
2513 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002514static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002515yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002516{
2517 LY_ERR ret = LY_SUCCESS;
2518 uint8_t dev_mod;
2519 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002520 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002521 struct lysp_deviate_add *d_add = NULL;
2522 struct lysp_deviate_rpl *d_rpl = NULL;
2523 struct lysp_deviate_del *d_del = NULL;
2524
2525 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002526 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2527 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 +02002528
2529 if (strcmp(temp_val, "not-supported") == 0) {
2530 dev_mod = LYS_DEV_NOT_SUPPORTED;
2531 } else if (strcmp(temp_val, "add") == 0) {
2532 dev_mod = LYS_DEV_ADD;
2533 } else if (strcmp(temp_val, "replace") == 0) {
2534 dev_mod = LYS_DEV_REPLACE;
2535 } else if (strcmp(temp_val, "delete") == 0) {
2536 dev_mod = LYS_DEV_DELETE;
2537 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002538 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002539 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002540 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002541 return LY_EVALID;
2542 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002543 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002544
2545 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2546 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002547 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002548 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002549 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2550 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002551 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002552
2553 } else if (dev_mod == LYS_DEV_ADD) {
2554 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002555 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002556 d = (struct lysp_deviate *)d_add;
2557 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2558 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2559 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002560 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002561 {LY_STMT_DEFAULT, &d_add->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002562 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2563 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2564 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2565 {LY_STMT_MUST, &d_add->musts, 0},
2566 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2567 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2568 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2569 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002570 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002571
2572 } else if (dev_mod == LYS_DEV_REPLACE) {
2573 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002574 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002575 d = (struct lysp_deviate *)d_rpl;
2576 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2577 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2578 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002579 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002580 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
Radek Krejci0f969882020-08-21 16:56:47 +02002581 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2582 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2583 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2584 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2585 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2586 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2587 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002588 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002589
2590 } else {
2591 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002592 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002593 d = (struct lysp_deviate *)d_del;
2594 struct yin_subelement subelems[5] = {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002595 {LY_STMT_DEFAULT, &d_del->dflts, 0},
Radek Krejci0f969882020-08-21 16:56:47 +02002596 {LY_STMT_MUST, &d_del->musts, 0},
2597 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2598 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2599 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2600 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002601 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002602 }
2603 LY_CHECK_GOTO(ret, cleanup);
2604
2605 d->mod = dev_mod;
2606 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002607 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002608
2609 return ret;
2610
2611cleanup:
2612 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002613 return ret;
2614}
2615
David Sedlák992fb7c2019-07-24 16:51:01 +02002616/**
David Sedlák8b754462019-07-25 16:22:13 +02002617 * @brief Parse deviation element.
2618 *
2619 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002620 * @param[in] deviations Deviations to add to.
2621 *
2622 * @return LY_ERR values.
2623 */
2624static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002625yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002626{
2627 struct lysp_deviation *dev;
2628
2629 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002630 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002631
2632 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002633 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2634 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2635 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002636 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002637 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2638 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2639 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2640 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2641 };
Michal Vasko69730152020-10-09 16:30:07 +02002642
Michal Vaskob36053d2020-03-26 15:49:30 +01002643 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002644}
2645
2646/**
David Sedlákb4e44562019-07-04 15:42:12 +02002647 * @brief Map keyword type to substatement info.
2648 *
2649 * @param[in] kw Keyword type.
2650 *
2651 * @return correct LYEXT_SUBSTMT information.
2652 */
2653static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002654kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002655{
2656 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002657 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002658 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002659 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002660 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002661 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002662 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002663 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002664 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002665 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002666 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002667 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002668 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002669 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002670 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002671 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002672 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002673 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002674 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002675 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002676 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002677 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002678 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002679 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002680 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002681 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002682 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002683 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002684 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002685 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002686 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002687 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002688 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002689 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002690 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002691 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002692 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002693 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002694 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002695 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002696 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002697 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002698 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002699 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002700 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002701 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002702 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002703 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002704 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002706 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002707 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002708 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002709 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002710 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002711 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002712 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002713 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002714 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002715 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002716 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002717 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002718 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002719 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002720 return LYEXT_SUBSTMT_IFFEATURE;
2721 default:
2722 return LYEXT_SUBSTMT_SELF;
2723 }
2724}
2725
David Sedlákc5b20842019-08-13 10:18:31 +02002726/**
2727 * @brief map keyword to keyword-group.
2728 *
2729 * @param[in] ctx YIN parser context used for logging.
2730 * @param[in] kw Keyword that is child of module or submodule.
2731 * @param[out] group Group of keyword.
2732 *
2733 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2734 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002735static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002736kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002737{
2738 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002739 /* module header */
2740 case LY_STMT_NONE:
2741 case LY_STMT_NAMESPACE:
2742 case LY_STMT_PREFIX:
2743 case LY_STMT_BELONGS_TO:
2744 case LY_STMT_YANG_VERSION:
2745 *group = Y_MOD_MODULE_HEADER;
2746 break;
2747 /* linkage */
2748 case LY_STMT_INCLUDE:
2749 case LY_STMT_IMPORT:
2750 *group = Y_MOD_LINKAGE;
2751 break;
2752 /* meta */
2753 case LY_STMT_ORGANIZATION:
2754 case LY_STMT_CONTACT:
2755 case LY_STMT_DESCRIPTION:
2756 case LY_STMT_REFERENCE:
2757 *group = Y_MOD_META;
2758 break;
2759 /* revision */
2760 case LY_STMT_REVISION:
2761 *group = Y_MOD_REVISION;
2762 break;
2763 /* body */
2764 case LY_STMT_ANYDATA:
2765 case LY_STMT_ANYXML:
2766 case LY_STMT_AUGMENT:
2767 case LY_STMT_CHOICE:
2768 case LY_STMT_CONTAINER:
2769 case LY_STMT_DEVIATION:
2770 case LY_STMT_EXTENSION:
2771 case LY_STMT_FEATURE:
2772 case LY_STMT_GROUPING:
2773 case LY_STMT_IDENTITY:
2774 case LY_STMT_LEAF:
2775 case LY_STMT_LEAF_LIST:
2776 case LY_STMT_LIST:
2777 case LY_STMT_NOTIFICATION:
2778 case LY_STMT_RPC:
2779 case LY_STMT_TYPEDEF:
2780 case LY_STMT_USES:
2781 case LY_STMT_EXTENSION_INSTANCE:
2782 *group = Y_MOD_BODY;
2783 break;
2784 default:
2785 LOGINT(ctx->xmlctx->ctx);
2786 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002787 }
2788
2789 return LY_SUCCESS;
2790}
2791
David Sedlákc5b20842019-08-13 10:18:31 +02002792/**
2793 * @brief Check if relative order of two keywords is valid.
2794 *
2795 * @param[in] ctx YIN parser context used for logging.
2796 * @param[in] kw Current keyword.
2797 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002798 * @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 +02002799 * because relative order is required only in module and submodule sub-elements, used for logging.
2800 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002801 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002802 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002803static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002804yin_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 +02002805{
Radek Krejcid6b76452019-09-03 17:03:03 +02002806 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002807 enum yang_module_stmt gr, next_gr;
2808
2809 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2810 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2811
2812 if (gr > next_gr) {
2813 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2814 return LY_EVALID;
2815 }
2816
2817 return LY_SUCCESS;
2818}
2819
David Sedlákc5dd0942019-09-13 10:23:59 +02002820/**
2821 * @brief Get element name prefixed by full URI of xml namespace.
2822 *
2823 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2824 * @param[in] name Name of element.
2825 * @param[in] name_len Length of element name.
2826 * @param[in] prefix Prefix of element.
2827 * @param[in] prefix_len Length of element prefix.
2828 *
2829 * @return Element name prefixed by URI on success, NULL on failure.
2830 */
2831static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002832name2nsname(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 +02002833{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002834 const char *ename = NULL;
Michal Vaskoc8a230d2020-08-14 12:17:10 +02002835 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002836
Michal Vaskob36053d2020-03-26 15:49:30 +01002837 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002838
Radek Krejci02728562019-09-18 14:13:05 +02002839 if (!strcmp(ns->uri, YIN_NS_URI)) {
2840 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002841 lydict_insert(ctx->xmlctx->ctx, name, name_len, &ename);
2842 return ename;
Radek Krejci02728562019-09-18 14:13:05 +02002843 }
2844 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002845 size_t ns_len = strlen(ns->uri);
2846 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2847
2848 char *result;
2849 char *temp;
Michal Vasko69730152020-10-09 16:30:07 +02002850
David Sedláke0ef1c62019-09-13 10:05:55 +02002851 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002852 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002853
2854 strcpy(result, ns->uri);
2855 result[ns_len] = ':';
2856 temp = &result[ns_len + 1];
2857 strncpy(temp, name, name_len);
2858 result[len] = '\0';
2859
Radek Krejci011e4aa2020-09-04 15:22:31 +02002860 lydict_insert_zc(ctx->xmlctx->ctx, result, &ename);
2861 return ename;
David Sedlák068dd352019-09-13 09:08:22 +02002862}
2863
David Sedlákd6e56892019-07-01 15:40:24 +02002864LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002865yin_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 +02002866 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002867{
2868 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002869 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002870 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002871 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002872
Michal Vaskob36053d2020-03-26 15:49:30 +01002873 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002874
Michal Vaskob36053d2020-03-26 15:49:30 +01002875 if (ctx->xmlctx->ws_only) {
2876 /* check whether there are any children */
2877 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2878 } else {
2879 /* we want to parse the value */
2880 next_status = LYXML_ELEM_CLOSE;
2881 }
2882
2883 if (next_status == LYXML_ELEMENT) {
2884 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2885
2886 /* current element has subelements as content */
2887 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2888 /* match keyword */
2889 last_kw = kw;
2890 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02002891 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01002892
2893 /* check if this element can be child of current element */
2894 subelem = get_record(kw, subelem_info_size, subelem_info);
2895 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02002896 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01002897 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2898 } else {
2899 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02002900 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01002901 }
2902 ret = LY_EVALID;
2903 goto cleanup;
2904 }
2905
2906 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02002907 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01002908 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2909 LY_CHECK_GOTO(ret, cleanup);
2910 }
2911
2912 /* flag check */
2913 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2914 /* subelement uniquenes */
2915 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2916 return LY_EVALID;
2917 }
2918 if (subelem->flags & YIN_SUBELEM_FIRST) {
2919 /* subelement is supposed to be defined as first subelement */
2920 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2921 LY_CHECK_GOTO(ret, cleanup);
2922 }
2923 if (subelem->flags & YIN_SUBELEM_VER2) {
2924 /* subelement is supported only in version 1.1 or higher */
Michal Vasko5d24f6c2020-10-13 13:49:06 +02002925 if (ctx->parsed_mod->version < LYS_VERSION_1_1) {
Michal Vaskob36053d2020-03-26 15:49:30 +01002926 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 +02002927 ret = LY_EVALID;
2928 goto cleanup;
2929 }
David Sedlákd6e56892019-07-01 15:40:24 +02002930 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002931 /* note that element was parsed for easy uniqueness check in next iterations */
2932 subelem->flags |= YIN_SUBELEM_PARSED;
2933
2934 switch (kw) {
2935 /* call responsible function */
2936 case LY_STMT_EXTENSION_INSTANCE:
2937 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vasko69730152020-10-09 16:30:07 +02002938 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002939 break;
2940 case LY_STMT_ACTION:
2941 case LY_STMT_RPC:
2942 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2943 break;
2944 case LY_STMT_ANYDATA:
2945 case LY_STMT_ANYXML:
2946 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2947 break;
2948 case LY_STMT_ARGUMENT:
2949 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2950 break;
2951 case LY_STMT_AUGMENT:
2952 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2953 break;
2954 case LY_STMT_BASE:
2955 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2956 break;
2957 case LY_STMT_BELONGS_TO:
2958 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2959 break;
2960 case LY_STMT_BIT:
2961 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2962 break;
2963 case LY_STMT_CASE:
2964 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2965 break;
2966 case LY_STMT_CHOICE:
2967 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2968 break;
2969 case LY_STMT_CONFIG:
2970 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2971 break;
2972 case LY_STMT_CONTACT:
2973 case LY_STMT_DESCRIPTION:
2974 case LY_STMT_ORGANIZATION:
2975 case LY_STMT_REFERENCE:
2976 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2977 break;
2978 case LY_STMT_CONTAINER:
2979 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2980 break;
2981 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002982 ret = yin_parse_qname(ctx, kw, subelem, exts);
2983 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01002984 case LY_STMT_ERROR_APP_TAG:
2985 case LY_STMT_KEY:
2986 case LY_STMT_PRESENCE:
2987 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2988 break;
2989 case LY_STMT_DEVIATE:
2990 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2991 break;
2992 case LY_STMT_DEVIATION:
2993 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2994 break;
2995 case LY_STMT_ENUM:
2996 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2997 break;
2998 case LY_STMT_ERROR_MESSAGE:
2999 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3000 break;
3001 case LY_STMT_EXTENSION:
3002 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3003 break;
3004 case LY_STMT_FEATURE:
3005 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3006 break;
3007 case LY_STMT_FRACTION_DIGITS:
3008 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3009 break;
3010 case LY_STMT_GROUPING:
3011 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3012 break;
3013 case LY_STMT_IDENTITY:
3014 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3015 break;
3016 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003017 ret = yin_parse_qname(ctx, kw, subelem, exts);
3018 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003019 case LY_STMT_UNITS:
3020 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3021 break;
3022 case LY_STMT_IMPORT:
3023 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3024 break;
3025 case LY_STMT_INCLUDE:
3026 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3027 break;
3028 case LY_STMT_INPUT:
3029 case LY_STMT_OUTPUT:
3030 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3031 break;
3032 case LY_STMT_LEAF:
3033 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3034 break;
3035 case LY_STMT_LEAF_LIST:
3036 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3037 break;
3038 case LY_STMT_LENGTH:
3039 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3040 break;
3041 case LY_STMT_LIST:
3042 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3043 break;
3044 case LY_STMT_MANDATORY:
3045 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3046 break;
3047 case LY_STMT_MAX_ELEMENTS:
3048 case LY_STMT_MIN_ELEMENTS:
3049 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3050 break;
3051 case LY_STMT_MODIFIER:
3052 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3053 break;
3054 case LY_STMT_MUST:
3055 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3056 break;
3057 case LY_STMT_NAMESPACE:
3058 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3059 break;
3060 case LY_STMT_NOTIFICATION:
3061 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3062 break;
3063 case LY_STMT_ORDERED_BY:
3064 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3065 break;
3066 case LY_STMT_PATH:
3067 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3068 break;
3069 case LY_STMT_PATTERN:
3070 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3071 break;
3072 case LY_STMT_VALUE:
3073 case LY_STMT_POSITION:
3074 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3075 break;
3076 case LY_STMT_PREFIX:
3077 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3078 break;
3079 case LY_STMT_RANGE:
3080 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3081 break;
3082 case LY_STMT_REFINE:
3083 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3084 break;
3085 case LY_STMT_REQUIRE_INSTANCE:
3086 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3087 break;
3088 case LY_STMT_REVISION:
3089 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3090 break;
3091 case LY_STMT_REVISION_DATE:
3092 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3093 break;
3094 case LY_STMT_STATUS:
3095 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3096 break;
3097 case LY_STMT_TYPE:
3098 ret = yin_parse_type(ctx, current_element, subelem);
3099 break;
3100 case LY_STMT_TYPEDEF:
3101 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3102 break;
3103 case LY_STMT_UNIQUE:
3104 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3105 break;
3106 case LY_STMT_USES:
3107 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3108 break;
3109 case LY_STMT_WHEN:
3110 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3111 break;
3112 case LY_STMT_YANG_VERSION:
3113 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3114 break;
3115 case LY_STMT_YIN_ELEMENT:
3116 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3117 break;
3118 case LY_STMT_ARG_TEXT:
3119 case LY_STMT_ARG_VALUE:
3120 /* TODO what to do with content/attributes? */
3121 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3122 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3123 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3124 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3125 }
3126 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3127 break;
3128 default:
3129 LOGINT(ctx->xmlctx->ctx);
3130 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003131 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003132 LY_CHECK_GOTO(ret, cleanup);
3133 subelem = NULL;
3134
3135 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003136 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003137 } else {
3138 LY_CHECK_RET(ret);
3139 /* elements with text or none content */
3140 /* save text content, if text_content isn't set, it's just ignored */
3141 /* no resources are allocated in this branch, no need to use cleanup label */
3142 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3143 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003144 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 +01003145 LY_CHECK_RET(!*text_content, LY_EMEM);
3146 }
3147
3148 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003149 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003150
David Sedlák8b754462019-07-25 16:22:13 +02003151 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3152 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003153
3154cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003155 return ret;
3156}
3157
David Sedlák619db942019-07-03 14:47:30 +02003158LY_ERR
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003159yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, LY_ARRAY_COUNT_TYPE subelem_index,
Radek Krejci0f969882020-08-21 16:56:47 +02003160 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003161{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003162 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003163 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003164
Michal Vaskob36053d2020-03-26 15:49:30 +01003165 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3166
3167 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003168
3169 e->yin = 0;
3170 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003171 e->name = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
David Sedláke0ef1c62019-09-13 10:05:55 +02003172 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003173 e->insubstmt = subelem;
3174 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003175 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003176 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003177
David Sedlákb1a78352019-06-28 16:16:29 +02003178 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003179 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3180 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003181 new_subelem = calloc(1, sizeof(*new_subelem));
3182 if (!e->child) {
3183 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003184 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003185 last_subelem->next = new_subelem;
3186 }
3187 last_subelem = new_subelem;
3188
3189 last_subelem->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003190 LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
David Sedlák169cc522019-08-15 13:23:45 +02003191 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003192 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003193
Radek Krejci011e4aa2020-09-04 15:22:31 +02003194 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last_subelem->arg);
David Sedlák169cc522019-08-15 13:23:45 +02003195 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003196 } else {
3197 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003198 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003199
3200 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003201 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003202
David Sedlákf250ecf2019-07-01 11:02:05 +02003203 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003204 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3205 if (ctx->xmlctx->ws_only) {
3206 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3207 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3208 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3209 if (!e->child) {
3210 e->child = new_subelem;
3211 } else {
3212 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003213 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003214 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003215
Michal Vaskob36053d2020-03-26 15:49:30 +01003216 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3217 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003218 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003219 } else if (ctx->xmlctx->value_len) {
3220 /* save text content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003221 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, e->argument);
Michal Vaskob36053d2020-03-26 15:49:30 +01003222 LY_CHECK_RET(!e->argument, LY_EMEM);
3223
3224 /* parser next */
3225 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003226 }
3227
3228 return LY_SUCCESS;
3229}
3230
David Sedlákaa98bba2019-09-12 11:52:14 +02003231/**
3232 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3233 *
3234 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003235 * @param[in] elem_type Type of element that is currently being parsed.
3236 * @param[out] arg Value to write to.
3237 *
3238 * @return LY_ERR values.
3239 */
3240static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003241yin_parse_extension_instance_arg(struct lys_yin_parser_ctx *ctx, enum ly_stmt elem_type, const char **arg)
David Sedláke6284fc2019-09-10 11:57:02 +02003242{
David Sedlák071f7662019-09-12 02:02:51 +02003243 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003244
Michal Vaskob36053d2020-03-26 15:49:30 +01003245 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3246
David Sedláke6284fc2019-09-10 11:57:02 +02003247 switch (elem_type) {
3248 case LY_STMT_ACTION:
3249 case LY_STMT_ANYDATA:
3250 case LY_STMT_ANYXML:
3251 case LY_STMT_ARGUMENT:
3252 case LY_STMT_BASE:
3253 case LY_STMT_BIT:
3254 case LY_STMT_CASE:
3255 case LY_STMT_CHOICE:
3256 case LY_STMT_CONTAINER:
3257 case LY_STMT_ENUM:
3258 case LY_STMT_EXTENSION:
3259 case LY_STMT_FEATURE:
3260 case LY_STMT_GROUPING:
3261 case LY_STMT_IDENTITY:
3262 case LY_STMT_IF_FEATURE:
3263 case LY_STMT_LEAF:
3264 case LY_STMT_LEAF_LIST:
3265 case LY_STMT_LIST:
3266 case LY_STMT_MODULE:
3267 case LY_STMT_NOTIFICATION:
3268 case LY_STMT_RPC:
3269 case LY_STMT_SUBMODULE:
3270 case LY_STMT_TYPE:
3271 case LY_STMT_TYPEDEF:
3272 case LY_STMT_UNITS:
3273 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003274 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003275 break;
3276 case LY_STMT_AUGMENT:
3277 case LY_STMT_DEVIATION:
3278 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003279 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003280 break;
3281 case LY_STMT_CONFIG:
3282 case LY_STMT_DEFAULT:
3283 case LY_STMT_DEVIATE:
3284 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003285 case LY_STMT_FRACTION_DIGITS:
3286 case LY_STMT_KEY:
3287 case LY_STMT_LENGTH:
3288 case LY_STMT_MANDATORY:
3289 case LY_STMT_MAX_ELEMENTS:
3290 case LY_STMT_MIN_ELEMENTS:
3291 case LY_STMT_MODIFIER:
3292 case LY_STMT_ORDERED_BY:
3293 case LY_STMT_PATH:
3294 case LY_STMT_PATTERN:
3295 case LY_STMT_POSITION:
3296 case LY_STMT_PREFIX:
3297 case LY_STMT_PRESENCE:
3298 case LY_STMT_RANGE:
3299 case LY_STMT_REQUIRE_INSTANCE:
3300 case LY_STMT_STATUS:
3301 case LY_STMT_VALUE:
3302 case LY_STMT_YANG_VERSION:
3303 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003304 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003305 break;
3306 case LY_STMT_IMPORT:
3307 case LY_STMT_INCLUDE:
3308 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003309 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003310 break;
3311 case LY_STMT_INPUT:
3312 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003313 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003314 break;
3315 case LY_STMT_MUST:
3316 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003317 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003318 break;
3319 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003320 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003321 break;
3322 case LY_STMT_REVISION:
3323 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003324 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003325 break;
3326 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003327 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
David Sedláke6284fc2019-09-10 11:57:02 +02003328 break;
David Sedlák071f7662019-09-12 02:02:51 +02003329 /* argument is mapped to yin element */
3330 case LY_STMT_CONTACT:
3331 case LY_STMT_DESCRIPTION:
3332 case LY_STMT_ORGANIZATION:
3333 case LY_STMT_REFERENCE:
3334 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003335 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003336 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3337
3338 /* no content */
3339 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3340 if (ctx->xmlctx->ws_only) {
3341 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3342 }
3343 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +02003345 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003346 return LY_EVALID;
3347 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003348
3349 /* parse child element */
3350 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
Michal Vasko69730152020-10-09 16:30:07 +02003351 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3352 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003353 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
Michal Vasko69730152020-10-09 16:30:07 +02003354 ly_stmt2str(elem_type));
Michal Vaskob36053d2020-03-26 15:49:30 +01003355 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003356 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003357 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3358
3359 /* no attributes expected? TODO */
3360 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3361 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3362 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3363 }
3364
3365 /* load and save content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003366 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
Michal Vaskob36053d2020-03-26 15:49:30 +01003367 LY_CHECK_RET(!*arg, LY_EMEM);
3368
3369 /* load closing tag of subelement */
3370 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3371
3372 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3373 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3374 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3375 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003376 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003377 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003378 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003379 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003380 }
3381
David Sedlák071f7662019-09-12 02:02:51 +02003382 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003383}
3384
3385LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003386yin_parse_element_generic(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003387{
3388 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003389 struct lysp_stmt *last = NULL, *new = NULL;
3390
Michal Vaskob36053d2020-03-26 15:49:30 +01003391 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003392
3393 /* allocate new structure for element */
3394 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003395 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3396 (*element)->stmt = name2nsname(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len);
David Sedláke0ef1c62019-09-13 10:05:55 +02003397 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003398
Michal Vaskob36053d2020-03-26 15:49:30 +01003399 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003400 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003401
3402 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003403 if ((*element)->kw == LY_STMT_NONE) {
3404 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003405 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
Michal Vasko69730152020-10-09 16:30:07 +02003406 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003407 ret = LY_EVALID;
3408 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003409 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3410 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003411 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003412 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003413 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003414 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3415
David Sedlákaa98bba2019-09-12 11:52:14 +02003416 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003417 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003418 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003419 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003420 if (!(*element)->child) {
3421 /* save first */
3422 (*element)->child = new;
3423 } else {
3424 last->next = new;
3425 }
3426 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003427
David Sedláke6284fc2019-09-10 11:57:02 +02003428 last->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003429 LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003430 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003431 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003432 if (!ctx->xmlctx->prefix) {
3433 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3434
Radek Krejci011e4aa2020-09-04 15:22:31 +02003435 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003436 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003437 } else {
3438 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003439 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003440 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003441 }
3442 }
3443
Michal Vaskob36053d2020-03-26 15:49:30 +01003444 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3445 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3446 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3447 /* parse subelements */
3448 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003449 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003450 if (!(*element)->child) {
3451 /* save first */
3452 (*element)->child = new;
3453 } else {
3454 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003455 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003456 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003457
Michal Vaskob36053d2020-03-26 15:49:30 +01003458 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3459 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003460 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003461 } else {
3462 /* save element content */
3463 if (ctx->xmlctx->value_len) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003464 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
Michal Vaskob36053d2020-03-26 15:49:30 +01003465 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3466 }
3467
3468 /* read closing tag */
3469 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003470 }
3471
David Sedlákb0ca07d2019-09-11 11:54:05 +02003472cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003473 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003474}
3475
3476LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003477yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003478{
David Sedlák81497a32019-08-13 16:56:26 +02003479 LY_ERR ret = LY_SUCCESS;
3480 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003481 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003482
Michal Vaskoc3781c32020-10-06 14:04:08 +02003483 mod->is_submod = 0;
3484
Michal Vaskob36053d2020-03-26 15:49:30 +01003485 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3486 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003487 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003488 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3489 LY_STMT_ANYXML, &mod->data, 0,
3490 LY_STMT_AUGMENT, &mod->augments, 0,
3491 LY_STMT_CHOICE, &mod->data, 0,
3492 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3493 LY_STMT_CONTAINER, &mod->data, 0,
3494 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3495 LY_STMT_DEVIATION, &mod->deviations, 0,
3496 LY_STMT_EXTENSION, &mod->extensions, 0,
3497 LY_STMT_FEATURE, &mod->features, 0,
3498 LY_STMT_GROUPING, &mod->groupings, 0,
3499 LY_STMT_IDENTITY, &mod->identities, 0,
3500 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3501 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3502 LY_STMT_LEAF, &mod->data, 0,
3503 LY_STMT_LEAF_LIST, &mod->data, 0,
3504 LY_STMT_LIST, &mod->data, 0,
3505 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3506 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3507 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3508 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3509 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3510 LY_STMT_REVISION, &mod->revs, 0,
3511 LY_STMT_RPC, &mod->rpcs, 0,
3512 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3513 LY_STMT_USES, &mod->data, 0,
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003514 LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
Michal Vasko69730152020-10-09 16:30:07 +02003515 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003516
Michal Vaskob36053d2020-03-26 15:49:30 +01003517 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003518 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003519 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003520
David Sedláked809f12019-09-13 10:15:11 +02003521 /* finalize parent pointers to the reallocated items */
3522 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3523
3524 /* submodules share the namespace with the module names, so there must not be
3525 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003526 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003527 if (dup) {
3528 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3529 return LY_EVALID;
3530 }
3531
3532 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003533}
3534
3535LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003536yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003537{
David Sedlák81497a32019-08-13 16:56:26 +02003538 LY_ERR ret = LY_SUCCESS;
3539 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003540 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003541
Michal Vaskoc3781c32020-10-06 14:04:08 +02003542 submod->is_submod = 1;
3543
Michal Vaskob36053d2020-03-26 15:49:30 +01003544 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3545 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
David Sedlák81497a32019-08-13 16:56:26 +02003546 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003547 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3548 LY_STMT_ANYXML, &submod->data, 0,
3549 LY_STMT_AUGMENT, &submod->augments, 0,
3550 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3551 LY_STMT_CHOICE, &submod->data, 0,
3552 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3553 LY_STMT_CONTAINER, &submod->data, 0,
3554 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3555 LY_STMT_DEVIATION, &submod->deviations, 0,
3556 LY_STMT_EXTENSION, &submod->extensions, 0,
3557 LY_STMT_FEATURE, &submod->features, 0,
3558 LY_STMT_GROUPING, &submod->groupings, 0,
3559 LY_STMT_IDENTITY, &submod->identities, 0,
3560 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3561 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3562 LY_STMT_LEAF, &submod->data, 0,
3563 LY_STMT_LEAF_LIST, &submod->data, 0,
3564 LY_STMT_LIST, &submod->data, 0,
3565 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3566 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3567 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3568 LY_STMT_REVISION, &submod->revs, 0,
3569 LY_STMT_RPC, &submod->rpcs, 0,
3570 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3571 LY_STMT_USES, &submod->data, 0,
3572 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3573 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003574
Michal Vaskob36053d2020-03-26 15:49:30 +01003575 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003576 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003577 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003578
David Sedláked809f12019-09-13 10:15:11 +02003579 /* finalize parent pointers to the reallocated items */
3580 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3581
3582 /* submodules share the namespace with the module names, so there must not be
3583 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003584 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003585 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
David Sedláked809f12019-09-13 10:15:11 +02003586 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3587 return LY_EVALID;
3588 }
3589
3590 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003591}
3592
3593LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003594yin_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 +02003595 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003596{
Radek Krejcid6b76452019-09-03 17:03:03 +02003597 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003598 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003599 struct lysp_submodule *mod_p = NULL;
3600
3601 /* create context */
3602 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003603 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003604 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003605 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003606
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003607 mod_p = calloc(1, sizeof *mod_p);
3608 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3609 mod_p->mod = main_ctx->parsed_mod->mod;
3610 mod_p->parsing = 1;
3611 (*yin_ctx)->parsed_mod = (struct lysp_module *)mod_p;
3612
David Sedlák1b623122019-08-05 15:27:49 +02003613 /* map the typedefs and groupings list from main context to the submodule's context */
3614 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3615 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3616
David Sedlák8985a142019-07-31 16:43:06 +02003617 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003618 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 +02003619 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003620 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003621 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3622 ret = LY_EINVAL;
3623 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003624 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003625 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003626 ret = LY_EVALID;
3627 goto cleanup;
3628 }
3629
Michal Vaskob36053d2020-03-26 15:49:30 +01003630 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003631 LY_CHECK_GOTO(ret, cleanup);
3632
David Sedlákbf8a2b72019-08-14 16:48:10 +02003633 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003634 while (isspace(in->current[0])) {
3635 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003636 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003637 if (in->current[0]) {
3638 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003639 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003640 ret = LY_EVALID;
3641 goto cleanup;
3642 }
3643
David Sedlák8985a142019-07-31 16:43:06 +02003644 mod_p->parsing = 0;
3645 *submod = mod_p;
3646
3647cleanup:
3648 if (ret) {
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003649 lysp_module_free((struct lysp_module *)mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003650 yin_parser_ctx_free(*yin_ctx);
3651 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003652 }
David Sedlák8985a142019-07-31 16:43:06 +02003653 return ret;
3654}
3655
3656LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003657yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003658{
David Sedláke4889912018-11-02 09:52:40 +01003659 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003660 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003661 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003662
David Sedlák8985a142019-07-31 16:43:06 +02003663 /* create context */
3664 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003665 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003666 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003667 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003668
Michal Vasko5d24f6c2020-10-13 13:49:06 +02003669 mod_p = calloc(1, sizeof *mod_p);
3670 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3671 mod_p->mod = mod;
3672 mod_p->parsing = 1;
3673 (*yin_ctx)->parsed_mod = mod_p;
3674
David Sedlák8985a142019-07-31 16:43:06 +02003675 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003676 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 +02003677 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003678 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003679 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 +01003680 ret = LY_EINVAL;
3681 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003682 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003683 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003684 ret = LY_EVALID;
3685 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003686 }
3687
David Sedlák00250342019-06-21 14:19:39 +02003688 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003689 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003690 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003691
David Sedlákbf8a2b72019-08-14 16:48:10 +02003692 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003693 while (isspace(in->current[0])) {
3694 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003695 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003696 if (in->current[0]) {
3697 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003698 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003699 ret = LY_EVALID;
3700 goto cleanup;
3701 }
3702
David Sedlák3017da42019-02-15 09:48:04 +01003703 mod_p->parsing = 0;
3704 mod->parsed = mod_p;
3705
3706cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003707 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003708 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003709 yin_parser_ctx_free(*yin_ctx);
3710 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003711 }
David Sedlák2e411422018-12-17 02:35:39 +01003712 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003713}