blob: 8efa2de49a8fba5ddac6eae516274256e6f26aaf [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));
520 restr->arg.mod = ctx->main_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));
824 restr->arg.mod = ctx->main_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:
902 if (subinfo->flags & YIN_SUBELEM_TEXT) {
903 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
904 return yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest, YIN_ARG_VALUE, Y_STR_ARG, exts);
905 } else {
906 return yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest, YIN_ARG_VALUE, Y_STR_ARG, exts);
907 }
908 } else {
909 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
910 qname = (struct lysp_qname *)subinfo->dest;
911 } else {
912 qnames = (struct lysp_qname **)subinfo->dest;
913 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
914 }
915 qname->mod = ctx->main_mod;
916 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
917 }
918 case LY_STMT_IF_FEATURE:
919 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
920 if (subinfo->flags & YIN_SUBELEM_TEXT) {
921 return yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
922 } else {
923 qnames = (struct lysp_qname **)subinfo->dest;
924 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
925 qname->mod = ctx->main_mod;
926 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
927 }
928 default:
929 break;
930 }
931
932 LOGINT(ctx->xmlctx->ctx);
933 return LY_EINT;
934}
935
936/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200937 * @brief Parse position or value element.
938 *
939 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200940 * @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 +0200941 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200942 *
943 * @return LY_ERR values.
944 */
945static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100946yin_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 +0200947{
Radek Krejcid6b76452019-09-03 17:03:03 +0200948 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200949 const char *temp_val = NULL;
950 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200951 long int num = 0;
952 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +0200953
954 /* set value flag */
955 enm->flags |= LYS_SET_VALUE;
956
957 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100958 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
959 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
Michal Vasko69730152020-10-09 16:30:07 +0200960 if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +0200961 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200962 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 +0200963 goto error;
964 }
965
966 /* convert value */
967 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200968 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200969 num = strtol(temp_val, &ptr, 10);
Michal Vasko69730152020-10-09 16:30:07 +0200970 if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
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ák5545f5d2019-07-11 11:55:16 +0200972 goto error;
973 }
974 } else {
975 unum = strtoul(temp_val, &ptr, 10);
976 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200977 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 +0200978 goto error;
979 }
980 }
981 /* check if whole argument value was converted */
982 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200983 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 +0200984 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200985 }
986 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200987 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 +0200988 goto error;
989 }
990 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200991 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200992 enm->value = num;
993 } else {
994 enm->value = unum;
995 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100996 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200997
998 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200999 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001000 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1001 };
Michal Vasko69730152020-10-09 16:30:07 +02001002
Michal Vaskob36053d2020-03-26 15:49:30 +01001003 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +02001004
David Sedlákbf8a2b72019-08-14 16:48:10 +02001005error:
Michal Vaskob36053d2020-03-26 15:49:30 +01001006 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1007 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001008}
1009
David Sedlák05404f62019-07-24 14:11:53 +02001010/**
1011 * @brief Parse belongs-to element.
1012 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001013 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001014 * @param[out] submod Structure of submodule that is being parsed.
1015 * @param[in,out] exts Extension instances to add to.
1016 *
1017 * @return LY_ERR values
1018 */
1019static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001020yin_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 +02001021{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001022 const char *belongsto;
David Sedlák05404f62019-07-24 14:11:53 +02001023 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001024 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1025 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1026 };
David Sedlák05404f62019-07-24 14:11:53 +02001027
Michal Vaskob36053d2020-03-26 15:49:30 +01001028 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001029 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
1030 if (ctx->main_mod->name != belongsto) {
1031 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
1032 belongsto, ctx->main_mod->name);
1033 lydict_remove(ctx->xmlctx->ctx, belongsto);
1034 return LY_EVALID;
1035 }
1036 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001037
1038 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001039}
1040
David Sedlák5545f5d2019-07-11 11:55:16 +02001041/**
David Sedlákc1771b12019-07-10 15:55:46 +02001042 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001043 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001044 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001045 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001046 * @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 +02001047 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001048 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001049 *
1050 * @return LY_ERR values.
1051 */
1052static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001053yin_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 +02001054{
Radek Krejcid6b76452019-09-03 17:03:03 +02001055 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 +02001056
David Sedlák968ac342019-07-11 15:17:59 +02001057 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001058 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1059 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1060 };
Michal Vasko69730152020-10-09 16:30:07 +02001061
David Sedlákdf2a9732019-08-07 13:23:16 +02001062 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001063 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1064 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 +02001065
David Sedlákdf2a9732019-08-07 13:23:16 +02001066 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +01001067 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001068}
1069
1070/**
David Sedlákc1771b12019-07-10 15:55:46 +02001071 * @brief Parse error-message element.
1072 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001073 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001074 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001075 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001076 *
1077 * @return LY_ERR values.
1078 */
1079static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001080yin_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 +02001081{
David Sedlák968ac342019-07-11 15:17:59 +02001082 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001083 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1084 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1085 };
David Sedlákc1771b12019-07-10 15:55:46 +02001086
David Sedlákdf2a9732019-08-07 13:23:16 +02001087 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001088 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1089 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 +02001090
Michal Vaskob36053d2020-03-26 15:49:30 +01001091 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001092}
1093
1094/**
David Sedlák6542aed2019-08-14 10:47:43 +02001095 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001096 *
1097 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001098 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001099 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001100 *
1101 * @return LY_ERR values.
1102 */
1103static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001104yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001105{
David Sedlák6542aed2019-08-14 10:47:43 +02001106 struct lysp_type *type = NULL;
Michal Vasko69730152020-10-09 16:30:07 +02001107
Radek Krejcid6b76452019-09-03 17:03:03 +02001108 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001109 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001110 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001111 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001112 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001113 type = (struct lysp_type *)subinfo->dest;
1114 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001115
1116 type->mod = ctx->main_mod;
1117
David Sedlák6542aed2019-08-14 10:47:43 +02001118 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001119 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001120 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001121 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001122 type->flags |= LYS_SET_TYPE;
1123 type = nested_type;
1124 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001125
David Sedlák374d2b32019-07-17 15:06:55 +02001126 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001127 {LY_STMT_BASE, type, 0},
1128 {LY_STMT_BIT, type, 0},
1129 {LY_STMT_ENUM, type, 0},
1130 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1131 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1132 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1133 {LY_STMT_PATTERN, type, 0},
1134 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1135 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1136 {LY_STMT_TYPE, type},
1137 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1138 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001139
1140 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1141 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1142 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001143}
1144
David Sedlák1af868e2019-07-17 17:03:14 +02001145/**
1146 * @brief Parse max-elements element.
1147 *
1148 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001149 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001150 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001151 * @param[in,out] exts Extension instances to add to.
1152 *
1153 * @return LY_ERR values.
1154 */
1155static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001156yin_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 +02001157{
1158 const char *temp_val = NULL;
1159 char *ptr;
1160 unsigned long int num;
1161 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001162 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1163 };
David Sedlák374d2b32019-07-17 15:06:55 +02001164
David Sedlák1af868e2019-07-17 17:03:14 +02001165 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001166 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1167 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 +02001168 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 +02001169 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001170 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001171 return LY_EVALID;
1172 }
1173
1174 if (strcmp(temp_val, "unbounded")) {
1175 errno = 0;
1176 num = strtoul(temp_val, &ptr, 10);
1177 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001178 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001179 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001180 return LY_EVALID;
1181 }
1182 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001183 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001184 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001185 return LY_EVALID;
1186 }
1187 *max = num;
1188 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001189 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1190 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001191}
David Sedlák374d2b32019-07-17 15:06:55 +02001192
1193/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001194 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001195 *
1196 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001197 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001198 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001199 * @param[in,out] exts Extension instances to add to.
1200 *
1201 * @return LY_ERR values.
1202 */
1203static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001204yin_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 +02001205{
1206 const char *temp_val = NULL;
1207 char *ptr;
1208 unsigned long int num;
1209 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001210 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1211 };
David Sedlák09e18c92019-07-18 11:17:11 +02001212
1213 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001214 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1215 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 +02001216
Michal Vasko69730152020-10-09 16:30:07 +02001217 if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
David Sedlák1538a842019-08-08 15:38:51 +02001218 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001219 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001220 return LY_EVALID;
1221 }
1222
1223 errno = 0;
1224 num = strtoul(temp_val, &ptr, 10);
1225 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001226 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001227 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001228 return LY_EVALID;
1229 }
Michal Vasko69730152020-10-09 16:30:07 +02001230 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001231 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001232 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001233 return LY_EVALID;
1234 }
1235 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001236 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1237 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001238}
1239
David Sedláka2dad212019-07-18 12:45:19 +02001240/**
1241 * @brief Parse min-elements or max-elements element.
1242 *
1243 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001244 * @param[in] parent Identification of parent element.
1245 * @param[in] current Identification of current element.
1246 * @param[in] dest Where the parsed value and flags should be stored.
1247 *
1248 * @return LY_ERR values.
1249 */
David Sedlák09e18c92019-07-18 11:17:11 +02001250static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001251yin_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 +02001252{
Radek Krejcid6b76452019-09-03 17:03:03 +02001253 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1254 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 +02001255 uint32_t *lim;
1256 uint16_t *flags;
1257 struct lysp_ext_instance **exts;
1258
Radek Krejcid6b76452019-09-03 17:03:03 +02001259 if (parent == LY_STMT_LEAF_LIST) {
1260 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 +02001261 flags = &((struct lysp_node_leaflist *)dest)->flags;
1262 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001263 } else if (parent == LY_STMT_REFINE) {
1264 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001265 flags = &((struct lysp_refine *)dest)->flags;
1266 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001267 } else if (parent == LY_STMT_LIST) {
1268 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 +02001269 flags = &((struct lysp_node_list *)dest)->flags;
1270 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001271 } else {
1272 lim = ((struct minmax_dev_meta *)dest)->lim;
1273 flags = ((struct minmax_dev_meta *)dest)->flags;
1274 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001275 }
1276
Radek Krejcid6b76452019-09-03 17:03:03 +02001277 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001278 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001279 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001280 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001281 }
1282
1283 return LY_SUCCESS;
1284}
1285
1286/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001287 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001288 *
1289 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001290 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001291 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001292 *
1293 * @return LY_ERR values.
1294 */
1295static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001296yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001297{
1298 const char *temp_val;
1299 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001300 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1301 };
David Sedláka2dad212019-07-18 12:45:19 +02001302
Michal Vaskob36053d2020-03-26 15:49:30 +01001303 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1304 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 +02001305 if (strcmp(temp_val, "system") == 0) {
1306 *flags |= LYS_ORDBY_SYSTEM;
1307 } else if (strcmp(temp_val, "user") == 0) {
1308 *flags |= LYS_ORDBY_USER;
1309 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001310 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001311 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001312 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001313 return LY_EVALID;
1314 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001315 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001316
Michal Vaskob36053d2020-03-26 15:49:30 +01001317 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001318}
1319
1320/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001321 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001322 *
1323 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001324 * @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 +02001325 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001326 *
1327 * @return LY_ERR values.
1328 */
1329static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001330yin_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 +02001331{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001332 struct lysp_node_anydata *any;
1333
David Sedlák8d552d62019-08-06 15:29:05 +02001334 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001335 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001336 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001337 any->parent = node_meta->parent;
1338
David Sedlákbf8a2b72019-08-14 16:48:10 +02001339 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001340 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1341 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 +02001342
1343 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001344 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1345 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1346 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1347 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1348 {LY_STMT_MUST, &any->musts, 0},
1349 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1350 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1351 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1352 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1353 };
Michal Vasko69730152020-10-09 16:30:07 +02001354
Michal Vaskob36053d2020-03-26 15:49:30 +01001355 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001356}
1357
1358/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001359 * @brief parse leaf element.
1360 *
1361 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001362 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001363 *
1364 * @return LY_ERR values.
1365 */
1366static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001367yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001368{
David Sedlák203ca3a2019-07-18 15:26:25 +02001369 struct lysp_node_leaf *leaf;
1370
David Sedlák8d552d62019-08-06 15:29:05 +02001371 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001372 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001373 leaf->nodetype = LYS_LEAF;
1374 leaf->parent = node_meta->parent;
1375
David Sedlák203ca3a2019-07-18 15:26:25 +02001376 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001377 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1378 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 +02001379
1380 /* parse content */
1381 struct yin_subelement subelems[12] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001382 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1383 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1384 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1385 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1386 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1387 {LY_STMT_MUST, &leaf->musts, 0},
1388 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1389 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1390 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1391 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1392 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1393 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1394 };
Michal Vasko69730152020-10-09 16:30:07 +02001395
Michal Vaskob36053d2020-03-26 15:49:30 +01001396 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001397}
1398
1399/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001400 * @brief Parse leaf-list element.
1401 *
1402 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001403 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001404 *
1405 * @return LY_ERR values.
1406 */
1407static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001408yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001409{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001410 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001411
Michal Vaskob36053d2020-03-26 15:49:30 +01001412 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001413
David Sedlákc3da3ef2019-07-19 12:56:08 +02001414 llist->nodetype = LYS_LEAFLIST;
1415 llist->parent = node_meta->parent;
1416
David Sedlákc3da3ef2019-07-19 12:56:08 +02001417 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001418 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1419 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 +02001420
1421 /* parse content */
1422 struct yin_subelement subelems[14] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001423 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_DEFAULT, &llist->dflts, 0},
1425 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1426 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1427 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1428 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1429 {LY_STMT_MUST, &llist->musts, 0},
1430 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1431 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1432 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1433 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1434 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1435 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1436 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1437 };
Michal Vasko69730152020-10-09 16:30:07 +02001438
Michal Vaskob36053d2020-03-26 15:49:30 +01001439 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001440
David Sedlákbf8a2b72019-08-14 16:48:10 +02001441 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001442 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001443 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001444 return LY_EVALID;
1445 }
Michal Vasko69730152020-10-09 16:30:07 +02001446 if (llist->max && (llist->min > llist->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02001447 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001448 return LY_EVALID;
1449 }
1450
1451 return LY_SUCCESS;
1452}
1453
1454/**
David Sedlák04e17b22019-07-19 15:29:48 +02001455 * @brief Parse typedef element.
1456 *
1457 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001458 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001459 *
1460 * @return LY_ERR values.
1461 */
1462static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001463yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001464{
1465 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001466 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vasko69730152020-10-09 16:30:07 +02001467
Michal Vaskob36053d2020-03-26 15:49:30 +01001468 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001469
1470 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001471 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1472 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 +02001473
1474 /* parse content */
1475 struct yin_subelement subelems[7] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001476 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1477 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1478 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1479 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1480 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1481 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1482 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1483 };
Michal Vasko69730152020-10-09 16:30:07 +02001484
Michal Vaskob36053d2020-03-26 15:49:30 +01001485 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001486
1487 /* store data for collision check */
Michal Vasko69730152020-10-09 16:30:07 +02001488 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT |
1489 LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001490 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001491 }
1492
1493 return LY_SUCCESS;
1494}
1495
1496/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001497 * @brief Parse refine element.
1498 *
1499 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001500 * @param[in,out] refines Refines to add to.
1501 *
1502 * @return LY_ERR values.
1503 */
1504static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001505yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001506{
1507 struct lysp_refine *rf;
1508
1509 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001510 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001511
1512 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001513 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1514 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1515 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001516
1517 /* parse content */
1518 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001519 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02001520 {LY_STMT_DEFAULT, &rf->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02001521 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02001522 {LY_STMT_IF_FEATURE, &rf->iffeatures, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02001523 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1524 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1525 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1526 {LY_STMT_MUST, &rf->musts, 0},
1527 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1528 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1529 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1530 };
Michal Vasko69730152020-10-09 16:30:07 +02001531
Michal Vaskob36053d2020-03-26 15:49:30 +01001532 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001533}
1534
1535/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001536 * @brief Parse uses element.
1537 *
1538 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001539 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001540 *
1541 * @return LY_ERR values.
1542 */
1543static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001544yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001545{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001546 struct lysp_node_uses *uses;
1547
David Sedlák8d552d62019-08-06 15:29:05 +02001548 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001549 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001550 uses->nodetype = LYS_USES;
1551 uses->parent = node_meta->parent;
1552
David Sedlák0d6de5a2019-07-22 13:25:44 +02001553 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001554 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1555 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 +02001556
1557 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001558 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001559 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001560 {LY_STMT_AUGMENT, &augments, 0},
1561 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1562 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1563 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1564 {LY_STMT_REFINE, &uses->refines, 0},
1565 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1566 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1567 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1568 };
Michal Vasko69730152020-10-09 16:30:07 +02001569
Michal Vaskob36053d2020-03-26 15:49:30 +01001570 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001571 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1572
1573 return LY_SUCCESS;
1574}
1575
1576/**
David Sedlákaa854b02019-07-22 14:17:10 +02001577 * @brief Parse revision element.
1578 *
1579 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001580 * @param[in,out] revs Parsed revisions to add to.
1581 *
1582 * @return LY_ERR values.
1583 */
1584static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001585yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001586{
1587 struct lysp_revision *rev;
1588 const char *temp_date = NULL;
1589
1590 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001591 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001592
1593 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001594 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1595 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 +02001596 /* check value */
1597 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001598 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001599 return LY_EVALID;
1600 }
1601 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001602 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001603
1604 /* parse content */
1605 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001606 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1607 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1608 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1609 };
Michal Vasko69730152020-10-09 16:30:07 +02001610
Michal Vaskob36053d2020-03-26 15:49:30 +01001611 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001612}
1613
David Sedlák5e13dea2019-07-22 16:06:45 +02001614/**
1615 * @brief Parse include element.
1616 *
1617 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001618 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1619 *
1620 * @return LY_ERR values.
1621 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001622static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001623yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001624{
1625 struct lysp_include *inc;
1626
1627 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001628 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001629
1630 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001631 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1632 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, LY_STMT_INCLUDE));
David Sedlák0c2bab92019-07-22 15:33:19 +02001633
1634 /* submodules share the namespace with the module names, so there must not be
1635 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001636 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 +02001637 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001638 return LY_EVALID;
1639 }
1640
1641 /* parse content */
1642 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001643 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1644 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1645 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1646 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1647 };
Michal Vasko69730152020-10-09 16:30:07 +02001648
Michal Vaskob36053d2020-03-26 15:49:30 +01001649 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001650}
1651
David Sedlákaa854b02019-07-22 14:17:10 +02001652/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001653 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001654 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001655 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001656 * @param[in,out] rev Array to store the parsed value in.
1657 * @param[in,out] exts Extension instances to add to.
1658 *
1659 * @return LY_ERR values.
1660 */
1661static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001662yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001663{
1664 const char *temp_rev;
1665 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001666 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1667 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001668
Michal Vaskob36053d2020-03-26 15:49:30 +01001669 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1670 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 +02001671 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 +02001672 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001673
1674 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001675 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001676
Michal Vaskob36053d2020-03-26 15:49:30 +01001677 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001678}
1679
1680/**
1681 * @brief Parse config element.
1682 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001683 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001684 * @param[in,out] flags Flags to add to.
1685 * @param[in,out] exts Extension instances to add to.
1686 *
1687 * @return LY_ERR values.
1688 */
1689static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001690yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001691{
1692 const char *temp_val = NULL;
1693 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001694 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1695 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001696
Michal Vaskob36053d2020-03-26 15:49:30 +01001697 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1698 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 +02001699 if (strcmp(temp_val, "true") == 0) {
1700 *flags |= LYS_CONFIG_W;
1701 } else if (strcmp(temp_val, "false") == 0) {
1702 *flags |= LYS_CONFIG_R;
1703 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001704 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
Michal Vasko69730152020-10-09 16:30:07 +02001705 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001706 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001707 return LY_EVALID;
1708 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001709 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001710
Michal Vaskob36053d2020-03-26 15:49:30 +01001711 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001712}
1713
1714/**
1715 * @brief Parse yang-version element.
1716 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001717 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001718 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001719 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001720 *
1721 * @return LY_ERR values.
1722 */
1723static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001724yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001725{
1726 const char *temp_version = NULL;
1727 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001728 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1729 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001730
Michal Vaskob36053d2020-03-26 15:49:30 +01001731 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1732 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 +02001733 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001734 *version = LYS_VERSION_1_0;
1735 } else if (strcmp(temp_version, "1.1") == 0) {
1736 *version = LYS_VERSION_1_1;
1737 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001738 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001739 "yang-version", "1", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001740 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001741 return LY_EVALID;
1742 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001743 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001744 ctx->mod_version = *version;
1745
Michal Vaskob36053d2020-03-26 15:49:30 +01001746 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001747}
1748
1749/**
1750 * @brief Parse import element.
1751 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001752 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001753 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1754 *
1755 * @return LY_ERR values.
1756 */
1757static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001758yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001759{
1760 struct lysp_import *imp;
Michal Vasko69730152020-10-09 16:30:07 +02001761
David Sedlákdfbbb442019-08-06 16:33:21 +02001762 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001763 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001764
1765 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001766 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1767 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1768 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1769 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1770 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1771 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001772
1773 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001774 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1775 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1776 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001777 /* check prefix validity */
1778 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1779
1780 return LY_SUCCESS;
1781}
1782
1783/**
1784 * @brief Parse mandatory element.
1785 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001786 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001787 * @param[in,out] flags Flags to add to.
1788 * @param[in,out] exts Extension instances to add to.
1789 *
1790 * @return LY_ERR values.
1791 */
1792static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001793yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001794{
1795 const char *temp_val = NULL;
1796 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001797 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1798 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001799
Michal Vaskob36053d2020-03-26 15:49:30 +01001800 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1801 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 +02001802 if (strcmp(temp_val, "true") == 0) {
1803 *flags |= LYS_MAND_TRUE;
1804 } else if (strcmp(temp_val, "false") == 0) {
1805 *flags |= LYS_MAND_FALSE;
1806 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001807 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001808 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001809 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001810 return LY_EVALID;
1811 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001812 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001813
Michal Vaskob36053d2020-03-26 15:49:30 +01001814 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001815}
1816
1817/**
1818 * @brief Parse status element.
1819 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001820 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001821 * @param[in,out] flags Flags to add to.
1822 * @param[in,out] exts Extension instances to add to.
1823 *
1824 * @return LY_ERR values.
1825 */
1826static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001827yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001828{
1829 const char *value = NULL;
1830 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001831 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1832 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001833
Michal Vaskob36053d2020-03-26 15:49:30 +01001834 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1835 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 +02001836 if (strcmp(value, "current") == 0) {
1837 *flags |= LYS_STATUS_CURR;
1838 } else if (strcmp(value, "deprecated") == 0) {
1839 *flags |= LYS_STATUS_DEPRC;
1840 } else if (strcmp(value, "obsolete") == 0) {
1841 *flags |= LYS_STATUS_OBSLT;
1842 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001843 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001844 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001845 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001846 return LY_EVALID;
1847 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001848 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001849
Michal Vaskob36053d2020-03-26 15:49:30 +01001850 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001851}
1852
1853/**
1854 * @brief Parse when element.
1855 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001856 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001857 * @param[out] when_p When pointer to parse to.
1858 */
1859static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001860yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001861{
1862 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001863 LY_ERR ret = LY_SUCCESS;
1864
David Sedlákdfbbb442019-08-06 16:33:21 +02001865 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001866 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001867
1868 ret = lyxml_ctx_next(ctx->xmlctx);
1869 LY_CHECK_ERR_RET(ret, free(when), ret);
1870
Michal Vaskob36053d2020-03-26 15:49:30 +01001871 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001872 LY_CHECK_ERR_RET(ret, free(when), ret);
1873
David Sedlákdfbbb442019-08-06 16:33:21 +02001874 *when_p = when;
1875 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001876 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1877 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1878 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1879 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001880
Michal Vaskob36053d2020-03-26 15:49:30 +01001881 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001882}
1883
1884/**
1885 * @brief Parse yin-elemenet element.
1886 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001887 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001888 * @param[in,out] data Data to read from, always moved to currently handled position.
1889 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001890 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001891 *
1892 * @return LY_ERR values.
1893 */
1894static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001895yin_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 +02001896{
1897 const char *temp_val = NULL;
1898 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001899 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1900 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001901
Michal Vaskob36053d2020-03-26 15:49:30 +01001902 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1903 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 +02001904 if (strcmp(temp_val, "true") == 0) {
1905 *flags |= LYS_YINELEM_TRUE;
1906 } else if (strcmp(temp_val, "false") == 0) {
1907 *flags |= LYS_YINELEM_FALSE;
1908 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001909 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
Michal Vasko69730152020-10-09 16:30:07 +02001910 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001911 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001912 return LY_EVALID;
1913 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001914 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001915
Michal Vaskob36053d2020-03-26 15:49:30 +01001916 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001917}
1918
1919/**
1920 * @brief Parse argument element.
1921 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001922 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001923 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1924 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001925 *
1926 * @return LY_ERR values.
1927 */
1928static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001929yin_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 +02001930{
1931 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001932 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1933 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1934 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001935
Michal Vaskob36053d2020-03-26 15:49:30 +01001936 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1937 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 +02001938
Michal Vaskob36053d2020-03-26 15:49:30 +01001939 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001940}
1941
1942/**
1943 * @brief Parse the extension statement.
1944 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001945 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001946 * @param[in,out] extensions Extensions to add to.
1947 *
1948 * @return LY_ERR values.
1949 */
1950static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001951yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001952{
1953 struct lysp_ext *ex;
Michal Vasko69730152020-10-09 16:30:07 +02001954
Michal Vaskob36053d2020-03-26 15:49:30 +01001955 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1956 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1957 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 +02001958
1959 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1960 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001961 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1962 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1963 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1964 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1965 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1966 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001967
Michal Vaskob36053d2020-03-26 15:49:30 +01001968 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001969}
1970
1971/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001972 * @brief Parse feature element.
1973 *
1974 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001975 * @param[in,out] features Features to add to.
1976 *
1977 * @return LY_ERR values.
1978 */
1979static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001980yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001981{
1982 struct lysp_feature *feat;
1983
1984 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001985 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001986
1987 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001988 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1989 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 +02001990
1991 /* parse content */
1992 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001993 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1994 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1995 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1996 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1997 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1998 };
Michal Vasko69730152020-10-09 16:30:07 +02001999
Michal Vaskob36053d2020-03-26 15:49:30 +01002000 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02002001}
2002
2003/**
David Sedlák28794f22019-07-22 16:45:00 +02002004 * @brief Parse identity element.
2005 *
2006 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02002007 * @param[in,out] identities Identities to add to.
2008 *
2009 * @return LY_ERR values.
2010 */
2011static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002012yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02002013{
2014 struct lysp_ident *ident;
2015
2016 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01002017 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02002018
2019 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002020 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2021 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 +02002022
2023 /* parse content */
2024 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002025 {LY_STMT_BASE, &ident->bases, 0},
2026 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2027 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2028 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2029 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2030 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2031 };
Michal Vasko69730152020-10-09 16:30:07 +02002032
Michal Vaskob36053d2020-03-26 15:49:30 +01002033 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002034}
2035
2036/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002037 * @brief Parse list element.
2038 *
2039 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002040 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002041 *
2042 * @return LY_ERR values.
2043 */
2044static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002045yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002046{
David Sedlákaf536aa2019-07-23 13:42:23 +02002047 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002048 LY_ERR ret = LY_SUCCESS;
2049 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002050
Michal Vaskob36053d2020-03-26 15:49:30 +01002051 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002052 list->nodetype = LYS_LIST;
2053 list->parent = node_meta->parent;
2054
David Sedlákaf536aa2019-07-23 13:42:23 +02002055 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002056 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2057 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 +02002058
2059 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002060 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002061 LY_STMT_ACTION, &list->actions, 0,
2062 LY_STMT_ANYDATA, &list->child, 0,
2063 LY_STMT_ANYXML, &list->child, 0,
2064 LY_STMT_CHOICE, &list->child, 0,
2065 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2066 LY_STMT_CONTAINER, &list->child, 0,
2067 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2068 LY_STMT_GROUPING, &list->groupings, 0,
2069 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2070 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2071 LY_STMT_LEAF, &list->child, 0,
2072 LY_STMT_LEAF_LIST, &list->child, 0,
2073 LY_STMT_LIST, &list->child, 0,
2074 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2075 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2076 LY_STMT_MUST, &list->musts, 0,
2077 LY_STMT_NOTIFICATION, &list->notifs, 0,
2078 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2079 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2080 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2081 LY_STMT_TYPEDEF, &list->typedefs, 0,
2082 LY_STMT_UNIQUE, &list->uniques, 0,
2083 LY_STMT_USES, &list->child, 0,
2084 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2085 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002086 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002087 subelems_deallocator(25, subelems);
2088 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002089
2090 /* finalize parent pointers to the reallocated items */
2091 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2092
Michal Vasko69730152020-10-09 16:30:07 +02002093 if (list->max && (list->min > list->max)) {
David Sedlák1538a842019-08-08 15:38:51 +02002094 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002095 return LY_EVALID;
2096 }
2097
2098 return LY_SUCCESS;
2099}
2100
2101/**
David Sedlák031b9e72019-07-23 15:19:37 +02002102 * @brief Parse notification element.
2103 *
2104 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002105 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002106 *
2107 * @return LY_ERR values.
2108 */
2109static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002110yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002111{
2112 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002113 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002114 LY_ERR ret = LY_SUCCESS;
2115 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002116
2117 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002118 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002119 notif->nodetype = LYS_NOTIF;
2120 notif->parent = notif_meta->parent;
2121
2122 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002123 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2124 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 +02002125
2126 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002127 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002128 LY_STMT_ANYDATA, &notif->data, 0,
2129 LY_STMT_ANYXML, &notif->data, 0,
2130 LY_STMT_CHOICE, &notif->data, 0,
2131 LY_STMT_CONTAINER, &notif->data, 0,
2132 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2133 LY_STMT_GROUPING, &notif->groupings, 0,
2134 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2135 LY_STMT_LEAF, &notif->data, 0,
2136 LY_STMT_LEAF_LIST, &notif->data, 0,
2137 LY_STMT_LIST, &notif->data, 0,
2138 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2139 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2140 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2141 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2142 LY_STMT_USES, &notif->data, 0,
2143 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02002144
Michal Vaskob36053d2020-03-26 15:49:30 +01002145 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002146 subelems_deallocator(16, subelems);
2147 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002148
2149 /* finalize parent pointers to the reallocated items */
2150 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2151
2152 return LY_SUCCESS;
2153}
2154
2155/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002156 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002157 *
2158 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002159 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002160 *
2161 * @return LY_ERR values.
2162 */
2163static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002164yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002165{
2166 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002167 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002168 LY_ERR ret = LY_SUCCESS;
2169 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002170
2171 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002172 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002173 grp->nodetype = LYS_GROUPING;
2174 grp->parent = gr_meta->parent;
2175
2176 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002177 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2178 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 +02002179
2180 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002181 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002182 LY_STMT_ACTION, &grp->actions, 0,
2183 LY_STMT_ANYDATA, &grp->data, 0,
2184 LY_STMT_ANYXML, &grp->data, 0,
2185 LY_STMT_CHOICE, &grp->data, 0,
2186 LY_STMT_CONTAINER, &grp->data, 0,
2187 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2188 LY_STMT_GROUPING, &grp->groupings, 0,
2189 LY_STMT_LEAF, &grp->data, 0,
2190 LY_STMT_LEAF_LIST, &grp->data, 0,
2191 LY_STMT_LIST, &grp->data, 0,
2192 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2193 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2194 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2195 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2196 LY_STMT_USES, &grp->data, 0,
2197 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002198 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002199 subelems_deallocator(16, subelems);
2200 LY_CHECK_RET(ret);
2201
David Sedláke3ce9ef2019-07-23 16:34:30 +02002202 /* finalize parent pointers to the reallocated items */
2203 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2204
2205 return LY_SUCCESS;
2206}
2207
2208/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002209 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002210 *
2211 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002212 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002213 *
2214 * @return LY_ERR values.
2215 */
2216static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002217yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002218{
David Sedlákf111bcb2019-07-23 17:15:51 +02002219 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002220 LY_ERR ret = LY_SUCCESS;
2221 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002222
2223 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002224 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002225 cont->nodetype = LYS_CONTAINER;
2226 cont->parent = node_meta->parent;
2227
David Sedlákf111bcb2019-07-23 17:15:51 +02002228 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002229 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2230 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 +02002231
2232 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002233 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002234 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2235 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2236 LY_STMT_ANYXML, &cont->child, 0,
2237 LY_STMT_CHOICE, &cont->child, 0,
2238 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2239 LY_STMT_CONTAINER, &cont->child, 0,
2240 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2241 LY_STMT_GROUPING, &cont->groupings, 0,
2242 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2243 LY_STMT_LEAF, &cont->child, 0,
2244 LY_STMT_LEAF_LIST, &cont->child, 0,
2245 LY_STMT_LIST, &cont->child, 0,
2246 LY_STMT_MUST, &cont->musts, 0,
2247 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2248 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2249 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2250 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2251 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2252 LY_STMT_USES, &cont->child, 0,
2253 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2254 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002255 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002256 subelems_deallocator(21, subelems);
2257 LY_CHECK_RET(ret);
2258
David Sedlákf111bcb2019-07-23 17:15:51 +02002259 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2260
2261 return LY_SUCCESS;
2262}
2263
2264/**
David Sedlák5379d392019-07-24 10:42:03 +02002265 * @brief Parse case element.
2266 *
2267 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002268 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002269 *
2270 * @return LY_ERR values.
2271 */
2272static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002273yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002274{
David Sedlák5379d392019-07-24 10:42:03 +02002275 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002276 LY_ERR ret = LY_SUCCESS;
Michal Vasko69730152020-10-09 16:30:07 +02002277 struct yin_subelement *subelems = NULL;
David Sedlák5379d392019-07-24 10:42:03 +02002278
2279 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002280 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002281 cas->nodetype = LYS_CASE;
2282 cas->parent = node_meta->parent;
2283
David Sedlák5379d392019-07-24 10:42:03 +02002284 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002285 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2286 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, LY_STMT_CASE));
David Sedlák5379d392019-07-24 10:42:03 +02002287
2288 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002289 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002290 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2291 LY_STMT_ANYXML, &cas->child, 0,
2292 LY_STMT_CHOICE, &cas->child, 0,
2293 LY_STMT_CONTAINER, &cas->child, 0,
2294 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2295 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2296 LY_STMT_LEAF, &cas->child, 0,
2297 LY_STMT_LEAF_LIST, &cas->child, 0,
2298 LY_STMT_LIST, &cas->child, 0,
2299 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2300 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2301 LY_STMT_USES, &cas->child, 0,
2302 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2303 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002304 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002305 subelems_deallocator(14, subelems);
2306
2307 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002308}
2309
2310/**
David Sedlák05404f62019-07-24 14:11:53 +02002311 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002312 *
2313 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002314 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002315 *
2316 * @return LY_ERR values.
2317 */
2318LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002319yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002320{
David Sedlák81497a32019-08-13 16:56:26 +02002321 LY_ERR ret = LY_SUCCESS;
2322 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002323 struct lysp_node_choice *choice;
2324
2325 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002326 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002327
David Sedlákb7abcfa2019-07-24 12:33:35 +02002328 choice->nodetype = LYS_CHOICE;
2329 choice->parent = node_meta->parent;
2330
David Sedlákb7abcfa2019-07-24 12:33:35 +02002331 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002332 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2333 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 +02002334
2335 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002336 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002337 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2338 LY_STMT_ANYXML, &choice->child, 0,
2339 LY_STMT_CASE, &choice->child, 0,
2340 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2341 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2342 LY_STMT_CONTAINER, &choice->child, 0,
2343 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2344 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2345 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2346 LY_STMT_LEAF, &choice->child, 0,
2347 LY_STMT_LEAF_LIST, &choice->child, 0,
2348 LY_STMT_LIST, &choice->child, 0,
2349 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2350 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2351 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2352 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2353 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002354 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002355 subelems_deallocator(17, subelems);
2356 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002357}
2358
2359/**
David Sedlák05404f62019-07-24 14:11:53 +02002360 * @brief Parse input or output element.
2361 *
2362 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002363 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002364 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2365 *
2366 * @return LY_ERR values.
2367 */
2368static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002369yin_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 +02002370{
David Sedlák81497a32019-08-13 16:56:26 +02002371 LY_ERR ret = LY_SUCCESS;
2372 struct yin_subelement *subelems = NULL;
2373
David Sedlák05404f62019-07-24 14:11:53 +02002374 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002375 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002376 inout_meta->inout_p->parent = inout_meta->parent;
2377
2378 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002379 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2380 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 +02002381
2382 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002383 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002384 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2385 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2386 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2387 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2388 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2389 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2390 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2391 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2392 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2393 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2394 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2395 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002396 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002397 subelems_deallocator(12, subelems);
2398 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002399
Michal Vaskob83af8a2020-01-06 09:49:22 +01002400 if (!inout_meta->inout_p->data) {
2401 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2402 return LY_EVALID;
2403 }
2404
David Sedlák05404f62019-07-24 14:11:53 +02002405 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002406 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 +02002407
2408 return LY_SUCCESS;
2409}
2410
David Sedlák992fb7c2019-07-24 16:51:01 +02002411/**
2412 * @brief Parse action element.
2413 *
2414 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002415 * @param[in] act_meta Meta information about parent node and actions to add to.
2416 *
2417 * @return LY_ERR values.
2418 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002419static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002420yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002421{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002422 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002423 LY_ERR ret = LY_SUCCESS;
2424 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002425
2426 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002427 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002428 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002429 act->parent = act_meta->parent;
2430
2431 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002432 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2433 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 +02002434
2435 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002436 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002437 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2438 LY_STMT_GROUPING, &act->groupings, 0,
2439 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2440 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2441 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2442 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2443 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2444 LY_STMT_TYPEDEF, &act->typedefs, 0,
2445 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002446 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002447 subelems_deallocator(9, subelems);
2448 LY_CHECK_RET(ret);
2449
Michal Vasko7f45cf22020-10-01 12:49:44 +02002450 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2451 if (!act->input.nodetype) {
2452 act->input.nodetype = LYS_INPUT;
2453 act->input.parent = (struct lysp_node *)act;
2454 }
2455 if (!act->output.nodetype) {
2456 act->output.nodetype = LYS_OUTPUT;
2457 act->output.parent = (struct lysp_node *)act;
2458 }
2459
David Sedlák85d0eca2019-07-24 15:15:21 +02002460 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2461
2462 return LY_SUCCESS;
2463}
2464
David Sedlák05404f62019-07-24 14:11:53 +02002465/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002466 * @brief Parse augment element.
2467 *
2468 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002469 * @param[in] aug_meta Meta information about parent node and augments to add to.
2470 *
2471 * @return LY_ERR values.
2472 */
2473static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002474yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002475{
2476 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002477 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002478 LY_ERR ret = LY_SUCCESS;
2479 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002480
2481 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002482 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002483 aug->nodetype = LYS_AUGMENT;
2484 aug->parent = aug_meta->parent;
2485
2486 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002487 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2488 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2489 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002490
2491 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002492 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02002493 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2494 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2495 LY_STMT_ANYXML, &aug->child, 0,
2496 LY_STMT_CASE, &aug->child, 0,
2497 LY_STMT_CHOICE, &aug->child, 0,
2498 LY_STMT_CONTAINER, &aug->child, 0,
2499 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2500 LY_STMT_IF_FEATURE, &aug->iffeatures, YIN_SUBELEM_TEXT,
2501 LY_STMT_LEAF, &aug->child, 0,
2502 LY_STMT_LEAF_LIST, &aug->child, 0,
2503 LY_STMT_LIST, &aug->child, 0,
2504 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2505 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2506 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2507 LY_STMT_USES, &aug->child, 0,
2508 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2509 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
Michal Vaskob36053d2020-03-26 15:49:30 +01002510 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002511 subelems_deallocator(17, subelems);
2512 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002513
2514 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2515
2516 return LY_SUCCESS;
2517}
2518
David Sedlák8b754462019-07-25 16:22:13 +02002519/**
2520 * @brief Parse deviate element.
2521 *
2522 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002523 * @param[in] deviates Deviates to add to.
2524 *
2525 * @return LY_ERR values.
2526 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002527static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002528yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002529{
2530 LY_ERR ret = LY_SUCCESS;
2531 uint8_t dev_mod;
2532 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002533 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002534 struct lysp_deviate_add *d_add = NULL;
2535 struct lysp_deviate_rpl *d_rpl = NULL;
2536 struct lysp_deviate_del *d_del = NULL;
2537
2538 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002539 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2540 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 +02002541
2542 if (strcmp(temp_val, "not-supported") == 0) {
2543 dev_mod = LYS_DEV_NOT_SUPPORTED;
2544 } else if (strcmp(temp_val, "add") == 0) {
2545 dev_mod = LYS_DEV_ADD;
2546 } else if (strcmp(temp_val, "replace") == 0) {
2547 dev_mod = LYS_DEV_REPLACE;
2548 } else if (strcmp(temp_val, "delete") == 0) {
2549 dev_mod = LYS_DEV_DELETE;
2550 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002551 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
Michal Vasko69730152020-10-09 16:30:07 +02002552 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002553 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002554 return LY_EVALID;
2555 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002556 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002557
2558 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2559 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002560 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002561 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002562 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2563 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002564 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002565
2566 } else if (dev_mod == LYS_DEV_ADD) {
2567 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002568 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002569 d = (struct lysp_deviate *)d_add;
2570 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2571 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2572 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002573 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02002574 {LY_STMT_DEFAULT, &d_add->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002575 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2576 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2577 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2578 {LY_STMT_MUST, &d_add->musts, 0},
2579 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2580 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2581 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2582 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002583 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002584
2585 } else if (dev_mod == LYS_DEV_REPLACE) {
2586 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002587 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002588 d = (struct lysp_deviate *)d_rpl;
2589 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2590 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2591 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002592 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02002593 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002594 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2595 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2596 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2597 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2598 {LY_STMT_UNITS, &d_rpl->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, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002602
2603 } else {
2604 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002605 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002606 d = (struct lysp_deviate *)d_del;
2607 struct yin_subelement subelems[5] = {
Michal Vasko7f45cf22020-10-01 12:49:44 +02002608 {LY_STMT_DEFAULT, &d_del->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002609 {LY_STMT_MUST, &d_del->musts, 0},
2610 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2611 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2612 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2613 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002614 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002615 }
2616 LY_CHECK_GOTO(ret, cleanup);
2617
2618 d->mod = dev_mod;
2619 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002620 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002621
2622 return ret;
2623
2624cleanup:
2625 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002626 return ret;
2627}
2628
David Sedlák992fb7c2019-07-24 16:51:01 +02002629/**
David Sedlák8b754462019-07-25 16:22:13 +02002630 * @brief Parse deviation element.
2631 *
2632 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002633 * @param[in] deviations Deviations to add to.
2634 *
2635 * @return LY_ERR values.
2636 */
2637static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002638yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002639{
2640 struct lysp_deviation *dev;
2641
2642 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002643 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002644
2645 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002646 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2647 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2648 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002649 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002650 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2651 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2652 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2653 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2654 };
Michal Vasko69730152020-10-09 16:30:07 +02002655
Michal Vaskob36053d2020-03-26 15:49:30 +01002656 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002657}
2658
2659/**
David Sedlákb4e44562019-07-04 15:42:12 +02002660 * @brief Map keyword type to substatement info.
2661 *
2662 * @param[in] kw Keyword type.
2663 *
2664 * @return correct LYEXT_SUBSTMT information.
2665 */
2666static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002667kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002668{
2669 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002670 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002671 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002672 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002673 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002674 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002675 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002676 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002677 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002678 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002679 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002680 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002681 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002682 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002683 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002684 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002685 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002686 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002687 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002688 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002689 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002690 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002691 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002692 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002693 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002694 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002695 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002696 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002697 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002698 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002699 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002700 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002701 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002702 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002703 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002704 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002705 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002706 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002707 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002708 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002709 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002710 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002711 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002712 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002713 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002714 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002715 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002716 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002717 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002718 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002719 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002720 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002721 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002722 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002723 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002724 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002725 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002726 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002727 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002728 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002729 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002730 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002731 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002732 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002733 return LYEXT_SUBSTMT_IFFEATURE;
2734 default:
2735 return LYEXT_SUBSTMT_SELF;
2736 }
2737}
2738
David Sedlákc5b20842019-08-13 10:18:31 +02002739/**
2740 * @brief map keyword to keyword-group.
2741 *
2742 * @param[in] ctx YIN parser context used for logging.
2743 * @param[in] kw Keyword that is child of module or submodule.
2744 * @param[out] group Group of keyword.
2745 *
2746 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2747 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002748static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002749kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002750{
2751 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002752 /* module header */
2753 case LY_STMT_NONE:
2754 case LY_STMT_NAMESPACE:
2755 case LY_STMT_PREFIX:
2756 case LY_STMT_BELONGS_TO:
2757 case LY_STMT_YANG_VERSION:
2758 *group = Y_MOD_MODULE_HEADER;
2759 break;
2760 /* linkage */
2761 case LY_STMT_INCLUDE:
2762 case LY_STMT_IMPORT:
2763 *group = Y_MOD_LINKAGE;
2764 break;
2765 /* meta */
2766 case LY_STMT_ORGANIZATION:
2767 case LY_STMT_CONTACT:
2768 case LY_STMT_DESCRIPTION:
2769 case LY_STMT_REFERENCE:
2770 *group = Y_MOD_META;
2771 break;
2772 /* revision */
2773 case LY_STMT_REVISION:
2774 *group = Y_MOD_REVISION;
2775 break;
2776 /* body */
2777 case LY_STMT_ANYDATA:
2778 case LY_STMT_ANYXML:
2779 case LY_STMT_AUGMENT:
2780 case LY_STMT_CHOICE:
2781 case LY_STMT_CONTAINER:
2782 case LY_STMT_DEVIATION:
2783 case LY_STMT_EXTENSION:
2784 case LY_STMT_FEATURE:
2785 case LY_STMT_GROUPING:
2786 case LY_STMT_IDENTITY:
2787 case LY_STMT_LEAF:
2788 case LY_STMT_LEAF_LIST:
2789 case LY_STMT_LIST:
2790 case LY_STMT_NOTIFICATION:
2791 case LY_STMT_RPC:
2792 case LY_STMT_TYPEDEF:
2793 case LY_STMT_USES:
2794 case LY_STMT_EXTENSION_INSTANCE:
2795 *group = Y_MOD_BODY;
2796 break;
2797 default:
2798 LOGINT(ctx->xmlctx->ctx);
2799 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002800 }
2801
2802 return LY_SUCCESS;
2803}
2804
David Sedlákc5b20842019-08-13 10:18:31 +02002805/**
2806 * @brief Check if relative order of two keywords is valid.
2807 *
2808 * @param[in] ctx YIN parser context used for logging.
2809 * @param[in] kw Current keyword.
2810 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002811 * @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 +02002812 * because relative order is required only in module and submodule sub-elements, used for logging.
2813 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002814 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002815 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002816static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002817yin_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 +02002818{
Radek Krejcid6b76452019-09-03 17:03:03 +02002819 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002820 enum yang_module_stmt gr, next_gr;
2821
2822 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2823 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2824
2825 if (gr > next_gr) {
2826 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2827 return LY_EVALID;
2828 }
2829
2830 return LY_SUCCESS;
2831}
2832
David Sedlákc5dd0942019-09-13 10:23:59 +02002833/**
2834 * @brief Get element name prefixed by full URI of xml namespace.
2835 *
2836 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2837 * @param[in] name Name of element.
2838 * @param[in] name_len Length of element name.
2839 * @param[in] prefix Prefix of element.
2840 * @param[in] prefix_len Length of element prefix.
2841 *
2842 * @return Element name prefixed by URI on success, NULL on failure.
2843 */
2844static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002845name2nsname(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 +02002846{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002847 const char *ename = NULL;
Michal Vaskoc8a230d2020-08-14 12:17:10 +02002848 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002849
Michal Vaskob36053d2020-03-26 15:49:30 +01002850 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002851
Radek Krejci02728562019-09-18 14:13:05 +02002852 if (!strcmp(ns->uri, YIN_NS_URI)) {
2853 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002854 lydict_insert(ctx->xmlctx->ctx, name, name_len, &ename);
2855 return ename;
Radek Krejci02728562019-09-18 14:13:05 +02002856 }
2857 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002858 size_t ns_len = strlen(ns->uri);
2859 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2860
2861 char *result;
2862 char *temp;
Michal Vasko69730152020-10-09 16:30:07 +02002863
David Sedláke0ef1c62019-09-13 10:05:55 +02002864 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002865 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002866
2867 strcpy(result, ns->uri);
2868 result[ns_len] = ':';
2869 temp = &result[ns_len + 1];
2870 strncpy(temp, name, name_len);
2871 result[len] = '\0';
2872
Radek Krejci011e4aa2020-09-04 15:22:31 +02002873 lydict_insert_zc(ctx->xmlctx->ctx, result, &ename);
2874 return ename;
David Sedlák068dd352019-09-13 09:08:22 +02002875}
2876
David Sedlákd6e56892019-07-01 15:40:24 +02002877LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002878yin_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 +02002879 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002880{
2881 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002882 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002883 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002884 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002885
Michal Vaskob36053d2020-03-26 15:49:30 +01002886 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002887
Michal Vaskob36053d2020-03-26 15:49:30 +01002888 if (ctx->xmlctx->ws_only) {
2889 /* check whether there are any children */
2890 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2891 } else {
2892 /* we want to parse the value */
2893 next_status = LYXML_ELEM_CLOSE;
2894 }
2895
2896 if (next_status == LYXML_ELEMENT) {
2897 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2898
2899 /* current element has subelements as content */
2900 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2901 /* match keyword */
2902 last_kw = kw;
2903 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02002904 ctx->xmlctx->prefix_len, current_element);
Michal Vaskob36053d2020-03-26 15:49:30 +01002905
2906 /* check if this element can be child of current element */
2907 subelem = get_record(kw, subelem_info_size, subelem_info);
2908 if (!subelem) {
Michal Vasko69730152020-10-09 16:30:07 +02002909 if ((current_element == LY_STMT_DEVIATE) && isdevsub(kw)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01002910 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2911 } else {
2912 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
Michal Vasko69730152020-10-09 16:30:07 +02002913 ctx->xmlctx->name, ly_stmt2str(current_element));
Michal Vaskob36053d2020-03-26 15:49:30 +01002914 }
2915 ret = LY_EVALID;
2916 goto cleanup;
2917 }
2918
2919 /* relative order is required only in module and submodule sub-elements */
Michal Vasko69730152020-10-09 16:30:07 +02002920 if ((current_element == LY_STMT_MODULE) || (current_element == LY_STMT_SUBMODULE)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01002921 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2922 LY_CHECK_GOTO(ret, cleanup);
2923 }
2924
2925 /* flag check */
2926 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2927 /* subelement uniquenes */
2928 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2929 return LY_EVALID;
2930 }
2931 if (subelem->flags & YIN_SUBELEM_FIRST) {
2932 /* subelement is supposed to be defined as first subelement */
2933 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2934 LY_CHECK_GOTO(ret, cleanup);
2935 }
2936 if (subelem->flags & YIN_SUBELEM_VER2) {
2937 /* subelement is supported only in version 1.1 or higher */
2938 if (ctx->mod_version < 2) {
2939 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 +02002940 ret = LY_EVALID;
2941 goto cleanup;
2942 }
David Sedlákd6e56892019-07-01 15:40:24 +02002943 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002944 /* note that element was parsed for easy uniqueness check in next iterations */
2945 subelem->flags |= YIN_SUBELEM_PARSED;
2946
2947 switch (kw) {
2948 /* call responsible function */
2949 case LY_STMT_EXTENSION_INSTANCE:
2950 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vasko69730152020-10-09 16:30:07 +02002951 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002952 break;
2953 case LY_STMT_ACTION:
2954 case LY_STMT_RPC:
2955 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2956 break;
2957 case LY_STMT_ANYDATA:
2958 case LY_STMT_ANYXML:
2959 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2960 break;
2961 case LY_STMT_ARGUMENT:
2962 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2963 break;
2964 case LY_STMT_AUGMENT:
2965 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2966 break;
2967 case LY_STMT_BASE:
2968 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2969 break;
2970 case LY_STMT_BELONGS_TO:
2971 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2972 break;
2973 case LY_STMT_BIT:
2974 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2975 break;
2976 case LY_STMT_CASE:
2977 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2978 break;
2979 case LY_STMT_CHOICE:
2980 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2981 break;
2982 case LY_STMT_CONFIG:
2983 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2984 break;
2985 case LY_STMT_CONTACT:
2986 case LY_STMT_DESCRIPTION:
2987 case LY_STMT_ORGANIZATION:
2988 case LY_STMT_REFERENCE:
2989 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2990 break;
2991 case LY_STMT_CONTAINER:
2992 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2993 break;
2994 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002995 ret = yin_parse_qname(ctx, kw, subelem, exts);
2996 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01002997 case LY_STMT_ERROR_APP_TAG:
2998 case LY_STMT_KEY:
2999 case LY_STMT_PRESENCE:
3000 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3001 break;
3002 case LY_STMT_DEVIATE:
3003 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3004 break;
3005 case LY_STMT_DEVIATION:
3006 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3007 break;
3008 case LY_STMT_ENUM:
3009 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3010 break;
3011 case LY_STMT_ERROR_MESSAGE:
3012 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
3013 break;
3014 case LY_STMT_EXTENSION:
3015 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3016 break;
3017 case LY_STMT_FEATURE:
3018 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3019 break;
3020 case LY_STMT_FRACTION_DIGITS:
3021 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3022 break;
3023 case LY_STMT_GROUPING:
3024 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3025 break;
3026 case LY_STMT_IDENTITY:
3027 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3028 break;
3029 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003030 ret = yin_parse_qname(ctx, kw, subelem, exts);
3031 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003032 case LY_STMT_UNITS:
3033 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3034 break;
3035 case LY_STMT_IMPORT:
3036 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3037 break;
3038 case LY_STMT_INCLUDE:
3039 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3040 break;
3041 case LY_STMT_INPUT:
3042 case LY_STMT_OUTPUT:
3043 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3044 break;
3045 case LY_STMT_LEAF:
3046 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3047 break;
3048 case LY_STMT_LEAF_LIST:
3049 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3050 break;
3051 case LY_STMT_LENGTH:
3052 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3053 break;
3054 case LY_STMT_LIST:
3055 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3056 break;
3057 case LY_STMT_MANDATORY:
3058 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3059 break;
3060 case LY_STMT_MAX_ELEMENTS:
3061 case LY_STMT_MIN_ELEMENTS:
3062 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3063 break;
3064 case LY_STMT_MODIFIER:
3065 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3066 break;
3067 case LY_STMT_MUST:
3068 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3069 break;
3070 case LY_STMT_NAMESPACE:
3071 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3072 break;
3073 case LY_STMT_NOTIFICATION:
3074 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3075 break;
3076 case LY_STMT_ORDERED_BY:
3077 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3078 break;
3079 case LY_STMT_PATH:
3080 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3081 break;
3082 case LY_STMT_PATTERN:
3083 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3084 break;
3085 case LY_STMT_VALUE:
3086 case LY_STMT_POSITION:
3087 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3088 break;
3089 case LY_STMT_PREFIX:
3090 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3091 break;
3092 case LY_STMT_RANGE:
3093 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3094 break;
3095 case LY_STMT_REFINE:
3096 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3097 break;
3098 case LY_STMT_REQUIRE_INSTANCE:
3099 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3100 break;
3101 case LY_STMT_REVISION:
3102 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3103 break;
3104 case LY_STMT_REVISION_DATE:
3105 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3106 break;
3107 case LY_STMT_STATUS:
3108 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3109 break;
3110 case LY_STMT_TYPE:
3111 ret = yin_parse_type(ctx, current_element, subelem);
3112 break;
3113 case LY_STMT_TYPEDEF:
3114 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3115 break;
3116 case LY_STMT_UNIQUE:
3117 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3118 break;
3119 case LY_STMT_USES:
3120 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3121 break;
3122 case LY_STMT_WHEN:
3123 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3124 break;
3125 case LY_STMT_YANG_VERSION:
3126 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3127 break;
3128 case LY_STMT_YIN_ELEMENT:
3129 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3130 break;
3131 case LY_STMT_ARG_TEXT:
3132 case LY_STMT_ARG_VALUE:
3133 /* TODO what to do with content/attributes? */
3134 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3135 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3136 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3137 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3138 }
3139 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3140 break;
3141 default:
3142 LOGINT(ctx->xmlctx->ctx);
3143 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003144 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003145 LY_CHECK_GOTO(ret, cleanup);
3146 subelem = NULL;
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 } else {
3151 LY_CHECK_RET(ret);
3152 /* elements with text or none content */
3153 /* save text content, if text_content isn't set, it's just ignored */
3154 /* no resources are allocated in this branch, no need to use cleanup label */
3155 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3156 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003157 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 +01003158 LY_CHECK_RET(!*text_content, LY_EMEM);
3159 }
3160
3161 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003162 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003163
David Sedlák8b754462019-07-25 16:22:13 +02003164 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3165 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003166
3167cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003168 return ret;
3169}
3170
David Sedlák619db942019-07-03 14:47:30 +02003171LY_ERR
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003172yin_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 +02003173 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003174{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003175 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003176 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003177
Michal Vaskob36053d2020-03-26 15:49:30 +01003178 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3179
3180 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003181
3182 e->yin = 0;
3183 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003184 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 +02003185 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003186 e->insubstmt = subelem;
3187 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003188 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003189 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003190
David Sedlákb1a78352019-06-28 16:16:29 +02003191 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003192 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3193 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003194 new_subelem = calloc(1, sizeof(*new_subelem));
3195 if (!e->child) {
3196 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003197 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003198 last_subelem->next = new_subelem;
3199 }
3200 last_subelem = new_subelem;
3201
3202 last_subelem->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003203 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 +02003204 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003205 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003206
Radek Krejci011e4aa2020-09-04 15:22:31 +02003207 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 +02003208 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003209 } else {
3210 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003211 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003212
3213 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003214 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003215
David Sedlákf250ecf2019-07-01 11:02:05 +02003216 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003217 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3218 if (ctx->xmlctx->ws_only) {
3219 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3220 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3221 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3222 if (!e->child) {
3223 e->child = new_subelem;
3224 } else {
3225 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003226 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003227 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003228
Michal Vaskob36053d2020-03-26 15:49:30 +01003229 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3230 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003231 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003232 } else if (ctx->xmlctx->value_len) {
3233 /* save text content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003234 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 +01003235 LY_CHECK_RET(!e->argument, LY_EMEM);
3236
3237 /* parser next */
3238 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003239 }
3240
3241 return LY_SUCCESS;
3242}
3243
David Sedlákaa98bba2019-09-12 11:52:14 +02003244/**
3245 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3246 *
3247 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003248 * @param[in] elem_type Type of element that is currently being parsed.
3249 * @param[out] arg Value to write to.
3250 *
3251 * @return LY_ERR values.
3252 */
3253static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003254yin_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 +02003255{
David Sedlák071f7662019-09-12 02:02:51 +02003256 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003257
Michal Vaskob36053d2020-03-26 15:49:30 +01003258 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3259
David Sedláke6284fc2019-09-10 11:57:02 +02003260 switch (elem_type) {
3261 case LY_STMT_ACTION:
3262 case LY_STMT_ANYDATA:
3263 case LY_STMT_ANYXML:
3264 case LY_STMT_ARGUMENT:
3265 case LY_STMT_BASE:
3266 case LY_STMT_BIT:
3267 case LY_STMT_CASE:
3268 case LY_STMT_CHOICE:
3269 case LY_STMT_CONTAINER:
3270 case LY_STMT_ENUM:
3271 case LY_STMT_EXTENSION:
3272 case LY_STMT_FEATURE:
3273 case LY_STMT_GROUPING:
3274 case LY_STMT_IDENTITY:
3275 case LY_STMT_IF_FEATURE:
3276 case LY_STMT_LEAF:
3277 case LY_STMT_LEAF_LIST:
3278 case LY_STMT_LIST:
3279 case LY_STMT_MODULE:
3280 case LY_STMT_NOTIFICATION:
3281 case LY_STMT_RPC:
3282 case LY_STMT_SUBMODULE:
3283 case LY_STMT_TYPE:
3284 case LY_STMT_TYPEDEF:
3285 case LY_STMT_UNITS:
3286 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003287 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 +02003288 break;
3289 case LY_STMT_AUGMENT:
3290 case LY_STMT_DEVIATION:
3291 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003292 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 +02003293 break;
3294 case LY_STMT_CONFIG:
3295 case LY_STMT_DEFAULT:
3296 case LY_STMT_DEVIATE:
3297 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003298 case LY_STMT_FRACTION_DIGITS:
3299 case LY_STMT_KEY:
3300 case LY_STMT_LENGTH:
3301 case LY_STMT_MANDATORY:
3302 case LY_STMT_MAX_ELEMENTS:
3303 case LY_STMT_MIN_ELEMENTS:
3304 case LY_STMT_MODIFIER:
3305 case LY_STMT_ORDERED_BY:
3306 case LY_STMT_PATH:
3307 case LY_STMT_PATTERN:
3308 case LY_STMT_POSITION:
3309 case LY_STMT_PREFIX:
3310 case LY_STMT_PRESENCE:
3311 case LY_STMT_RANGE:
3312 case LY_STMT_REQUIRE_INSTANCE:
3313 case LY_STMT_STATUS:
3314 case LY_STMT_VALUE:
3315 case LY_STMT_YANG_VERSION:
3316 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003317 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 +02003318 break;
3319 case LY_STMT_IMPORT:
3320 case LY_STMT_INCLUDE:
3321 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003322 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 +02003323 break;
3324 case LY_STMT_INPUT:
3325 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003326 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 +02003327 break;
3328 case LY_STMT_MUST:
3329 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003330 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 +02003331 break;
3332 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003333 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 +02003334 break;
3335 case LY_STMT_REVISION:
3336 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003337 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 +02003338 break;
3339 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003340 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 +02003341 break;
David Sedlák071f7662019-09-12 02:02:51 +02003342 /* argument is mapped to yin element */
3343 case LY_STMT_CONTACT:
3344 case LY_STMT_DESCRIPTION:
3345 case LY_STMT_ORGANIZATION:
3346 case LY_STMT_REFERENCE:
3347 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003348 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003349 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3350
3351 /* no content */
3352 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3353 if (ctx->xmlctx->ws_only) {
3354 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3355 }
3356 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3357 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
Michal Vasko69730152020-10-09 16:30:07 +02003358 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003359 return LY_EVALID;
3360 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003361
3362 /* parse child element */
3363 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 +02003364 if (((elem_type == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3365 ((elem_type != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003366 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 +02003367 ly_stmt2str(elem_type));
Michal Vaskob36053d2020-03-26 15:49:30 +01003368 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003369 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003370 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3371
3372 /* no attributes expected? TODO */
3373 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3374 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3375 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3376 }
3377
3378 /* load and save content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003379 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
Michal Vaskob36053d2020-03-26 15:49:30 +01003380 LY_CHECK_RET(!*arg, LY_EMEM);
3381
3382 /* load closing tag of subelement */
3383 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3384
3385 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3386 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3387 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3388 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003389 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003390 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003391 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003392 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003393 }
3394
David Sedlák071f7662019-09-12 02:02:51 +02003395 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003396}
3397
3398LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003399yin_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 +02003400{
3401 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003402 struct lysp_stmt *last = NULL, *new = NULL;
3403
Michal Vaskob36053d2020-03-26 15:49:30 +01003404 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003405
3406 /* allocate new structure for element */
3407 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003408 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3409 (*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 +02003410 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003411
Michal Vaskob36053d2020-03-26 15:49:30 +01003412 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
Michal Vasko69730152020-10-09 16:30:07 +02003413 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003414
3415 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003416 if ((*element)->kw == LY_STMT_NONE) {
3417 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003418 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 +02003419 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003420 ret = LY_EVALID;
3421 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003422 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3423 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003424 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003425 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003426 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003427 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3428
David Sedlákaa98bba2019-09-12 11:52:14 +02003429 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003430 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003431 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003432 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003433 if (!(*element)->child) {
3434 /* save first */
3435 (*element)->child = new;
3436 } else {
3437 last->next = new;
3438 }
3439 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003440
David Sedláke6284fc2019-09-10 11:57:02 +02003441 last->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003442 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 +02003443 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003444 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003445 if (!ctx->xmlctx->prefix) {
3446 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3447
Radek Krejci011e4aa2020-09-04 15:22:31 +02003448 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 +02003449 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003450 } else {
3451 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003452 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003453 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003454 }
3455 }
3456
Michal Vaskob36053d2020-03-26 15:49:30 +01003457 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3458 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3459 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3460 /* parse subelements */
3461 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003462 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003463 if (!(*element)->child) {
3464 /* save first */
3465 (*element)->child = new;
3466 } else {
3467 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003468 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003469 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003470
Michal Vaskob36053d2020-03-26 15:49:30 +01003471 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3472 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003473 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003474 } else {
3475 /* save element content */
3476 if (ctx->xmlctx->value_len) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003477 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 +01003478 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3479 }
3480
3481 /* read closing tag */
3482 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003483 }
3484
David Sedlákb0ca07d2019-09-11 11:54:05 +02003485cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003486 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003487}
3488
3489LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003490yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003491{
David Sedlák81497a32019-08-13 16:56:26 +02003492 LY_ERR ret = LY_SUCCESS;
3493 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003494 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003495
Michal Vaskoc3781c32020-10-06 14:04:08 +02003496 mod->is_submod = 0;
3497
Michal Vaskob36053d2020-03-26 15:49:30 +01003498 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3499 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 +02003500 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003501 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3502 LY_STMT_ANYXML, &mod->data, 0,
3503 LY_STMT_AUGMENT, &mod->augments, 0,
3504 LY_STMT_CHOICE, &mod->data, 0,
3505 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3506 LY_STMT_CONTAINER, &mod->data, 0,
3507 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3508 LY_STMT_DEVIATION, &mod->deviations, 0,
3509 LY_STMT_EXTENSION, &mod->extensions, 0,
3510 LY_STMT_FEATURE, &mod->features, 0,
3511 LY_STMT_GROUPING, &mod->groupings, 0,
3512 LY_STMT_IDENTITY, &mod->identities, 0,
3513 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3514 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3515 LY_STMT_LEAF, &mod->data, 0,
3516 LY_STMT_LEAF_LIST, &mod->data, 0,
3517 LY_STMT_LIST, &mod->data, 0,
3518 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3519 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3520 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3521 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3522 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3523 LY_STMT_REVISION, &mod->revs, 0,
3524 LY_STMT_RPC, &mod->rpcs, 0,
3525 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3526 LY_STMT_USES, &mod->data, 0,
3527 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
3528 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003529
Michal Vaskob36053d2020-03-26 15:49:30 +01003530 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003531 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003532 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003533
David Sedláked809f12019-09-13 10:15:11 +02003534 /* finalize parent pointers to the reallocated items */
3535 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3536
3537 /* submodules share the namespace with the module names, so there must not be
3538 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003539 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003540 if (dup) {
3541 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3542 return LY_EVALID;
3543 }
3544
3545 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003546}
3547
3548LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003549yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003550{
David Sedlák81497a32019-08-13 16:56:26 +02003551 LY_ERR ret = LY_SUCCESS;
3552 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003553 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003554
Michal Vaskoc3781c32020-10-06 14:04:08 +02003555 submod->is_submod = 1;
3556
Michal Vaskob36053d2020-03-26 15:49:30 +01003557 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3558 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 +02003559 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Michal Vasko69730152020-10-09 16:30:07 +02003560 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3561 LY_STMT_ANYXML, &submod->data, 0,
3562 LY_STMT_AUGMENT, &submod->augments, 0,
3563 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3564 LY_STMT_CHOICE, &submod->data, 0,
3565 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3566 LY_STMT_CONTAINER, &submod->data, 0,
3567 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3568 LY_STMT_DEVIATION, &submod->deviations, 0,
3569 LY_STMT_EXTENSION, &submod->extensions, 0,
3570 LY_STMT_FEATURE, &submod->features, 0,
3571 LY_STMT_GROUPING, &submod->groupings, 0,
3572 LY_STMT_IDENTITY, &submod->identities, 0,
3573 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3574 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3575 LY_STMT_LEAF, &submod->data, 0,
3576 LY_STMT_LEAF_LIST, &submod->data, 0,
3577 LY_STMT_LIST, &submod->data, 0,
3578 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3579 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3580 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3581 LY_STMT_REVISION, &submod->revs, 0,
3582 LY_STMT_RPC, &submod->rpcs, 0,
3583 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3584 LY_STMT_USES, &submod->data, 0,
3585 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3586 LY_STMT_EXTENSION_INSTANCE, NULL, 0));
David Sedlák81497a32019-08-13 16:56:26 +02003587
Michal Vaskob36053d2020-03-26 15:49:30 +01003588 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003589 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003590 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003591
David Sedláked809f12019-09-13 10:15:11 +02003592 /* finalize parent pointers to the reallocated items */
3593 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3594
3595 /* submodules share the namespace with the module names, so there must not be
3596 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003597 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003598 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
David Sedláked809f12019-09-13 10:15:11 +02003599 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3600 return LY_EVALID;
3601 }
3602
3603 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003604}
3605
3606LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003607yin_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 +02003608 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003609{
Radek Krejcid6b76452019-09-03 17:03:03 +02003610 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003611 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003612 struct lysp_submodule *mod_p = NULL;
3613
3614 /* create context */
3615 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003616 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003617 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko7c8439f2020-08-05 13:25:19 +02003618 (*yin_ctx)->main_mod = main_ctx->main_mod;
Michal Vasko63f3d842020-07-08 10:10:14 +02003619 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003620
David Sedlák1b623122019-08-05 15:27:49 +02003621 /* map the typedefs and groupings list from main context to the submodule's context */
3622 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3623 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3624
David Sedlák8985a142019-07-31 16:43:06 +02003625 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003626 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 +02003627 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003628 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003629 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3630 ret = LY_EINVAL;
3631 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003632 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003633 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003634 ret = LY_EVALID;
3635 goto cleanup;
3636 }
3637
3638 mod_p = calloc(1, sizeof *mod_p);
Radek Krejcif027df72020-09-15 13:00:28 +02003639 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003640 mod_p->mod = main_ctx->main_mod;
David Sedlák8985a142019-07-31 16:43:06 +02003641 mod_p->parsing = 1;
3642
Michal Vaskob36053d2020-03-26 15:49:30 +01003643 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003644 LY_CHECK_GOTO(ret, cleanup);
3645
David Sedlákbf8a2b72019-08-14 16:48:10 +02003646 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003647 while (isspace(in->current[0])) {
3648 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003649 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003650 if (in->current[0]) {
3651 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003652 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003653 ret = LY_EVALID;
3654 goto cleanup;
3655 }
3656
David Sedlák8985a142019-07-31 16:43:06 +02003657 mod_p->parsing = 0;
3658 *submod = mod_p;
3659
3660cleanup:
3661 if (ret) {
3662 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003663 yin_parser_ctx_free(*yin_ctx);
3664 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003665 }
David Sedlák8985a142019-07-31 16:43:06 +02003666 return ret;
3667}
3668
3669LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003670yin_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 +02003671{
David Sedláke4889912018-11-02 09:52:40 +01003672 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003673 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003674 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003675
David Sedlák8985a142019-07-31 16:43:06 +02003676 /* create context */
3677 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003678 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003679 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko7c8439f2020-08-05 13:25:19 +02003680 (*yin_ctx)->main_mod = mod;
Michal Vasko63f3d842020-07-08 10:10:14 +02003681 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003682
David Sedlák8985a142019-07-31 16:43:06 +02003683 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003684 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 +02003685 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003686 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003687 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 +01003688 ret = LY_EINVAL;
3689 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003690 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003691 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003692 ret = LY_EVALID;
3693 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003694 }
3695
David Sedlák3017da42019-02-15 09:48:04 +01003696 /* allocate module */
3697 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003698 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003699 mod_p->mod = mod;
3700 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003701
David Sedlák00250342019-06-21 14:19:39 +02003702 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003703 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003704 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003705
David Sedlákbf8a2b72019-08-14 16:48:10 +02003706 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003707 while (isspace(in->current[0])) {
3708 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003709 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003710 if (in->current[0]) {
3711 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
Michal Vasko69730152020-10-09 16:30:07 +02003712 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003713 ret = LY_EVALID;
3714 goto cleanup;
3715 }
3716
David Sedlák3017da42019-02-15 09:48:04 +01003717 mod_p->parsing = 0;
3718 mod->parsed = mod_p;
3719
3720cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003721 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003722 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003723 yin_parser_ctx_free(*yin_ctx);
3724 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003725 }
David Sedlák2e411422018-12-17 02:35:39 +01003726 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003727}