blob: c435a09a7be2d19da86d32f4dd40c1ecdba54ae2 [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 Vasko004d3152020-06-11 19:59:22 +020028#include "path.h"
Michal Vasko63f3d842020-07-08 10:10:14 +020029#include "parser_internal.h"
Radek Krejcica376bd2020-06-11 16:04:06 +020030#include "parser_schema.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
68 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 Vasko63f3d842020-07-08 10:10:14 +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;
David Sedlák7ff55a92019-06-17 11:11:41 +0200108 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200109
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200110#define READ_INC(LEN) already_read += LEN
111#define ARG_SET(STMT) arg=STMT
112#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
David Sedlákc10e7902018-12-17 02:17:59 +0100113
David Sedlák1c8b2702019-02-22 11:03:02 +0100114 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100115 case 'c':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200116 READ_INC(1);
117 if (ARG_CHECK("ondition", 8)) {
118 ARG_SET(YIN_ARG_CONDITION);
119 }
David Sedlák3b4db242018-10-19 16:11:01 +0200120 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'd':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200123 READ_INC(1);
124 if (ARG_CHECK("ate", 3)) {
125 ARG_SET(YIN_ARG_DATE);
126 }
David Sedlák3b4db242018-10-19 16:11:01 +0200127 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200128
David Sedlák94de2aa2019-02-15 12:42:11 +0100129 case 'm':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200130 READ_INC(1);
131 if (ARG_CHECK("odule", 5)) {
132 ARG_SET(YIN_ARG_MODULE);
133 }
David Sedlák872c7b42018-10-26 13:15:20 +0200134 break;
135
David Sedlák94de2aa2019-02-15 12:42:11 +0100136 case 'n':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200137 READ_INC(1);
138 if (ARG_CHECK("ame", 3)) {
139 ARG_SET(YIN_ARG_NAME);
140 }
David Sedlák872c7b42018-10-26 13:15:20 +0200141 break;
142
David Sedlák94de2aa2019-02-15 12:42:11 +0100143 case 't':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200144 READ_INC(1);
145 if (ARG_CHECK("a", 1)) {
146 if (ARG_CHECK("g", 1)) {
147 ARG_SET(YIN_ARG_TAG);
148 } else if (ARG_CHECK("rget-node", 9)) {
149 ARG_SET(YIN_ARG_TARGET_NODE);
150 }
151 } else if (ARG_CHECK("ext", 3)) {
152 ARG_SET(YIN_ARG_TEXT);
153 }
David Sedlák3b4db242018-10-19 16:11:01 +0200154 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200155
David Sedlák94de2aa2019-02-15 12:42:11 +0100156 case 'u':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200157 READ_INC(1);
158 if (ARG_CHECK("ri", 2)) {
159 ARG_SET(YIN_ARG_URI);
160 }
David Sedlák3b4db242018-10-19 16:11:01 +0200161 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200162
David Sedlák94de2aa2019-02-15 12:42:11 +0100163 case 'v':
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200164 READ_INC(1);
165 if (ARG_CHECK("alue", 4)) {
166 ARG_SET(YIN_ARG_VALUE);
167 }
David Sedlák3b4db242018-10-19 16:11:01 +0200168 break;
169 }
170
David Sedlákc10e7902018-12-17 02:17:59 +0100171 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200172 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200173 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200174 }
175
Radek Krejci8bb8d9d2020-08-21 14:53:27 +0200176#undef ARG_CHECK
177#undef ARG_SET
178#undef READ_INC
David Sedlák18730132019-03-15 15:51:34 +0100179
David Sedlák872c7b42018-10-26 13:15:20 +0200180 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200181}
182
Radek Krejcid6b76452019-09-03 17:03:03 +0200183#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
184 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
185 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
186 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200187
Radek Krejcid6b76452019-09-03 17:03:03 +0200188#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 +0200189
David Sedlák26ea1432019-08-14 13:42:23 +0200190/**
191 * @brief Free subelems information allocated on heap.
192 *
193 * @param[in] count Size of subelems array.
194 * @param[in] subelems Subelems array to free.
195 */
David Sedlák81497a32019-08-13 16:56:26 +0200196static void
197subelems_deallocator(size_t count, struct yin_subelement *subelems)
198{
Michal Vaskod989ba02020-08-24 10:59:24 +0200199 for (size_t i = 0; i < count; ++i) {
David Sedlák81497a32019-08-13 16:56:26 +0200200 if (HAS_META(subelems[i].type)) {
201 free(subelems[i].dest);
202 }
203 }
204
205 free(subelems);
206}
207
David Sedlák26ea1432019-08-14 13:42:23 +0200208/**
209 * @brief Allocate subelems information on heap.
210 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200211 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200212 * @param[in] count Number of subelements.
213 * @param[in] parent Parent node if any.
214 * @param[out] result Allocated subelems array.
215 *
216 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
217 */
David Sedlák81497a32019-08-13 16:56:26 +0200218static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100219subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
Radek Krejci0f969882020-08-21 16:56:47 +0200220 struct yin_subelement **result, ...)
David Sedlák81497a32019-08-13 16:56:26 +0200221{
222 va_list ap;
223
224 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200225 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200226
227 va_start(ap, result);
228 for (size_t i = 0; i < count; ++i) {
229 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200230 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200231 /* DEST */
232 if (IS_NODE_ELEM((*result)[i].type)) {
233 struct tree_node_meta *node_meta = NULL;
234 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200235 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200236 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200237 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200238 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200239 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200240 struct import_meta *imp_meta = NULL;
241 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200242 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200243 imp_meta->prefix = va_arg(ap, const char *);
244 imp_meta->imports = va_arg(ap, struct lysp_import **);
245 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200246 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200247 struct include_meta *inc_meta = NULL;
248 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200249 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200250 inc_meta->name = va_arg(ap, const char *);
251 inc_meta->includes = va_arg(ap, struct lysp_include **);
252 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200253 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200254 struct inout_meta *inout_meta = NULL;
255 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200256 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200257 inout_meta->parent = parent;
258 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
259 (*result)[i].dest = inout_meta;
260 } else {
261 (*result)[i].dest = va_arg(ap, void *);
262 }
263 /* FLAGS */
264 (*result)[i].flags = va_arg(ap, int);
265 }
266 va_end(ap);
267
268 return LY_SUCCESS;
269
David Sedlákbf8a2b72019-08-14 16:48:10 +0200270mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200271 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100272 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200273 return LY_EMEM;
274}
275
David Sedlák8f7a1172019-06-20 14:42:18 +0200276LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100277yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200278{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200279 uint8_t prefix = 0;
280 uint32_t c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100281 size_t utf8_char_len, already_read = 0;
282 const char *val;
283
284 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
285
286 val = ctx->xmlctx->value;
287 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200288 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
289 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
290 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100291 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200292
293 switch (val_type) {
294 case Y_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200295 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 +0200296 break;
297 case Y_PREF_IDENTIF_ARG:
Radek Krejci1deb5be2020-08-26 16:43:36 +0200298 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 +0200299 break;
300 case Y_STR_ARG:
301 case Y_MAYBE_STR_ARG:
302 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
303 break;
304 }
305 }
306
307 return LY_SUCCESS;
308}
309
David Sedlákb4e44562019-07-04 15:42:12 +0200310/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100311 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200312 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200313 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200314 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
315 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200316 * @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 +0200317 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200318 * @param[in] current_element Identification of current element, used for logging.
319 *
320 * @return LY_ERR values.
321 */
322static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100323yin_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 +0200324 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200325{
David Sedlákc5b20842019-08-13 10:18:31 +0200326 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200327 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200328
David Sedlák1bccdfa2019-06-17 15:55:27 +0200329 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100330 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200331 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100332 if (!ctx->xmlctx->prefix) {
333 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200334 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100335 /* skip it */
336 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200337 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200338 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200339 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200340 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100341
342 /* go to value */
343 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
344 LY_CHECK_RET(yin_validate_value(ctx, val_type));
Radek Krejci011e4aa2020-09-04 15:22:31 +0200345 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 +0200346 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200347 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100348 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
349 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200350 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200351 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100352 } else {
353 /* skip it */
354 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200355 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100356
357 /* next attribute */
358 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200359 }
360
David Sedlák292763b2019-07-09 11:10:53 +0200361 /* anything else than Y_MAYBE_STR_ARG is mandatory */
362 if (val_type != Y_MAYBE_STR_ARG && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100363 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
364 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200365 return LY_EVALID;
366 }
367
368 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200369}
370
David Sedlákd6e56892019-07-01 15:40:24 +0200371/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200372 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200373 *
374 * @param[in] type Type of wanted record.
375 * @param[in] array_size Size of array.
376 * @param[in] array Searched array.
377 *
378 * @return Pointer to desired record on success, NULL if element is not in the array.
379 */
David Sedlákb4e44562019-07-04 15:42:12 +0200380static struct yin_subelement *
Radek Krejci1deb5be2020-08-26 16:43:36 +0200381get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200382{
Radek Krejci1deb5be2020-08-26 16:43:36 +0200383 for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
Radek Krejci12b1c152019-09-05 16:20:48 +0200384 if (array[u].type == type) {
385 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200386 }
387 }
David Sedlákd6e56892019-07-01 15:40:24 +0200388 return NULL;
389}
390
David Sedlákbba38e52019-07-09 15:20:01 +0200391/**
392 * @brief Helper function to check mandatory constraint of subelement.
393 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200394 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200395 * @param[in] subelem_info Array of information about subelements.
396 * @param[in] subelem_info_size Size of subelem_info array.
397 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
398 *
399 * @return LY_ERR values.
400 */
401static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100402yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200403 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200404{
David Sedlákb0faad82019-07-04 14:28:59 +0200405 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200406 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200407 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200408 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200409 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200410 return LY_EVALID;
411 }
412 }
413
414 return LY_SUCCESS;
415}
416
David Sedlákbba38e52019-07-09 15:20:01 +0200417/**
418 * @brief Helper function to check "first" constraint of subelement.
419 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200420 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200421 * @param[in] subelem_info Array of information about subelements.
422 * @param[in] subelem_info_size Size of subelem_info array.
423 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200424 * @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 +0200425 *
426 * @return LY_ERR values.
427 */
428static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100429yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejci0f969882020-08-21 16:56:47 +0200430 signed char subelem_info_size, enum ly_stmt current_element,
431 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200432{
David Sedlákb0faad82019-07-04 14:28:59 +0200433 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200434 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200435 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
436 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200437 return LY_EVALID;
438 }
439 }
440
441 return LY_SUCCESS;
442}
443
David Sedlákbba38e52019-07-09 15:20:01 +0200444/**
David Sedlákb4e44562019-07-04 15:42:12 +0200445 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
446 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200447 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200448 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200449 * @param[in] kw Type of current element.
450 * @param[out] value Where value of attribute should be stored.
451 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200452 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200453 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200454 * @return LY_ERR values.
455 */
David Sedlákb4e44562019-07-04 15:42:12 +0200456static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100457yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
Radek Krejci0f969882020-08-21 16:56:47 +0200458 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200459{
Michal Vaskob36053d2020-03-26 15:49:30 +0100460 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
461 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200462 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200463 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
464 };
David Sedlákb4e44562019-07-04 15:42:12 +0200465
Michal Vaskob36053d2020-03-26 15:49:30 +0100466 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200467}
468
469/**
David Sedlák6542aed2019-08-14 10:47:43 +0200470 * @brief Parse path element.
471 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200472 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200473 * @param[in] kw Type of current element.
474 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200475 * @return LY_ERR values.
476 */
477static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100478yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200479{
Michal Vasko004d3152020-06-11 19:59:22 +0200480 LY_ERR ret;
481 const char *str_path;
482
483 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 +0200484 ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
Michal Vasko004d3152020-06-11 19:59:22 +0200485 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
486 lydict_remove(ctx->xmlctx->ctx, str_path);
487 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200488 type->flags |= LYS_SET_PATH;
489
490 return LY_SUCCESS;
491}
492
493/**
David Sedlákd3983112019-07-12 11:20:56 +0200494 * @brief Parse pattern element.
495 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200496 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200497 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200498 * @return LY_ERR values.
499 */
500static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100501yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200502{
503 const char *real_value = NULL;
504 char *saved_value = NULL;
505 struct lysp_restr *restr;
506
Michal Vaskob36053d2020-03-26 15:49:30 +0100507 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
508 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
509 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 +0200510 size_t len = strlen(real_value);
511
512 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100513 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200514 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100515 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200516 saved_value[0] = 0x06;
517 saved_value[len + 1] = '\0';
Michal Vasko7f45cf22020-10-01 12:49:44 +0200518 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
519 restr->arg.mod = ctx->main_mod;
David Sedlákd3983112019-07-12 11:20:56 +0200520 type->flags |= LYS_SET_PATTERN;
521
522 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200523 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
524 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
525 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
526 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
527 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
528 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
529 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100530 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200531}
532
David Sedlákc5b20842019-08-13 10:18:31 +0200533/**
534 * @brief Parse fraction-digits element.
535 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200536 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200537 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200538 * @return LY_ERR values.
539 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200540static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100541yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200542{
543 const char *temp_val = NULL;
544 char *ptr;
545 unsigned long int num;
546
Michal Vaskob36053d2020-03-26 15:49:30 +0100547 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
548 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 +0200549
550 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200551 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100552 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200553 return LY_EVALID;
554 }
555
556 errno = 0;
557 num = strtoul(temp_val, &ptr, 10);
558 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200559 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100560 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200561 return LY_EVALID;
562 }
563 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200564 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100565 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200566 return LY_EVALID;
567 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100568 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200569 type->fraction_digits = num;
570 type->flags |= LYS_SET_FRDIGITS;
571 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200572 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
573 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100574 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200575}
576
David Sedlák07869a52019-07-12 14:28:19 +0200577/**
David Sedlák43801c92019-08-05 15:58:54 +0200578 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200579 *
580 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200581 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200582 * @return LY_ERR values.
583 */
David Sedlákca36c422019-07-12 12:47:55 +0200584static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100585yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200586{
David Sedlák07869a52019-07-12 14:28:19 +0200587 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200588
Michal Vaskob36053d2020-03-26 15:49:30 +0100589 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200590 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100591 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
592 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 +0200593 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100594 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200595 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200596
597 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200598 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
599 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
600 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
601 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
602 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
603 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
604 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100605 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200606}
607
608/**
609 * @brief Parse bit element.
610 *
611 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200612 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200613 * @return LY_ERR values.
614 */
615static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100616yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200617{
618 struct lysp_type_enum *en;
619
Michal Vaskob36053d2020-03-26 15:49:30 +0100620 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200621 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100622 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
623 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 +0200624 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
625
626 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200627 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
628 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
629 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
630 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
631 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
632 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
633 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100634 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200635}
636
David Sedlákd3983112019-07-12 11:20:56 +0200637/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200638 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
639 * more instances, such as base or if-feature.
640 *
641 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200642 * @param[in] kw Type of current element.
643 * @param[out] values Parsed values to add to.
644 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200645 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200646 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200647 * @return LY_ERR values.
648 */
649static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100650yin_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 +0200651 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200652{
653 const char **value;
Michal Vaskob36053d2020-03-26 15:49:30 +0100654 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200655 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200656 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200657 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
658 };
David Sedlák968ac342019-07-11 15:17:59 +0200659
Michal Vaskob36053d2020-03-26 15:49:30 +0100660 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
661 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200662
Michal Vaskob36053d2020-03-26 15:49:30 +0100663 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200664}
665
666/**
David Sedlák6542aed2019-08-14 10:47:43 +0200667 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
668 *
669 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200670 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200671 * @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 +0200672 * @param[in] arg_type Expected type of attribute.
673 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200674 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200675 * @return LY_ERR values.
676 */
677static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100678yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
Radek Krejci0f969882020-08-21 16:56:47 +0200679 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200680{
681 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100682 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200683 arg_type, arg_val_type, exts));
684 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100685 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200686 arg_type, arg_val_type, exts));
687 }
688
689 return LY_SUCCESS;
690}
691
692/**
693 * @brief Parse base element.
694 *
695 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200696 * @param[in] parent Identification of parent element.
697 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200698 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200699 * @return LY_ERR values.
700 */
701static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100702yin_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 +0200703{
704 struct lysp_type *type = NULL;
705
Radek Krejcid6b76452019-09-03 17:03:03 +0200706 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200707 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100708 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200709 Y_PREF_IDENTIF_ARG, exts));
710 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200711 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100712 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200713 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
714 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100715 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200716 return LY_EINT;
717 }
718
719 return LY_SUCCESS;
720}
721
722/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200723 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200724 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200725 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100726 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200727 * @return LY_ERR values.
728 */
729static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100730yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200731{
732 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200733 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200734 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
735 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200736
737 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100738 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
739 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 +0200740 if (strcmp(temp_val, "true") == 0) {
741 type->require_instance = 1;
742 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200743 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
744 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100745 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200746 return LY_EVALID;
747 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100748 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200749
Michal Vaskob36053d2020-03-26 15:49:30 +0100750 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200751}
752
753/**
David Sedlákce77bf52019-07-11 16:59:31 +0200754 * @brief Parse modifier element.
755 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200756 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200757 * @param[in,out] pat Value to write to.
758 * @param[in,out] exts Extension instances to add to.
759 *
760 * @return LY_ERR values.
761 */
762static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100763yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200764{
David Sedlákd3983112019-07-12 11:20:56 +0200765 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200766 const char *temp_val;
767 char *modified_val;
768 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200769 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
770 };
David Sedlákce77bf52019-07-11 16:59:31 +0200771
Michal Vaskob36053d2020-03-26 15:49:30 +0100772 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
773 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 +0200774 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200775 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
776 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100777 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200778 return LY_EVALID;
779 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100780 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200781
782 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200783 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100784 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200785 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100786 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200787
788 /* modify the new value */
789 modified_val[0] = 0x15;
Radek Krejci011e4aa2020-09-04 15:22:31 +0200790 LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
David Sedlákce77bf52019-07-11 16:59:31 +0200791
Michal Vaskob36053d2020-03-26 15:49:30 +0100792 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200793}
794
795/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200796 * @brief Parse a restriction element (length, range or one instance of must).
797 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200798 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200799 * @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 +0200800 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200801 */
802static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100803yin_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 +0200804{
Radek Krejcid6b76452019-09-03 17:03:03 +0200805 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200806 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200807 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
808 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
809 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
810 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
811 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
812 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200813 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200814 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200815
Michal Vaskob36053d2020-03-26 15:49:30 +0100816 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vasko7f45cf22020-10-01 12:49:44 +0200817 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
818 restr->arg.mod = ctx->main_mod;
Michal Vaskob36053d2020-03-26 15:49:30 +0100819
820 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200821}
822
823/**
David Sedlák6542aed2019-08-14 10:47:43 +0200824 * @brief Parse range element.
825 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200826 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200827 * @param[out] type Type structure to store parsed value and flags.
828 *
829 * @return LY_ERR values.
830 */
831static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100832yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200833{
834 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100835 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
836 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
Michal Vasko44f3d2c2020-08-24 09:49:38 +0200837 type->flags |= LYS_SET_RANGE;
David Sedlák6542aed2019-08-14 10:47:43 +0200838
839 return LY_SUCCESS;
840}
841
842/**
843 * @brief Parse length element.
844 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200845 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200846 * @param[out] type Type structure to store parsed value and flags.
847 *
848 * @return LY_ERR values.
849 */
850static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100851yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200852{
853 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100854 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
855 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200856 type->flags |= LYS_SET_LENGTH;
857
858 return LY_SUCCESS;
859}
860
861/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200862 * @brief Parse must element.
863 *
864 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200865 * @param[in,out] restrs Restrictions to add to.
866 *
867 * @return LY_ERR values.
868 */
869static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100870yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200871{
872 struct lysp_restr *restr;
873
Michal Vaskob36053d2020-03-26 15:49:30 +0100874 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
875 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200876}
877
878/**
Michal Vasko7f45cf22020-10-01 12:49:44 +0200879 * @brief Parse a node id into an array.
880 *
881 * @param[in,out] ctx YIN parser context for logging and to store current state.
882 * @param[in] kw Type of current element.
883 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
884 * @param[in,out] exts Extension instances to add to.
885 *
886 * @return LY_ERR values.
887 */
888static LY_ERR
889yin_parse_qname(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
890 struct lysp_ext_instance **exts)
891{
892 struct lysp_qname *qname, **qnames;
893
894 switch (kw) {
895 case LY_STMT_DEFAULT:
896 if (subinfo->flags & YIN_SUBELEM_TEXT) {
897 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
898 return yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest, YIN_ARG_VALUE, Y_STR_ARG, exts);
899 } else {
900 return yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest, YIN_ARG_VALUE, Y_STR_ARG, exts);
901 }
902 } else {
903 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
904 qname = (struct lysp_qname *)subinfo->dest;
905 } else {
906 qnames = (struct lysp_qname **)subinfo->dest;
907 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
908 }
909 qname->mod = ctx->main_mod;
910 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
911 }
912 case LY_STMT_IF_FEATURE:
913 assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
914 if (subinfo->flags & YIN_SUBELEM_TEXT) {
915 return yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
916 } else {
917 qnames = (struct lysp_qname **)subinfo->dest;
918 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
919 qname->mod = ctx->main_mod;
920 return yin_parse_simple_element(ctx, kw, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
921 }
922 default:
923 break;
924 }
925
926 LOGINT(ctx->xmlctx->ctx);
927 return LY_EINT;
928}
929
930/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200931 * @brief Parse position or value element.
932 *
933 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200934 * @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 +0200935 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200936 *
937 * @return LY_ERR values.
938 */
939static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100940yin_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 +0200941{
Radek Krejcid6b76452019-09-03 17:03:03 +0200942 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200943 const char *temp_val = NULL;
944 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200945 long int num = 0;
946 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +0200947
948 /* set value flag */
949 enm->flags |= LYS_SET_VALUE;
950
951 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100952 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
953 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200954 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejci0f969882020-08-21 16:56:47 +0200955 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200956 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 +0200957 goto error;
958 }
959
960 /* convert value */
961 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200962 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200963 num = strtol(temp_val, &ptr, 10);
964 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200965 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200966 goto error;
967 }
968 } else {
969 unum = strtoul(temp_val, &ptr, 10);
970 if (unum > UINT64_C(4294967295)) {
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 }
975 /* check if whole argument value was converted */
976 if (*ptr != '\0') {
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ákebcd0eb2019-07-16 17:55:12 +0200978 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200979 }
980 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200981 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 +0200982 goto error;
983 }
984 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200985 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200986 enm->value = num;
987 } else {
988 enm->value = unum;
989 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100990 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200991
992 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200993 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +0200994 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
995 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100996 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200997
David Sedlákbf8a2b72019-08-14 16:48:10 +0200998error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100999 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1000 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +02001001}
1002
David Sedlák05404f62019-07-24 14:11:53 +02001003/**
1004 * @brief Parse belongs-to element.
1005 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001006 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001007 * @param[out] submod Structure of submodule that is being parsed.
1008 * @param[in,out] exts Extension instances to add to.
1009 *
1010 * @return LY_ERR values
1011 */
1012static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001013yin_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 +02001014{
Michal Vaskoc3781c32020-10-06 14:04:08 +02001015 const char *belongsto;
David Sedlák05404f62019-07-24 14:11:53 +02001016 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001017 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1018 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1019 };
David Sedlák05404f62019-07-24 14:11:53 +02001020
Michal Vaskob36053d2020-03-26 15:49:30 +01001021 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
Michal Vaskoc3781c32020-10-06 14:04:08 +02001022 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
1023 if (ctx->main_mod->name != belongsto) {
1024 LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
1025 belongsto, ctx->main_mod->name);
1026 lydict_remove(ctx->xmlctx->ctx, belongsto);
1027 return LY_EVALID;
1028 }
1029 lydict_remove(ctx->xmlctx->ctx, belongsto);
Michal Vaskob36053d2020-03-26 15:49:30 +01001030
1031 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +02001032}
1033
David Sedlák5545f5d2019-07-11 11:55:16 +02001034/**
David Sedlákc1771b12019-07-10 15:55:46 +02001035 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +02001036 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +02001037 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001038 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001039 * @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 +02001040 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001041 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +02001042 *
1043 * @return LY_ERR values.
1044 */
1045static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001046yin_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 +02001047{
Radek Krejcid6b76452019-09-03 17:03:03 +02001048 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 +02001049
David Sedlák968ac342019-07-11 15:17:59 +02001050 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001051 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1052 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1053 };
David Sedlákdf2a9732019-08-07 13:23:16 +02001054 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001055 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1056 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 +02001057
David Sedlákdf2a9732019-08-07 13:23:16 +02001058 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +01001059 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +02001060}
1061
1062/**
David Sedlákc1771b12019-07-10 15:55:46 +02001063 * @brief Parse error-message element.
1064 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001065 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +02001066 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001067 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +02001068 *
1069 * @return LY_ERR values.
1070 */
1071static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001072yin_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 +02001073{
David Sedlák968ac342019-07-11 15:17:59 +02001074 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001075 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1076 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1077 };
David Sedlákc1771b12019-07-10 15:55:46 +02001078
David Sedlákdf2a9732019-08-07 13:23:16 +02001079 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001080 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1081 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 +02001082
Michal Vaskob36053d2020-03-26 15:49:30 +01001083 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001084}
1085
1086/**
David Sedlák6542aed2019-08-14 10:47:43 +02001087 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001088 *
1089 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001090 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001091 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001092 *
1093 * @return LY_ERR values.
1094 */
1095static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001096yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001097{
David Sedlák6542aed2019-08-14 10:47:43 +02001098 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001099 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001100 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001101 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001102 type = *((struct lysp_type **)subinfo->dest);
Michal Vaskod989ba02020-08-24 10:59:24 +02001103 } else {
David Sedlák6542aed2019-08-14 10:47:43 +02001104 type = (struct lysp_type *)subinfo->dest;
1105 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001106
1107 type->mod = ctx->main_mod;
1108
David Sedlák6542aed2019-08-14 10:47:43 +02001109 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001110 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001111 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001112 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001113 type->flags |= LYS_SET_TYPE;
1114 type = nested_type;
1115 }
Michal Vaskoe9c050f2020-10-06 14:01:23 +02001116
David Sedlák374d2b32019-07-17 15:06:55 +02001117 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001118 {LY_STMT_BASE, type, 0},
1119 {LY_STMT_BIT, type, 0},
1120 {LY_STMT_ENUM, type, 0},
1121 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1122 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1123 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1124 {LY_STMT_PATTERN, type, 0},
1125 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1126 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1127 {LY_STMT_TYPE, type},
1128 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1129 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001130
1131 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1132 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1133 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001134}
1135
David Sedlák1af868e2019-07-17 17:03:14 +02001136/**
1137 * @brief Parse max-elements element.
1138 *
1139 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001140 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001141 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001142 * @param[in,out] exts Extension instances to add to.
1143 *
1144 * @return LY_ERR values.
1145 */
1146static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001147yin_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 +02001148{
1149 const char *temp_val = NULL;
1150 char *ptr;
1151 unsigned long int num;
1152 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001153 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1154 };
David Sedlák374d2b32019-07-17 15:06:55 +02001155
David Sedlák1af868e2019-07-17 17:03:14 +02001156 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001157 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1158 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
David Sedlák1af868e2019-07-17 17:03:14 +02001159 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 +02001160 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001161 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001162 return LY_EVALID;
1163 }
1164
1165 if (strcmp(temp_val, "unbounded")) {
1166 errno = 0;
1167 num = strtoul(temp_val, &ptr, 10);
1168 if (*ptr != '\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 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001174 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001175 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001176 return LY_EVALID;
1177 }
1178 *max = num;
1179 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001180 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1181 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001182}
David Sedlák374d2b32019-07-17 15:06:55 +02001183
1184/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001185 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001186 *
1187 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001188 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001189 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001190 * @param[in,out] exts Extension instances to add to.
1191 *
1192 * @return LY_ERR values.
1193 */
1194static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001195yin_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 +02001196{
1197 const char *temp_val = NULL;
1198 char *ptr;
1199 unsigned long int num;
1200 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001201 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1202 };
David Sedlák09e18c92019-07-18 11:17:11 +02001203
1204 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001205 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1206 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 +02001207
1208 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001209 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001210 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001211 return LY_EVALID;
1212 }
1213
1214 errno = 0;
1215 num = strtoul(temp_val, &ptr, 10);
1216 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001217 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001218 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001219 return LY_EVALID;
1220 }
1221 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001222 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001223 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001224 return LY_EVALID;
1225 }
1226 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001227 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1228 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001229}
1230
David Sedláka2dad212019-07-18 12:45:19 +02001231/**
1232 * @brief Parse min-elements or max-elements element.
1233 *
1234 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001235 * @param[in] parent Identification of parent element.
1236 * @param[in] current Identification of current element.
1237 * @param[in] dest Where the parsed value and flags should be stored.
1238 *
1239 * @return LY_ERR values.
1240 */
David Sedlák09e18c92019-07-18 11:17:11 +02001241static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001242yin_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 +02001243{
Radek Krejcid6b76452019-09-03 17:03:03 +02001244 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1245 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 +02001246 uint32_t *lim;
1247 uint16_t *flags;
1248 struct lysp_ext_instance **exts;
1249
Radek Krejcid6b76452019-09-03 17:03:03 +02001250 if (parent == LY_STMT_LEAF_LIST) {
1251 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 +02001252 flags = &((struct lysp_node_leaflist *)dest)->flags;
1253 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001254 } else if (parent == LY_STMT_REFINE) {
1255 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001256 flags = &((struct lysp_refine *)dest)->flags;
1257 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001258 } else if (parent == LY_STMT_LIST) {
1259 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 +02001260 flags = &((struct lysp_node_list *)dest)->flags;
1261 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001262 } else {
1263 lim = ((struct minmax_dev_meta *)dest)->lim;
1264 flags = ((struct minmax_dev_meta *)dest)->flags;
1265 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001266 }
1267
Radek Krejcid6b76452019-09-03 17:03:03 +02001268 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001269 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001270 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001271 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001272 }
1273
1274 return LY_SUCCESS;
1275}
1276
1277/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001278 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001279 *
1280 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001281 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001282 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001283 *
1284 * @return LY_ERR values.
1285 */
1286static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001287yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001288{
1289 const char *temp_val;
1290 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001291 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1292 };
David Sedláka2dad212019-07-18 12:45:19 +02001293
Michal Vaskob36053d2020-03-26 15:49:30 +01001294 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1295 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 +02001296 if (strcmp(temp_val, "system") == 0) {
1297 *flags |= LYS_ORDBY_SYSTEM;
1298 } else if (strcmp(temp_val, "user") == 0) {
1299 *flags |= LYS_ORDBY_USER;
1300 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001301 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1302 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001303 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001304 return LY_EVALID;
1305 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001306 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001307
Michal Vaskob36053d2020-03-26 15:49:30 +01001308 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001309}
1310
1311/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001312 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001313 *
1314 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001315 * @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 +02001316 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001317 *
1318 * @return LY_ERR values.
1319 */
1320static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001321yin_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 +02001322{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001323 struct lysp_node_anydata *any;
1324
David Sedlák8d552d62019-08-06 15:29:05 +02001325 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001326 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001327 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001328 any->parent = node_meta->parent;
1329
David Sedlákbf8a2b72019-08-14 16:48:10 +02001330 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001331 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1332 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 +02001333
1334 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001335 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1337 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1338 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1339 {LY_STMT_MUST, &any->musts, 0},
1340 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1341 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1342 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1343 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1344 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001345 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001346}
1347
1348/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001349 * @brief parse leaf element.
1350 *
1351 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001352 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001353 *
1354 * @return LY_ERR values.
1355 */
1356static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001357yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001358{
David Sedlák203ca3a2019-07-18 15:26:25 +02001359 struct lysp_node_leaf *leaf;
1360
David Sedlák8d552d62019-08-06 15:29:05 +02001361 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001362 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001363 leaf->nodetype = LYS_LEAF;
1364 leaf->parent = node_meta->parent;
1365
David Sedlák203ca3a2019-07-18 15:26:25 +02001366 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001367 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1368 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 +02001369
1370 /* parse content */
1371 struct yin_subelement subelems[12] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001372 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1373 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1374 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1375 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1376 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1377 {LY_STMT_MUST, &leaf->musts, 0},
1378 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1379 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1380 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1381 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1382 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1383 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1384 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001385 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001386}
1387
1388/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001389 * @brief Parse leaf-list element.
1390 *
1391 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001392 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001393 *
1394 * @return LY_ERR values.
1395 */
1396static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001397yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001398{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001399 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001400
Michal Vaskob36053d2020-03-26 15:49:30 +01001401 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001402
David Sedlákc3da3ef2019-07-19 12:56:08 +02001403 llist->nodetype = LYS_LEAFLIST;
1404 llist->parent = node_meta->parent;
1405
David Sedlákc3da3ef2019-07-19 12:56:08 +02001406 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001407 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1408 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 +02001409
1410 /* parse content */
1411 struct yin_subelement subelems[14] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001412 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1413 {LY_STMT_DEFAULT, &llist->dflts, 0},
1414 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1415 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1416 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1417 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1418 {LY_STMT_MUST, &llist->musts, 0},
1419 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1420 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1421 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1422 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1423 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1425 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1426 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001427 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001428
David Sedlákbf8a2b72019-08-14 16:48:10 +02001429 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001430 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001431 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001432 return LY_EVALID;
1433 }
1434 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001435 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001436 return LY_EVALID;
1437 }
1438
1439 return LY_SUCCESS;
1440}
1441
1442/**
David Sedlák04e17b22019-07-19 15:29:48 +02001443 * @brief Parse typedef element.
1444 *
1445 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001446 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001447 *
1448 * @return LY_ERR values.
1449 */
1450static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001451yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001452{
1453 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001454 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vaskob36053d2020-03-26 15:49:30 +01001455 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001456
1457 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001458 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1459 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
David Sedlák04e17b22019-07-19 15:29:48 +02001460
1461 /* parse content */
1462 struct yin_subelement subelems[7] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001463 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1464 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1466 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1467 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1468 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1469 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1470 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001471 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001472
1473 /* store data for collision check */
Michal Vasko7f45cf22020-10-01 12:49:44 +02001474 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INPUT
1475 | LYS_OUTPUT | LYS_NOTIF))) {
Radek Krejciba03a5a2020-08-27 14:40:41 +02001476 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
David Sedlák04e17b22019-07-19 15:29:48 +02001477 }
1478
1479 return LY_SUCCESS;
1480}
1481
1482/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001483 * @brief Parse refine element.
1484 *
1485 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001486 * @param[in,out] refines Refines to add to.
1487 *
1488 * @return LY_ERR values.
1489 */
1490static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001491yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001492{
1493 struct lysp_refine *rf;
1494
1495 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001496 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001497
1498 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001499 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1500 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1501 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001502
1503 /* parse content */
1504 struct yin_subelement subelems[11] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001505 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02001506 {LY_STMT_DEFAULT, &rf->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02001507 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02001508 {LY_STMT_IF_FEATURE, &rf->iffeatures, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02001509 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1511 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1512 {LY_STMT_MUST, &rf->musts, 0},
1513 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1514 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1515 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1516 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001517 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001518}
1519
1520/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001521 * @brief Parse uses element.
1522 *
1523 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001524 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001525 *
1526 * @return LY_ERR values.
1527 */
1528static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001529yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001530{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001531 struct lysp_node_uses *uses;
1532
David Sedlák8d552d62019-08-06 15:29:05 +02001533 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001534 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001535 uses->nodetype = LYS_USES;
1536 uses->parent = node_meta->parent;
1537
David Sedlák0d6de5a2019-07-22 13:25:44 +02001538 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001539 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1540 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 +02001541
1542 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001543 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001544 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001545 {LY_STMT_AUGMENT, &augments, 0},
1546 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1547 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1548 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1549 {LY_STMT_REFINE, &uses->refines, 0},
1550 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1551 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1552 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1553 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001554 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001555 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1556
1557 return LY_SUCCESS;
1558}
1559
1560/**
David Sedlákaa854b02019-07-22 14:17:10 +02001561 * @brief Parse revision element.
1562 *
1563 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001564 * @param[in,out] revs Parsed revisions to add to.
1565 *
1566 * @return LY_ERR values.
1567 */
1568static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001569yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001570{
1571 struct lysp_revision *rev;
1572 const char *temp_date = NULL;
1573
1574 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001575 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001576
1577 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001578 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1579 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 +02001580 /* check value */
1581 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001582 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001583 return LY_EVALID;
1584 }
1585 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001586 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001587
1588 /* parse content */
1589 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001590 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1591 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1592 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1593 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001594 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001595}
1596
David Sedlák5e13dea2019-07-22 16:06:45 +02001597/**
1598 * @brief Parse include element.
1599 *
1600 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001601 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1602 *
1603 * @return LY_ERR values.
1604 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001605static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001606yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001607{
1608 struct lysp_include *inc;
1609
1610 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001611 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001612
1613 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001614 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1615 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 +02001616
1617 /* submodules share the namespace with the module names, so there must not be
1618 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001619 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 +02001620 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001621 return LY_EVALID;
1622 }
1623
1624 /* parse content */
1625 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001626 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1627 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1628 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1629 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1630 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001631 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001632}
1633
David Sedlákaa854b02019-07-22 14:17:10 +02001634/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001635 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001636 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001637 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001638 * @param[in,out] rev Array to store the parsed value in.
1639 * @param[in,out] exts Extension instances to add to.
1640 *
1641 * @return LY_ERR values.
1642 */
1643static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001644yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001645{
1646 const char *temp_rev;
1647 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001648 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1649 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001650
Michal Vaskob36053d2020-03-26 15:49:30 +01001651 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1652 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 +02001653 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
Michal Vaskob36053d2020-03-26 15:49:30 +01001654 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001655
1656 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001657 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001658
Michal Vaskob36053d2020-03-26 15:49:30 +01001659 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001660}
1661
1662/**
1663 * @brief Parse config element.
1664 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001665 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001666 * @param[in,out] flags Flags to add to.
1667 * @param[in,out] exts Extension instances to add to.
1668 *
1669 * @return LY_ERR values.
1670 */
1671static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001672yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001673{
1674 const char *temp_val = NULL;
1675 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001676 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1677 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001678
Michal Vaskob36053d2020-03-26 15:49:30 +01001679 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1680 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 +02001681 if (strcmp(temp_val, "true") == 0) {
1682 *flags |= LYS_CONFIG_W;
1683 } else if (strcmp(temp_val, "false") == 0) {
1684 *flags |= LYS_CONFIG_R;
1685 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001686 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1687 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001688 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001689 return LY_EVALID;
1690 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001691 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001692
Michal Vaskob36053d2020-03-26 15:49:30 +01001693 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001694}
1695
1696/**
1697 * @brief Parse yang-version element.
1698 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001699 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001700 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001701 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001702 *
1703 * @return LY_ERR values.
1704 */
1705static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001706yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001707{
1708 const char *temp_version = NULL;
1709 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001710 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1711 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001712
Michal Vaskob36053d2020-03-26 15:49:30 +01001713 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1714 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 +02001715 if (strcmp(temp_version, "1") == 0) {
David Sedlákdfbbb442019-08-06 16:33:21 +02001716 *version = LYS_VERSION_1_0;
1717 } else if (strcmp(temp_version, "1.1") == 0) {
1718 *version = LYS_VERSION_1_1;
1719 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001720 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
Radek Krejci96e48da2020-09-04 13:18:06 +02001721 "yang-version", "1", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001722 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001723 return LY_EVALID;
1724 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001725 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001726 ctx->mod_version = *version;
1727
Michal Vaskob36053d2020-03-26 15:49:30 +01001728 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001729}
1730
1731/**
1732 * @brief Parse import element.
1733 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001734 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001735 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1736 *
1737 * @return LY_ERR values.
1738 */
1739static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001740yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001741{
1742 struct lysp_import *imp;
1743 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001744 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001745
1746 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001747 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1748 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1749 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1750 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1751 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1752 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001753
1754 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001755 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1756 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1757 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001758 /* check prefix validity */
1759 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1760
1761 return LY_SUCCESS;
1762}
1763
1764/**
1765 * @brief Parse mandatory element.
1766 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001767 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001768 * @param[in,out] flags Flags to add to.
1769 * @param[in,out] exts Extension instances to add to.
1770 *
1771 * @return LY_ERR values.
1772 */
1773static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001774yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001775{
1776 const char *temp_val = NULL;
1777 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001778 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1779 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001780
Michal Vaskob36053d2020-03-26 15:49:30 +01001781 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1782 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MANDATORY));
David Sedlákdfbbb442019-08-06 16:33:21 +02001783 if (strcmp(temp_val, "true") == 0) {
1784 *flags |= LYS_MAND_TRUE;
1785 } else if (strcmp(temp_val, "false") == 0) {
1786 *flags |= LYS_MAND_FALSE;
1787 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001788 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1789 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001790 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001791 return LY_EVALID;
1792 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001793 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001794
Michal Vaskob36053d2020-03-26 15:49:30 +01001795 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001796}
1797
1798/**
1799 * @brief Parse status element.
1800 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001801 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001802 * @param[in,out] flags Flags to add to.
1803 * @param[in,out] exts Extension instances to add to.
1804 *
1805 * @return LY_ERR values.
1806 */
1807static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001808yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001809{
1810 const char *value = NULL;
1811 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001812 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1813 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001814
Michal Vaskob36053d2020-03-26 15:49:30 +01001815 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1816 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 +02001817 if (strcmp(value, "current") == 0) {
1818 *flags |= LYS_STATUS_CURR;
1819 } else if (strcmp(value, "deprecated") == 0) {
1820 *flags |= LYS_STATUS_DEPRC;
1821 } else if (strcmp(value, "obsolete") == 0) {
1822 *flags |= LYS_STATUS_OBSLT;
1823 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001824 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1825 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001826 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001827 return LY_EVALID;
1828 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001829 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001830
Michal Vaskob36053d2020-03-26 15:49:30 +01001831 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001832}
1833
1834/**
1835 * @brief Parse when element.
1836 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001837 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001838 * @param[out] when_p When pointer to parse to.
1839 */
1840static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001841yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001842{
1843 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001844 LY_ERR ret = LY_SUCCESS;
1845
David Sedlákdfbbb442019-08-06 16:33:21 +02001846 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001847 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001848
1849 ret = lyxml_ctx_next(ctx->xmlctx);
1850 LY_CHECK_ERR_RET(ret, free(when), ret);
1851
Michal Vaskob36053d2020-03-26 15:49:30 +01001852 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001853 LY_CHECK_ERR_RET(ret, free(when), ret);
1854
David Sedlákdfbbb442019-08-06 16:33:21 +02001855 *when_p = when;
1856 struct yin_subelement subelems[3] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001857 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1858 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1859 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1860 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001861
Michal Vaskob36053d2020-03-26 15:49:30 +01001862 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001863}
1864
1865/**
1866 * @brief Parse yin-elemenet element.
1867 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001868 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001869 * @param[in,out] data Data to read from, always moved to currently handled position.
1870 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001871 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001872 *
1873 * @return LY_ERR values.
1874 */
1875static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001876yin_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 +02001877{
1878 const char *temp_val = NULL;
1879 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001880 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1881 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001882
Michal Vaskob36053d2020-03-26 15:49:30 +01001883 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1884 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_YIN_ELEMENT));
David Sedlákdfbbb442019-08-06 16:33:21 +02001885 if (strcmp(temp_val, "true") == 0) {
1886 *flags |= LYS_YINELEM_TRUE;
1887 } else if (strcmp(temp_val, "false") == 0) {
1888 *flags |= LYS_YINELEM_FALSE;
1889 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001890 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1891 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001892 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001893 return LY_EVALID;
1894 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001895 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001896
Michal Vaskob36053d2020-03-26 15:49:30 +01001897 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001898}
1899
1900/**
1901 * @brief Parse argument element.
1902 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001903 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001904 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1905 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001906 *
1907 * @return LY_ERR values.
1908 */
1909static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001910yin_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 +02001911{
1912 struct yin_subelement subelems[2] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001913 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1914 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1915 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001916
Michal Vaskob36053d2020-03-26 15:49:30 +01001917 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1918 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 +02001919
Michal Vaskob36053d2020-03-26 15:49:30 +01001920 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001921}
1922
1923/**
1924 * @brief Parse the extension statement.
1925 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001926 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001927 * @param[in,out] extensions Extensions to add to.
1928 *
1929 * @return LY_ERR values.
1930 */
1931static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001932yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001933{
1934 struct lysp_ext *ex;
Michal Vaskob36053d2020-03-26 15:49:30 +01001935 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1936 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1937 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 +02001938
1939 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1940 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001941 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1942 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1943 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1944 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1945 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1946 };
David Sedlákdfbbb442019-08-06 16:33:21 +02001947
Michal Vaskob36053d2020-03-26 15:49:30 +01001948 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001949}
1950
1951/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001952 * @brief Parse feature element.
1953 *
1954 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001955 * @param[in,out] features Features to add to.
1956 *
1957 * @return LY_ERR values.
1958 */
1959static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001960yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001961{
1962 struct lysp_feature *feat;
1963
1964 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001965 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001966
1967 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001968 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1969 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 +02001970
1971 /* parse content */
1972 struct yin_subelement subelems[5] = {
Radek Krejci0f969882020-08-21 16:56:47 +02001973 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1974 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1975 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1976 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1977 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1978 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001979 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001980}
1981
1982/**
David Sedlák28794f22019-07-22 16:45:00 +02001983 * @brief Parse identity element.
1984 *
1985 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001986 * @param[in,out] identities Identities to add to.
1987 *
1988 * @return LY_ERR values.
1989 */
1990static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001991yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02001992{
1993 struct lysp_ident *ident;
1994
1995 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01001996 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02001997
1998 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001999 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2000 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 +02002001
2002 /* parse content */
2003 struct yin_subelement subelems[6] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002004 {LY_STMT_BASE, &ident->bases, 0},
2005 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2006 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2007 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2008 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2009 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2010 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002011 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02002012}
2013
2014/**
David Sedlákaf536aa2019-07-23 13:42:23 +02002015 * @brief Parse list element.
2016 *
2017 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002018 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02002019 *
2020 * @return LY_ERR values.
2021 */
2022static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002023yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02002024{
David Sedlákaf536aa2019-07-23 13:42:23 +02002025 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02002026 LY_ERR ret = LY_SUCCESS;
2027 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02002028
Michal Vaskob36053d2020-03-26 15:49:30 +01002029 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02002030 list->nodetype = LYS_LIST;
2031 list->parent = node_meta->parent;
2032
David Sedlákaf536aa2019-07-23 13:42:23 +02002033 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002034 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2035 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 +02002036
2037 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02002038 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002039 LY_STMT_ACTION, &list->actions, 0,
2040 LY_STMT_ANYDATA, &list->child, 0,
2041 LY_STMT_ANYXML, &list->child, 0,
2042 LY_STMT_CHOICE, &list->child, 0,
2043 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2044 LY_STMT_CONTAINER, &list->child, 0,
2045 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2046 LY_STMT_GROUPING, &list->groupings, 0,
2047 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2048 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2049 LY_STMT_LEAF, &list->child, 0,
2050 LY_STMT_LEAF_LIST, &list->child, 0,
2051 LY_STMT_LIST, &list->child, 0,
2052 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2053 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2054 LY_STMT_MUST, &list->musts, 0,
2055 LY_STMT_NOTIFICATION, &list->notifs, 0,
2056 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2057 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2058 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2059 LY_STMT_TYPEDEF, &list->typedefs, 0,
2060 LY_STMT_UNIQUE, &list->uniques, 0,
2061 LY_STMT_USES, &list->child, 0,
2062 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2063 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002064 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002065 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002066 subelems_deallocator(25, subelems);
2067 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02002068
2069 /* finalize parent pointers to the reallocated items */
2070 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
2071
2072 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02002073 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02002074 return LY_EVALID;
2075 }
2076
2077 return LY_SUCCESS;
2078}
2079
2080/**
David Sedlák031b9e72019-07-23 15:19:37 +02002081 * @brief Parse notification element.
2082 *
2083 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002084 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002085 *
2086 * @return LY_ERR values.
2087 */
2088static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002089yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002090{
2091 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002092 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002093 LY_ERR ret = LY_SUCCESS;
2094 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002095
2096 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002097 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002098 notif->nodetype = LYS_NOTIF;
2099 notif->parent = notif_meta->parent;
2100
2101 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002102 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2103 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 +02002104
2105 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002106 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002107 LY_STMT_ANYDATA, &notif->data, 0,
2108 LY_STMT_ANYXML, &notif->data, 0,
2109 LY_STMT_CHOICE, &notif->data, 0,
2110 LY_STMT_CONTAINER, &notif->data, 0,
2111 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2112 LY_STMT_GROUPING, &notif->groupings, 0,
2113 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2114 LY_STMT_LEAF, &notif->data, 0,
2115 LY_STMT_LEAF_LIST, &notif->data, 0,
2116 LY_STMT_LIST, &notif->data, 0,
2117 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2118 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2119 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2120 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2121 LY_STMT_USES, &notif->data, 0,
2122 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002123 ));
2124
Michal Vaskob36053d2020-03-26 15:49:30 +01002125 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002126 subelems_deallocator(16, subelems);
2127 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002128
2129 /* finalize parent pointers to the reallocated items */
2130 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2131
2132 return LY_SUCCESS;
2133}
2134
2135/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002136 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002137 *
2138 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002139 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002140 *
2141 * @return LY_ERR values.
2142 */
2143static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002144yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002145{
2146 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002147 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002148 LY_ERR ret = LY_SUCCESS;
2149 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002150
2151 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002152 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002153 grp->nodetype = LYS_GROUPING;
2154 grp->parent = gr_meta->parent;
2155
2156 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002157 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2158 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 +02002159
2160 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002161 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002162 LY_STMT_ACTION, &grp->actions, 0,
2163 LY_STMT_ANYDATA, &grp->data, 0,
2164 LY_STMT_ANYXML, &grp->data, 0,
2165 LY_STMT_CHOICE, &grp->data, 0,
2166 LY_STMT_CONTAINER, &grp->data, 0,
2167 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2168 LY_STMT_GROUPING, &grp->groupings, 0,
2169 LY_STMT_LEAF, &grp->data, 0,
2170 LY_STMT_LEAF_LIST, &grp->data, 0,
2171 LY_STMT_LIST, &grp->data, 0,
2172 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2173 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2174 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2175 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2176 LY_STMT_USES, &grp->data, 0,
2177 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002178 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002179 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002180 subelems_deallocator(16, subelems);
2181 LY_CHECK_RET(ret);
2182
David Sedláke3ce9ef2019-07-23 16:34:30 +02002183 /* finalize parent pointers to the reallocated items */
2184 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2185
2186 return LY_SUCCESS;
2187}
2188
2189/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002190 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002191 *
2192 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002193 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002194 *
2195 * @return LY_ERR values.
2196 */
2197static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002198yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002199{
David Sedlákf111bcb2019-07-23 17:15:51 +02002200 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002201 LY_ERR ret = LY_SUCCESS;
2202 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002203
2204 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002205 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002206 cont->nodetype = LYS_CONTAINER;
2207 cont->parent = node_meta->parent;
2208
David Sedlákf111bcb2019-07-23 17:15:51 +02002209 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002210 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2211 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 +02002212
2213 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002214 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002215 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2216 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2217 LY_STMT_ANYXML, &cont->child, 0,
2218 LY_STMT_CHOICE, &cont->child, 0,
2219 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2220 LY_STMT_CONTAINER, &cont->child, 0,
2221 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2222 LY_STMT_GROUPING, &cont->groupings, 0,
2223 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2224 LY_STMT_LEAF, &cont->child, 0,
2225 LY_STMT_LEAF_LIST, &cont->child, 0,
2226 LY_STMT_LIST, &cont->child, 0,
2227 LY_STMT_MUST, &cont->musts, 0,
2228 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2229 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2230 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2231 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2232 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2233 LY_STMT_USES, &cont->child, 0,
2234 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2235 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002236 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002237 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002238 subelems_deallocator(21, subelems);
2239 LY_CHECK_RET(ret);
2240
David Sedlákf111bcb2019-07-23 17:15:51 +02002241 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2242
2243 return LY_SUCCESS;
2244}
2245
2246/**
David Sedlák5379d392019-07-24 10:42:03 +02002247 * @brief Parse case element.
2248 *
2249 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002250 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002251 *
2252 * @return LY_ERR values.
2253 */
2254static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002255yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002256{
David Sedlák5379d392019-07-24 10:42:03 +02002257 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002258 LY_ERR ret = LY_SUCCESS;
2259 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002260
2261 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002262 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002263 cas->nodetype = LYS_CASE;
2264 cas->parent = node_meta->parent;
2265
David Sedlák5379d392019-07-24 10:42:03 +02002266 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002267 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2268 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 +02002269
2270 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002271 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002272 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2273 LY_STMT_ANYXML, &cas->child, 0,
2274 LY_STMT_CHOICE, &cas->child, 0,
2275 LY_STMT_CONTAINER, &cas->child, 0,
2276 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2277 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2278 LY_STMT_LEAF, &cas->child, 0,
2279 LY_STMT_LEAF_LIST, &cas->child, 0,
2280 LY_STMT_LIST, &cas->child, 0,
2281 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2282 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2283 LY_STMT_USES, &cas->child, 0,
2284 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2285 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002286 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002287 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002288 subelems_deallocator(14, subelems);
2289
2290 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002291}
2292
2293/**
David Sedlák05404f62019-07-24 14:11:53 +02002294 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002295 *
2296 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002297 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002298 *
2299 * @return LY_ERR values.
2300 */
2301LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002302yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002303{
David Sedlák81497a32019-08-13 16:56:26 +02002304 LY_ERR ret = LY_SUCCESS;
2305 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002306 struct lysp_node_choice *choice;
2307
2308 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002309 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002310
David Sedlákb7abcfa2019-07-24 12:33:35 +02002311 choice->nodetype = LYS_CHOICE;
2312 choice->parent = node_meta->parent;
2313
David Sedlákb7abcfa2019-07-24 12:33:35 +02002314 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002315 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2316 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 +02002317
2318 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002319 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002320 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2321 LY_STMT_ANYXML, &choice->child, 0,
2322 LY_STMT_CASE, &choice->child, 0,
2323 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2324 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2325 LY_STMT_CONTAINER, &choice->child, 0,
2326 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2327 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2328 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2329 LY_STMT_LEAF, &choice->child, 0,
2330 LY_STMT_LEAF_LIST, &choice->child, 0,
2331 LY_STMT_LIST, &choice->child, 0,
2332 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2333 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2334 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2335 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2336 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002337 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002338 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002339 subelems_deallocator(17, subelems);
2340 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002341}
2342
2343/**
David Sedlák05404f62019-07-24 14:11:53 +02002344 * @brief Parse input or output element.
2345 *
2346 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002347 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002348 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2349 *
2350 * @return LY_ERR values.
2351 */
2352static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002353yin_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 +02002354{
David Sedlák81497a32019-08-13 16:56:26 +02002355 LY_ERR ret = LY_SUCCESS;
2356 struct yin_subelement *subelems = NULL;
2357
David Sedlák05404f62019-07-24 14:11:53 +02002358 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002359 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002360 inout_meta->inout_p->parent = inout_meta->parent;
2361
2362 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002363 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2364 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 +02002365
2366 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002367 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002368 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2369 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2370 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2371 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2372 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2373 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2374 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2375 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2376 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2377 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2378 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2379 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002380 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002381 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002382 subelems_deallocator(12, subelems);
2383 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002384
Michal Vaskob83af8a2020-01-06 09:49:22 +01002385 if (!inout_meta->inout_p->data) {
2386 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2387 return LY_EVALID;
2388 }
2389
David Sedlák05404f62019-07-24 14:11:53 +02002390 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002391 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 +02002392
2393 return LY_SUCCESS;
2394}
2395
David Sedlák992fb7c2019-07-24 16:51:01 +02002396/**
2397 * @brief Parse action element.
2398 *
2399 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002400 * @param[in] act_meta Meta information about parent node and actions to add to.
2401 *
2402 * @return LY_ERR values.
2403 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002404static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002405yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002406{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002407 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002408 LY_ERR ret = LY_SUCCESS;
2409 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002410
2411 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002412 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002413 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002414 act->parent = act_meta->parent;
2415
2416 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002417 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2418 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 +02002419
2420 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002421 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002422 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2423 LY_STMT_GROUPING, &act->groupings, 0,
2424 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2425 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2426 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2427 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2428 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2429 LY_STMT_TYPEDEF, &act->typedefs, 0,
2430 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002431 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002432 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002433 subelems_deallocator(9, subelems);
2434 LY_CHECK_RET(ret);
2435
Michal Vasko7f45cf22020-10-01 12:49:44 +02002436 /* always initialize inout, they are technically present (needed for later deviations/refines) */
2437 if (!act->input.nodetype) {
2438 act->input.nodetype = LYS_INPUT;
2439 act->input.parent = (struct lysp_node *)act;
2440 }
2441 if (!act->output.nodetype) {
2442 act->output.nodetype = LYS_OUTPUT;
2443 act->output.parent = (struct lysp_node *)act;
2444 }
2445
David Sedlák85d0eca2019-07-24 15:15:21 +02002446 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2447
2448 return LY_SUCCESS;
2449}
2450
David Sedlák05404f62019-07-24 14:11:53 +02002451/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002452 * @brief Parse augment element.
2453 *
2454 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002455 * @param[in] aug_meta Meta information about parent node and augments to add to.
2456 *
2457 * @return LY_ERR values.
2458 */
2459static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002460yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002461{
2462 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002463 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002464 LY_ERR ret = LY_SUCCESS;
2465 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002466
2467 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002468 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002469 aug->nodetype = LYS_AUGMENT;
2470 aug->parent = aug_meta->parent;
2471
2472 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002473 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2474 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2475 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002476
2477 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002478 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002479 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2480 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2481 LY_STMT_ANYXML, &aug->child, 0,
2482 LY_STMT_CASE, &aug->child, 0,
2483 LY_STMT_CHOICE, &aug->child, 0,
2484 LY_STMT_CONTAINER, &aug->child, 0,
2485 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
Michal Vasko7f45cf22020-10-01 12:49:44 +02002486 LY_STMT_IF_FEATURE, &aug->iffeatures, YIN_SUBELEM_TEXT,
Radek Krejcid6b76452019-09-03 17:03:03 +02002487 LY_STMT_LEAF, &aug->child, 0,
2488 LY_STMT_LEAF_LIST, &aug->child, 0,
2489 LY_STMT_LIST, &aug->child, 0,
2490 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2491 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2492 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2493 LY_STMT_USES, &aug->child, 0,
2494 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2495 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002496 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002497 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002498 subelems_deallocator(17, subelems);
2499 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002500
2501 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2502
2503 return LY_SUCCESS;
2504}
2505
David Sedlák8b754462019-07-25 16:22:13 +02002506/**
2507 * @brief Parse deviate element.
2508 *
2509 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002510 * @param[in] deviates Deviates to add to.
2511 *
2512 * @return LY_ERR values.
2513 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002514static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002515yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002516{
2517 LY_ERR ret = LY_SUCCESS;
2518 uint8_t dev_mod;
2519 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002520 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002521 struct lysp_deviate_add *d_add = NULL;
2522 struct lysp_deviate_rpl *d_rpl = NULL;
2523 struct lysp_deviate_del *d_del = NULL;
2524
2525 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002526 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2527 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_DEVIATE));
David Sedlák4ffcec82019-07-25 15:10:21 +02002528
2529 if (strcmp(temp_val, "not-supported") == 0) {
2530 dev_mod = LYS_DEV_NOT_SUPPORTED;
2531 } else if (strcmp(temp_val, "add") == 0) {
2532 dev_mod = LYS_DEV_ADD;
2533 } else if (strcmp(temp_val, "replace") == 0) {
2534 dev_mod = LYS_DEV_REPLACE;
2535 } else if (strcmp(temp_val, "delete") == 0) {
2536 dev_mod = LYS_DEV_DELETE;
2537 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002538 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2539 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002540 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002541 return LY_EVALID;
2542 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002543 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002544
2545 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2546 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002547 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002548 struct yin_subelement subelems[1] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002549 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2550 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002551 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002552
2553 } else if (dev_mod == LYS_DEV_ADD) {
2554 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002555 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002556 d = (struct lysp_deviate *)d_add;
2557 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2558 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2559 struct yin_subelement subelems[9] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002560 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02002561 {LY_STMT_DEFAULT, &d_add->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002562 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2563 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2564 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2565 {LY_STMT_MUST, &d_add->musts, 0},
2566 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2567 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2568 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2569 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002570 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002571
2572 } else if (dev_mod == LYS_DEV_REPLACE) {
2573 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002574 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002575 d = (struct lysp_deviate *)d_rpl;
2576 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2577 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2578 struct yin_subelement subelems[8] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002579 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
Michal Vasko7f45cf22020-10-01 12:49:44 +02002580 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002581 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2582 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2583 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2584 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2585 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2586 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2587 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002588 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002589
2590 } else {
2591 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002592 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002593 d = (struct lysp_deviate *)d_del;
2594 struct yin_subelement subelems[5] = {
Michal Vasko7f45cf22020-10-01 12:49:44 +02002595 {LY_STMT_DEFAULT, &d_del->dflts, YIN_SUBELEM_TEXT},
Radek Krejci0f969882020-08-21 16:56:47 +02002596 {LY_STMT_MUST, &d_del->musts, 0},
2597 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2598 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2599 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2600 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002601 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002602 }
2603 LY_CHECK_GOTO(ret, cleanup);
2604
2605 d->mod = dev_mod;
2606 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002607 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002608
2609 return ret;
2610
2611cleanup:
2612 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002613 return ret;
2614}
2615
David Sedlák992fb7c2019-07-24 16:51:01 +02002616/**
David Sedlák8b754462019-07-25 16:22:13 +02002617 * @brief Parse deviation element.
2618 *
2619 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002620 * @param[in] deviations Deviations to add to.
2621 *
2622 * @return LY_ERR values.
2623 */
2624static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002625yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002626{
2627 struct lysp_deviation *dev;
2628
2629 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002630 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002631
2632 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002633 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2634 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2635 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002636 struct yin_subelement subelems[4] = {
Radek Krejci0f969882020-08-21 16:56:47 +02002637 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2638 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2639 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2640 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2641 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002642 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002643}
2644
2645/**
David Sedlákb4e44562019-07-04 15:42:12 +02002646 * @brief Map keyword type to substatement info.
2647 *
2648 * @param[in] kw Keyword type.
2649 *
2650 * @return correct LYEXT_SUBSTMT information.
2651 */
2652static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002653kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002654{
2655 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002656 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002657 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002658 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002659 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002660 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002661 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002662 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002663 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002664 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002665 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002666 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002667 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002668 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002669 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002670 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002671 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002672 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002673 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002674 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002675 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002676 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002677 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002678 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002679 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002680 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002681 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002682 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002683 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002684 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002685 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002686 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002687 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002688 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002689 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002690 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002691 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002692 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002693 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002694 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002695 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002696 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002697 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002698 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002699 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002700 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002701 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002702 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002703 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002704 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002705 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002706 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002707 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002708 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002709 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002710 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002711 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002712 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002713 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002714 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002715 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002716 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002717 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002718 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002719 return LYEXT_SUBSTMT_IFFEATURE;
2720 default:
2721 return LYEXT_SUBSTMT_SELF;
2722 }
2723}
2724
David Sedlákc5b20842019-08-13 10:18:31 +02002725/**
2726 * @brief map keyword to keyword-group.
2727 *
2728 * @param[in] ctx YIN parser context used for logging.
2729 * @param[in] kw Keyword that is child of module or submodule.
2730 * @param[out] group Group of keyword.
2731 *
2732 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2733 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002734static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002735kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002736{
2737 switch (kw) {
Radek Krejci0f969882020-08-21 16:56:47 +02002738 /* module header */
2739 case LY_STMT_NONE:
2740 case LY_STMT_NAMESPACE:
2741 case LY_STMT_PREFIX:
2742 case LY_STMT_BELONGS_TO:
2743 case LY_STMT_YANG_VERSION:
2744 *group = Y_MOD_MODULE_HEADER;
2745 break;
2746 /* linkage */
2747 case LY_STMT_INCLUDE:
2748 case LY_STMT_IMPORT:
2749 *group = Y_MOD_LINKAGE;
2750 break;
2751 /* meta */
2752 case LY_STMT_ORGANIZATION:
2753 case LY_STMT_CONTACT:
2754 case LY_STMT_DESCRIPTION:
2755 case LY_STMT_REFERENCE:
2756 *group = Y_MOD_META;
2757 break;
2758 /* revision */
2759 case LY_STMT_REVISION:
2760 *group = Y_MOD_REVISION;
2761 break;
2762 /* body */
2763 case LY_STMT_ANYDATA:
2764 case LY_STMT_ANYXML:
2765 case LY_STMT_AUGMENT:
2766 case LY_STMT_CHOICE:
2767 case LY_STMT_CONTAINER:
2768 case LY_STMT_DEVIATION:
2769 case LY_STMT_EXTENSION:
2770 case LY_STMT_FEATURE:
2771 case LY_STMT_GROUPING:
2772 case LY_STMT_IDENTITY:
2773 case LY_STMT_LEAF:
2774 case LY_STMT_LEAF_LIST:
2775 case LY_STMT_LIST:
2776 case LY_STMT_NOTIFICATION:
2777 case LY_STMT_RPC:
2778 case LY_STMT_TYPEDEF:
2779 case LY_STMT_USES:
2780 case LY_STMT_EXTENSION_INSTANCE:
2781 *group = Y_MOD_BODY;
2782 break;
2783 default:
2784 LOGINT(ctx->xmlctx->ctx);
2785 return LY_EINT;
David Sedláke6cd89e2019-08-07 12:46:02 +02002786 }
2787
2788 return LY_SUCCESS;
2789}
2790
David Sedlákc5b20842019-08-13 10:18:31 +02002791/**
2792 * @brief Check if relative order of two keywords is valid.
2793 *
2794 * @param[in] ctx YIN parser context used for logging.
2795 * @param[in] kw Current keyword.
2796 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002797 * @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 +02002798 * because relative order is required only in module and submodule sub-elements, used for logging.
2799 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002800 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002801 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002802static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002803yin_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 +02002804{
Radek Krejcid6b76452019-09-03 17:03:03 +02002805 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002806 enum yang_module_stmt gr, next_gr;
2807
2808 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2809 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2810
2811 if (gr > next_gr) {
2812 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2813 return LY_EVALID;
2814 }
2815
2816 return LY_SUCCESS;
2817}
2818
David Sedlákc5dd0942019-09-13 10:23:59 +02002819/**
2820 * @brief Get element name prefixed by full URI of xml namespace.
2821 *
2822 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2823 * @param[in] name Name of element.
2824 * @param[in] name_len Length of element name.
2825 * @param[in] prefix Prefix of element.
2826 * @param[in] prefix_len Length of element prefix.
2827 *
2828 * @return Element name prefixed by URI on success, NULL on failure.
2829 */
2830static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002831name2nsname(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 +02002832{
Radek Krejci011e4aa2020-09-04 15:22:31 +02002833 const char *ename = NULL;
Michal Vaskoc8a230d2020-08-14 12:17:10 +02002834 const struct lyxml_ns *ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
Radek Krejci011e4aa2020-09-04 15:22:31 +02002835
Michal Vaskob36053d2020-03-26 15:49:30 +01002836 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002837
Radek Krejci02728562019-09-18 14:13:05 +02002838 if (!strcmp(ns->uri, YIN_NS_URI)) {
2839 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Radek Krejci011e4aa2020-09-04 15:22:31 +02002840 lydict_insert(ctx->xmlctx->ctx, name, name_len, &ename);
2841 return ename;
Radek Krejci02728562019-09-18 14:13:05 +02002842 }
2843 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002844 size_t ns_len = strlen(ns->uri);
2845 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2846
2847 char *result;
2848 char *temp;
2849 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002850 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002851
2852 strcpy(result, ns->uri);
2853 result[ns_len] = ':';
2854 temp = &result[ns_len + 1];
2855 strncpy(temp, name, name_len);
2856 result[len] = '\0';
2857
Radek Krejci011e4aa2020-09-04 15:22:31 +02002858 lydict_insert_zc(ctx->xmlctx->ctx, result, &ename);
2859 return ename;
David Sedlák068dd352019-09-13 09:08:22 +02002860}
2861
David Sedlákd6e56892019-07-01 15:40:24 +02002862LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002863yin_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 +02002864 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002865{
2866 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002867 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002868 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002869 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002870
Michal Vaskob36053d2020-03-26 15:49:30 +01002871 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002872
Michal Vaskob36053d2020-03-26 15:49:30 +01002873 if (ctx->xmlctx->ws_only) {
2874 /* check whether there are any children */
2875 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2876 } else {
2877 /* we want to parse the value */
2878 next_status = LYXML_ELEM_CLOSE;
2879 }
2880
2881 if (next_status == LYXML_ELEMENT) {
2882 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2883
2884 /* current element has subelements as content */
2885 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2886 /* match keyword */
2887 last_kw = kw;
2888 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
2889 ctx->xmlctx->prefix_len, current_element);
2890
2891 /* check if this element can be child of current element */
2892 subelem = get_record(kw, subelem_info_size, subelem_info);
2893 if (!subelem) {
2894 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
2895 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2896 } else {
2897 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
2898 ctx->xmlctx->name, ly_stmt2str(current_element));
2899 }
2900 ret = LY_EVALID;
2901 goto cleanup;
2902 }
2903
2904 /* relative order is required only in module and submodule sub-elements */
2905 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
2906 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2907 LY_CHECK_GOTO(ret, cleanup);
2908 }
2909
2910 /* flag check */
2911 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2912 /* subelement uniquenes */
2913 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2914 return LY_EVALID;
2915 }
2916 if (subelem->flags & YIN_SUBELEM_FIRST) {
2917 /* subelement is supposed to be defined as first subelement */
2918 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2919 LY_CHECK_GOTO(ret, cleanup);
2920 }
2921 if (subelem->flags & YIN_SUBELEM_VER2) {
2922 /* subelement is supported only in version 1.1 or higher */
2923 if (ctx->mod_version < 2) {
2924 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 +02002925 ret = LY_EVALID;
2926 goto cleanup;
2927 }
David Sedlákd6e56892019-07-01 15:40:24 +02002928 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002929 /* note that element was parsed for easy uniqueness check in next iterations */
2930 subelem->flags |= YIN_SUBELEM_PARSED;
2931
2932 switch (kw) {
2933 /* call responsible function */
2934 case LY_STMT_EXTENSION_INSTANCE:
2935 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vasko22df3f02020-08-24 13:29:22 +02002936 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002937 break;
2938 case LY_STMT_ACTION:
2939 case LY_STMT_RPC:
2940 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2941 break;
2942 case LY_STMT_ANYDATA:
2943 case LY_STMT_ANYXML:
2944 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2945 break;
2946 case LY_STMT_ARGUMENT:
2947 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2948 break;
2949 case LY_STMT_AUGMENT:
2950 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2951 break;
2952 case LY_STMT_BASE:
2953 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2954 break;
2955 case LY_STMT_BELONGS_TO:
2956 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2957 break;
2958 case LY_STMT_BIT:
2959 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2960 break;
2961 case LY_STMT_CASE:
2962 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2963 break;
2964 case LY_STMT_CHOICE:
2965 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2966 break;
2967 case LY_STMT_CONFIG:
2968 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2969 break;
2970 case LY_STMT_CONTACT:
2971 case LY_STMT_DESCRIPTION:
2972 case LY_STMT_ORGANIZATION:
2973 case LY_STMT_REFERENCE:
2974 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2975 break;
2976 case LY_STMT_CONTAINER:
2977 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2978 break;
2979 case LY_STMT_DEFAULT:
Michal Vasko7f45cf22020-10-01 12:49:44 +02002980 ret = yin_parse_qname(ctx, kw, subelem, exts);
2981 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01002982 case LY_STMT_ERROR_APP_TAG:
2983 case LY_STMT_KEY:
2984 case LY_STMT_PRESENCE:
2985 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2986 break;
2987 case LY_STMT_DEVIATE:
2988 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2989 break;
2990 case LY_STMT_DEVIATION:
2991 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2992 break;
2993 case LY_STMT_ENUM:
2994 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2995 break;
2996 case LY_STMT_ERROR_MESSAGE:
2997 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
2998 break;
2999 case LY_STMT_EXTENSION:
3000 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3001 break;
3002 case LY_STMT_FEATURE:
3003 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3004 break;
3005 case LY_STMT_FRACTION_DIGITS:
3006 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3007 break;
3008 case LY_STMT_GROUPING:
3009 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3010 break;
3011 case LY_STMT_IDENTITY:
3012 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3013 break;
3014 case LY_STMT_IF_FEATURE:
Michal Vasko7f45cf22020-10-01 12:49:44 +02003015 ret = yin_parse_qname(ctx, kw, subelem, exts);
3016 break;
Michal Vaskob36053d2020-03-26 15:49:30 +01003017 case LY_STMT_UNITS:
3018 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3019 break;
3020 case LY_STMT_IMPORT:
3021 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3022 break;
3023 case LY_STMT_INCLUDE:
3024 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3025 break;
3026 case LY_STMT_INPUT:
3027 case LY_STMT_OUTPUT:
3028 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
3029 break;
3030 case LY_STMT_LEAF:
3031 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3032 break;
3033 case LY_STMT_LEAF_LIST:
3034 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3035 break;
3036 case LY_STMT_LENGTH:
3037 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3038 break;
3039 case LY_STMT_LIST:
3040 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3041 break;
3042 case LY_STMT_MANDATORY:
3043 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3044 break;
3045 case LY_STMT_MAX_ELEMENTS:
3046 case LY_STMT_MIN_ELEMENTS:
3047 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
3048 break;
3049 case LY_STMT_MODIFIER:
3050 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
3051 break;
3052 case LY_STMT_MUST:
3053 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3054 break;
3055 case LY_STMT_NAMESPACE:
3056 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3057 break;
3058 case LY_STMT_NOTIFICATION:
3059 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3060 break;
3061 case LY_STMT_ORDERED_BY:
3062 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
3063 break;
3064 case LY_STMT_PATH:
3065 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
3066 break;
3067 case LY_STMT_PATTERN:
3068 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3069 break;
3070 case LY_STMT_VALUE:
3071 case LY_STMT_POSITION:
3072 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
3073 break;
3074 case LY_STMT_PREFIX:
3075 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
3076 break;
3077 case LY_STMT_RANGE:
3078 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3079 break;
3080 case LY_STMT_REFINE:
3081 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3082 break;
3083 case LY_STMT_REQUIRE_INSTANCE:
3084 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3085 break;
3086 case LY_STMT_REVISION:
3087 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3088 break;
3089 case LY_STMT_REVISION_DATE:
3090 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3091 break;
3092 case LY_STMT_STATUS:
3093 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3094 break;
3095 case LY_STMT_TYPE:
3096 ret = yin_parse_type(ctx, current_element, subelem);
3097 break;
3098 case LY_STMT_TYPEDEF:
3099 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3100 break;
3101 case LY_STMT_UNIQUE:
3102 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3103 break;
3104 case LY_STMT_USES:
3105 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3106 break;
3107 case LY_STMT_WHEN:
3108 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3109 break;
3110 case LY_STMT_YANG_VERSION:
3111 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3112 break;
3113 case LY_STMT_YIN_ELEMENT:
3114 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3115 break;
3116 case LY_STMT_ARG_TEXT:
3117 case LY_STMT_ARG_VALUE:
3118 /* TODO what to do with content/attributes? */
3119 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3120 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3121 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3122 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3123 }
3124 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3125 break;
3126 default:
3127 LOGINT(ctx->xmlctx->ctx);
3128 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003129 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003130 LY_CHECK_GOTO(ret, cleanup);
3131 subelem = NULL;
3132
3133 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003134 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003135 } else {
3136 LY_CHECK_RET(ret);
3137 /* elements with text or none content */
3138 /* save text content, if text_content isn't set, it's just ignored */
3139 /* no resources are allocated in this branch, no need to use cleanup label */
3140 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3141 if (text_content) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003142 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 +01003143 LY_CHECK_RET(!*text_content, LY_EMEM);
3144 }
3145
3146 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003147 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003148
David Sedlák8b754462019-07-25 16:22:13 +02003149 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3150 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003151
3152cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003153 return ret;
3154}
3155
David Sedlák619db942019-07-03 14:47:30 +02003156LY_ERR
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003157yin_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 +02003158 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003159{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003160 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003161 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003162
Michal Vaskob36053d2020-03-26 15:49:30 +01003163 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3164
3165 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003166
3167 e->yin = 0;
3168 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003169 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 +02003170 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003171 e->insubstmt = subelem;
3172 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003173 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003174 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003175
David Sedlákb1a78352019-06-28 16:16:29 +02003176 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003177 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3178 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003179 new_subelem = calloc(1, sizeof(*new_subelem));
3180 if (!e->child) {
3181 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003182 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003183 last_subelem->next = new_subelem;
3184 }
3185 last_subelem = new_subelem;
3186
3187 last_subelem->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003188 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 +02003189 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003190 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003191
Radek Krejci011e4aa2020-09-04 15:22:31 +02003192 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 +02003193 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003194 } else {
3195 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003196 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003197
3198 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003199 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003200
David Sedlákf250ecf2019-07-01 11:02:05 +02003201 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003202 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3203 if (ctx->xmlctx->ws_only) {
3204 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3205 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3206 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3207 if (!e->child) {
3208 e->child = new_subelem;
3209 } else {
3210 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003211 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003212 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003213
Michal Vaskob36053d2020-03-26 15:49:30 +01003214 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3215 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003216 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003217 } else if (ctx->xmlctx->value_len) {
3218 /* save text content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003219 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 +01003220 LY_CHECK_RET(!e->argument, LY_EMEM);
3221
3222 /* parser next */
3223 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003224 }
3225
3226 return LY_SUCCESS;
3227}
3228
David Sedlákaa98bba2019-09-12 11:52:14 +02003229/**
3230 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3231 *
3232 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003233 * @param[in] elem_type Type of element that is currently being parsed.
3234 * @param[out] arg Value to write to.
3235 *
3236 * @return LY_ERR values.
3237 */
3238static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003239yin_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 +02003240{
David Sedlák071f7662019-09-12 02:02:51 +02003241 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003242
Michal Vaskob36053d2020-03-26 15:49:30 +01003243 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3244
David Sedláke6284fc2019-09-10 11:57:02 +02003245 switch (elem_type) {
3246 case LY_STMT_ACTION:
3247 case LY_STMT_ANYDATA:
3248 case LY_STMT_ANYXML:
3249 case LY_STMT_ARGUMENT:
3250 case LY_STMT_BASE:
3251 case LY_STMT_BIT:
3252 case LY_STMT_CASE:
3253 case LY_STMT_CHOICE:
3254 case LY_STMT_CONTAINER:
3255 case LY_STMT_ENUM:
3256 case LY_STMT_EXTENSION:
3257 case LY_STMT_FEATURE:
3258 case LY_STMT_GROUPING:
3259 case LY_STMT_IDENTITY:
3260 case LY_STMT_IF_FEATURE:
3261 case LY_STMT_LEAF:
3262 case LY_STMT_LEAF_LIST:
3263 case LY_STMT_LIST:
3264 case LY_STMT_MODULE:
3265 case LY_STMT_NOTIFICATION:
3266 case LY_STMT_RPC:
3267 case LY_STMT_SUBMODULE:
3268 case LY_STMT_TYPE:
3269 case LY_STMT_TYPEDEF:
3270 case LY_STMT_UNITS:
3271 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003272 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 +02003273 break;
3274 case LY_STMT_AUGMENT:
3275 case LY_STMT_DEVIATION:
3276 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003277 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 +02003278 break;
3279 case LY_STMT_CONFIG:
3280 case LY_STMT_DEFAULT:
3281 case LY_STMT_DEVIATE:
3282 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003283 case LY_STMT_FRACTION_DIGITS:
3284 case LY_STMT_KEY:
3285 case LY_STMT_LENGTH:
3286 case LY_STMT_MANDATORY:
3287 case LY_STMT_MAX_ELEMENTS:
3288 case LY_STMT_MIN_ELEMENTS:
3289 case LY_STMT_MODIFIER:
3290 case LY_STMT_ORDERED_BY:
3291 case LY_STMT_PATH:
3292 case LY_STMT_PATTERN:
3293 case LY_STMT_POSITION:
3294 case LY_STMT_PREFIX:
3295 case LY_STMT_PRESENCE:
3296 case LY_STMT_RANGE:
3297 case LY_STMT_REQUIRE_INSTANCE:
3298 case LY_STMT_STATUS:
3299 case LY_STMT_VALUE:
3300 case LY_STMT_YANG_VERSION:
3301 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003302 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 +02003303 break;
3304 case LY_STMT_IMPORT:
3305 case LY_STMT_INCLUDE:
3306 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003307 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 +02003308 break;
3309 case LY_STMT_INPUT:
3310 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003311 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 +02003312 break;
3313 case LY_STMT_MUST:
3314 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003315 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 +02003316 break;
3317 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003318 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 +02003319 break;
3320 case LY_STMT_REVISION:
3321 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003322 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 +02003323 break;
3324 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003325 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 +02003326 break;
David Sedlák071f7662019-09-12 02:02:51 +02003327 /* argument is mapped to yin element */
3328 case LY_STMT_CONTACT:
3329 case LY_STMT_DESCRIPTION:
3330 case LY_STMT_ORGANIZATION:
3331 case LY_STMT_REFERENCE:
3332 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003333 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003334 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3335
3336 /* no content */
3337 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3338 if (ctx->xmlctx->ws_only) {
3339 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3340 }
3341 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3342 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3343 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003344 return LY_EVALID;
3345 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003346
3347 /* parse child element */
3348 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3349 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
Radek Krejci0f969882020-08-21 16:56:47 +02003350 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
Michal Vaskob36053d2020-03-26 15:49:30 +01003351 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3352 ly_stmt2str(elem_type));
3353 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003354 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003355 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3356
3357 /* no attributes expected? TODO */
3358 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3359 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3360 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3361 }
3362
3363 /* load and save content */
Radek Krejci011e4aa2020-09-04 15:22:31 +02003364 INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
Michal Vaskob36053d2020-03-26 15:49:30 +01003365 LY_CHECK_RET(!*arg, LY_EMEM);
3366
3367 /* load closing tag of subelement */
3368 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3369
3370 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3371 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3372 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3373 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003374 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003375 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003376 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003377 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003378 }
3379
David Sedlák071f7662019-09-12 02:02:51 +02003380 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003381}
3382
3383LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003384yin_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 +02003385{
3386 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003387 struct lysp_stmt *last = NULL, *new = NULL;
3388
Michal Vaskob36053d2020-03-26 15:49:30 +01003389 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003390
3391 /* allocate new structure for element */
3392 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003393 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3394 (*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 +02003395 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003396
Michal Vaskob36053d2020-03-26 15:49:30 +01003397 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3398 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003399
3400 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003401 if ((*element)->kw == LY_STMT_NONE) {
3402 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003403 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3404 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003405 ret = LY_EVALID;
3406 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003407 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3408 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003409 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003410 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003411 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003412 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3413
David Sedlákaa98bba2019-09-12 11:52:14 +02003414 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003415 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003416 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003417 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003418 if (!(*element)->child) {
3419 /* save first */
3420 (*element)->child = new;
3421 } else {
3422 last->next = new;
3423 }
3424 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003425
David Sedláke6284fc2019-09-10 11:57:02 +02003426 last->flags |= LYS_YIN_ATTR;
Radek Krejci011e4aa2020-09-04 15:22:31 +02003427 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 +02003428 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003429 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003430 if (!ctx->xmlctx->prefix) {
3431 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3432
Radek Krejci011e4aa2020-09-04 15:22:31 +02003433 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 +02003434 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003435 } else {
3436 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003437 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003438 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003439 }
3440 }
3441
Michal Vaskob36053d2020-03-26 15:49:30 +01003442 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3443 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3444 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3445 /* parse subelements */
3446 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003447 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003448 if (!(*element)->child) {
3449 /* save first */
3450 (*element)->child = new;
3451 } else {
3452 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003453 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003454 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003455
Michal Vaskob36053d2020-03-26 15:49:30 +01003456 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3457 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003458 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003459 } else {
3460 /* save element content */
3461 if (ctx->xmlctx->value_len) {
Radek Krejci011e4aa2020-09-04 15:22:31 +02003462 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 +01003463 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3464 }
3465
3466 /* read closing tag */
3467 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003468 }
3469
David Sedlákb0ca07d2019-09-11 11:54:05 +02003470cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003471 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003472}
3473
3474LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003475yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003476{
David Sedlák81497a32019-08-13 16:56:26 +02003477 LY_ERR ret = LY_SUCCESS;
3478 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003479 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003480
Michal Vaskoc3781c32020-10-06 14:04:08 +02003481 mod->is_submod = 0;
3482
Michal Vaskob36053d2020-03-26 15:49:30 +01003483 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3484 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 +02003485 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003486 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3487 LY_STMT_ANYXML, &mod->data, 0,
3488 LY_STMT_AUGMENT, &mod->augments, 0,
3489 LY_STMT_CHOICE, &mod->data, 0,
3490 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3491 LY_STMT_CONTAINER, &mod->data, 0,
3492 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3493 LY_STMT_DEVIATION, &mod->deviations, 0,
3494 LY_STMT_EXTENSION, &mod->extensions, 0,
3495 LY_STMT_FEATURE, &mod->features, 0,
3496 LY_STMT_GROUPING, &mod->groupings, 0,
3497 LY_STMT_IDENTITY, &mod->identities, 0,
3498 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3499 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3500 LY_STMT_LEAF, &mod->data, 0,
3501 LY_STMT_LEAF_LIST, &mod->data, 0,
3502 LY_STMT_LIST, &mod->data, 0,
3503 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3504 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3505 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3506 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3507 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3508 LY_STMT_REVISION, &mod->revs, 0,
3509 LY_STMT_RPC, &mod->rpcs, 0,
3510 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3511 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003512 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003513 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003514 ));
3515
Michal Vaskob36053d2020-03-26 15:49:30 +01003516 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003517 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003518 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003519
David Sedláked809f12019-09-13 10:15:11 +02003520 /* finalize parent pointers to the reallocated items */
3521 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3522
3523 /* submodules share the namespace with the module names, so there must not be
3524 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003525 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003526 if (dup) {
3527 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3528 return LY_EVALID;
3529 }
3530
3531 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003532}
3533
3534LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003535yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003536{
David Sedlák81497a32019-08-13 16:56:26 +02003537 LY_ERR ret = LY_SUCCESS;
3538 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003539 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003540
Michal Vaskoc3781c32020-10-06 14:04:08 +02003541 submod->is_submod = 1;
3542
Michal Vaskob36053d2020-03-26 15:49:30 +01003543 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3544 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 +02003545 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003546 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3547 LY_STMT_ANYXML, &submod->data, 0,
3548 LY_STMT_AUGMENT, &submod->augments, 0,
3549 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3550 LY_STMT_CHOICE, &submod->data, 0,
3551 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3552 LY_STMT_CONTAINER, &submod->data, 0,
3553 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3554 LY_STMT_DEVIATION, &submod->deviations, 0,
3555 LY_STMT_EXTENSION, &submod->extensions, 0,
3556 LY_STMT_FEATURE, &submod->features, 0,
3557 LY_STMT_GROUPING, &submod->groupings, 0,
3558 LY_STMT_IDENTITY, &submod->identities, 0,
3559 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3560 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3561 LY_STMT_LEAF, &submod->data, 0,
3562 LY_STMT_LEAF_LIST, &submod->data, 0,
3563 LY_STMT_LIST, &submod->data, 0,
3564 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3565 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3566 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3567 LY_STMT_REVISION, &submod->revs, 0,
3568 LY_STMT_RPC, &submod->rpcs, 0,
3569 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3570 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003571 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003572 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003573 ));
3574
Michal Vaskob36053d2020-03-26 15:49:30 +01003575 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003576 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003577 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003578
David Sedláked809f12019-09-13 10:15:11 +02003579 /* finalize parent pointers to the reallocated items */
3580 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3581
3582 /* submodules share the namespace with the module names, so there must not be
3583 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003584 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003585 if (dup && strcmp(dup->mod->name, submod->mod->name)) {
David Sedláked809f12019-09-13 10:15:11 +02003586 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3587 return LY_EVALID;
3588 }
3589
3590 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003591}
3592
3593LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003594yin_parse_submodule(struct lys_yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx,
Radek Krejci0f969882020-08-21 16:56:47 +02003595 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003596{
Radek Krejcid6b76452019-09-03 17:03:03 +02003597 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003598 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003599 struct lysp_submodule *mod_p = NULL;
3600
3601 /* create context */
3602 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003603 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003604 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko7c8439f2020-08-05 13:25:19 +02003605 (*yin_ctx)->main_mod = main_ctx->main_mod;
Michal Vasko63f3d842020-07-08 10:10:14 +02003606 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003607
David Sedlák1b623122019-08-05 15:27:49 +02003608 /* map the typedefs and groupings list from main context to the submodule's context */
3609 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3610 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3611
David Sedlák8985a142019-07-31 16:43:06 +02003612 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003613 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
Radek Krejci0f969882020-08-21 16:56:47 +02003614 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003615 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003616 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3617 ret = LY_EINVAL;
3618 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003619 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003620 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003621 ret = LY_EVALID;
3622 goto cleanup;
3623 }
3624
3625 mod_p = calloc(1, sizeof *mod_p);
Radek Krejcif027df72020-09-15 13:00:28 +02003626 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
Michal Vaskoc3781c32020-10-06 14:04:08 +02003627 mod_p->mod = main_ctx->main_mod;
David Sedlák8985a142019-07-31 16:43:06 +02003628 mod_p->parsing = 1;
3629
Michal Vaskob36053d2020-03-26 15:49:30 +01003630 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003631 LY_CHECK_GOTO(ret, cleanup);
3632
David Sedlákbf8a2b72019-08-14 16:48:10 +02003633 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003634 while (isspace(in->current[0])) {
3635 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003636 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003637 if (in->current[0]) {
3638 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
3639 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003640 ret = LY_EVALID;
3641 goto cleanup;
3642 }
3643
David Sedlák8985a142019-07-31 16:43:06 +02003644 mod_p->parsing = 0;
3645 *submod = mod_p;
3646
3647cleanup:
3648 if (ret) {
3649 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003650 yin_parser_ctx_free(*yin_ctx);
3651 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003652 }
David Sedlák8985a142019-07-31 16:43:06 +02003653 return ret;
3654}
3655
3656LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003657yin_parse_module(struct lys_yin_parser_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003658{
David Sedláke4889912018-11-02 09:52:40 +01003659 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003660 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003661 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003662
David Sedlák8985a142019-07-31 16:43:06 +02003663 /* create context */
3664 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003665 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003666 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko7c8439f2020-08-05 13:25:19 +02003667 (*yin_ctx)->main_mod = mod;
Michal Vasko63f3d842020-07-08 10:10:14 +02003668 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003669
David Sedlák8985a142019-07-31 16:43:06 +02003670 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003671 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
Radek Krejci0f969882020-08-21 16:56:47 +02003672 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003673 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003674 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 +01003675 ret = LY_EINVAL;
3676 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003677 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003678 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003679 ret = LY_EVALID;
3680 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003681 }
3682
David Sedlák3017da42019-02-15 09:48:04 +01003683 /* allocate module */
3684 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003685 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003686 mod_p->mod = mod;
3687 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003688
David Sedlák00250342019-06-21 14:19:39 +02003689 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003690 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003691 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003692
David Sedlákbf8a2b72019-08-14 16:48:10 +02003693 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003694 while (isspace(in->current[0])) {
3695 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003696 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003697 if (in->current[0]) {
3698 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
3699 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003700 ret = LY_EVALID;
3701 goto cleanup;
3702 }
3703
David Sedlák3017da42019-02-15 09:48:04 +01003704 mod_p->parsing = 0;
3705 mod->parsed = mod_p;
3706
3707cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003708 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003709 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003710 yin_parser_ctx_free(*yin_ctx);
3711 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003712 }
David Sedlák2e411422018-12-17 02:35:39 +01003713 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003714}