blob: 89dc4cffd887023cb154b0a2adb0b10ff593b518 [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
David Sedlákf6251182019-06-06 10:22:13 +020046const char *const yin_attr_list[] = {
47 [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,
Michal Vasko63f3d842020-07-08 10:10:14 +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 Vaskob36053d2020-03-26 15:49:30 +010072 ns = lyxml_ns_get(ctx->xmlctx, 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
David Sedlák94de2aa2019-02-15 12:42:11 +0100110#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
111#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100112#define IF_ARG_PREFIX_END }
113
David Sedlák1c8b2702019-02-22 11:03:02 +0100114 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100115 case 'c':
116 already_read += 1;
117 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200118 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200119
David Sedlák94de2aa2019-02-15 12:42:11 +0100120 case 'd':
121 already_read += 1;
122 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200123 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200124
David Sedlák94de2aa2019-02-15 12:42:11 +0100125 case 'm':
126 already_read += 1;
127 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200128 break;
129
David Sedlák94de2aa2019-02-15 12:42:11 +0100130 case 'n':
131 already_read += 1;
132 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200133 break;
134
David Sedlák94de2aa2019-02-15 12:42:11 +0100135 case 't':
136 already_read += 1;
137 IF_ARG_PREFIX("a", 1)
138 IF_ARG("g", 1, YIN_ARG_TAG)
139 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
140 IF_ARG_PREFIX_END
141 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200142 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200143
David Sedlák94de2aa2019-02-15 12:42:11 +0100144 case 'u':
145 already_read += 1;
146 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200147 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200148
David Sedlák94de2aa2019-02-15 12:42:11 +0100149 case 'v':
150 already_read += 1;
151 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200152 break;
153 }
154
David Sedlákc10e7902018-12-17 02:17:59 +0100155 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200156 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200157 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200158 }
159
David Sedlák18730132019-03-15 15:51:34 +0100160#undef IF_ARG
161#undef IF_ARG_PREFIX
162#undef IF_ARG_PREFIX_END
163
David Sedlák872c7b42018-10-26 13:15:20 +0200164 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200165}
166
Radek Krejcid6b76452019-09-03 17:03:03 +0200167#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
168 kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
169 kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
170 kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
David Sedlák81497a32019-08-13 16:56:26 +0200171
Radek Krejcid6b76452019-09-03 17:03:03 +0200172#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 +0200173
David Sedlák26ea1432019-08-14 13:42:23 +0200174/**
175 * @brief Free subelems information allocated on heap.
176 *
177 * @param[in] count Size of subelems array.
178 * @param[in] subelems Subelems array to free.
179 */
David Sedlák81497a32019-08-13 16:56:26 +0200180static void
181subelems_deallocator(size_t count, struct yin_subelement *subelems)
182{
183 for(size_t i = 0; i < count; ++i) {
184 if (HAS_META(subelems[i].type)) {
185 free(subelems[i].dest);
186 }
187 }
188
189 free(subelems);
190}
191
David Sedlák26ea1432019-08-14 13:42:23 +0200192/**
193 * @brief Allocate subelems information on heap.
194 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200195 * @param[in] ctx YIN parser context, used for logging.
David Sedlák26ea1432019-08-14 13:42:23 +0200196 * @param[in] count Number of subelements.
197 * @param[in] parent Parent node if any.
198 * @param[out] result Allocated subelems array.
199 *
200 * @return LY_SUCCESS on success LY_EMEM on memmory allocation failure.
201 */
David Sedlák81497a32019-08-13 16:56:26 +0200202static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100203subelems_allocator(struct lys_yin_parser_ctx *ctx, size_t count, struct lysp_node *parent,
David Sedlák81497a32019-08-13 16:56:26 +0200204 struct yin_subelement **result, ...)
205{
206 va_list ap;
207
208 *result = calloc(count, sizeof **result);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200209 LY_CHECK_GOTO(!(*result), mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200210
211 va_start(ap, result);
212 for (size_t i = 0; i < count; ++i) {
213 /* TYPE */
Radek Krejcid6b76452019-09-03 17:03:03 +0200214 (*result)[i].type = va_arg(ap, enum ly_stmt);
David Sedlák81497a32019-08-13 16:56:26 +0200215 /* DEST */
216 if (IS_NODE_ELEM((*result)[i].type)) {
217 struct tree_node_meta *node_meta = NULL;
218 node_meta = calloc(1, sizeof *node_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200219 LY_CHECK_GOTO(!node_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200220 node_meta->parent = parent;
David Sedlákbf8a2b72019-08-14 16:48:10 +0200221 node_meta->nodes = va_arg(ap, void *);
David Sedlák81497a32019-08-13 16:56:26 +0200222 (*result)[i].dest = node_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200223 } else if ((*result)[i].type == LY_STMT_IMPORT) {
David Sedlák81497a32019-08-13 16:56:26 +0200224 struct import_meta *imp_meta = NULL;
225 imp_meta = calloc(1, sizeof *imp_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200226 LY_CHECK_GOTO(!imp_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200227 imp_meta->prefix = va_arg(ap, const char *);
228 imp_meta->imports = va_arg(ap, struct lysp_import **);
229 (*result)[i].dest = imp_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200230 } else if ((*result)[i].type == LY_STMT_INCLUDE) {
David Sedlák81497a32019-08-13 16:56:26 +0200231 struct include_meta *inc_meta = NULL;
232 inc_meta = calloc(1, sizeof *inc_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200233 LY_CHECK_GOTO(!inc_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200234 inc_meta->name = va_arg(ap, const char *);
235 inc_meta->includes = va_arg(ap, struct lysp_include **);
236 (*result)[i].dest = inc_meta;
Radek Krejcid6b76452019-09-03 17:03:03 +0200237 } else if ((*result)[i].type == LY_STMT_INPUT || (*result)[i].type == LY_STMT_OUTPUT) {
David Sedlák81497a32019-08-13 16:56:26 +0200238 struct inout_meta *inout_meta = NULL;
239 inout_meta = calloc(1, sizeof *inout_meta);
David Sedlákbf8a2b72019-08-14 16:48:10 +0200240 LY_CHECK_GOTO(!inout_meta, mem_err);
David Sedlák81497a32019-08-13 16:56:26 +0200241 inout_meta->parent = parent;
242 inout_meta->inout_p = va_arg(ap, struct lysp_action_inout *);
243 (*result)[i].dest = inout_meta;
244 } else {
245 (*result)[i].dest = va_arg(ap, void *);
246 }
247 /* FLAGS */
248 (*result)[i].flags = va_arg(ap, int);
249 }
250 va_end(ap);
251
252 return LY_SUCCESS;
253
David Sedlákbf8a2b72019-08-14 16:48:10 +0200254mem_err:
David Sedlák81497a32019-08-13 16:56:26 +0200255 subelems_deallocator(count, *result);
Michal Vaskob36053d2020-03-26 15:49:30 +0100256 LOGMEM(ctx->xmlctx->ctx);
David Sedlák81497a32019-08-13 16:56:26 +0200257 return LY_EMEM;
258}
259
David Sedlák8f7a1172019-06-20 14:42:18 +0200260LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100261yin_validate_value(struct lys_yin_parser_ctx *ctx, enum yang_arg val_type)
David Sedlák4a650532019-07-10 11:55:18 +0200262{
263 int prefix = 0;
264 unsigned int c;
Michal Vaskob36053d2020-03-26 15:49:30 +0100265 size_t utf8_char_len, already_read = 0;
266 const char *val;
267
268 assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
269
270 val = ctx->xmlctx->value;
271 while (already_read < ctx->xmlctx->value_len) {
David Sedlák4a650532019-07-10 11:55:18 +0200272 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
273 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
274 already_read += utf8_char_len;
Michal Vaskob36053d2020-03-26 15:49:30 +0100275 LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
David Sedlák4a650532019-07-10 11:55:18 +0200276
277 switch (val_type) {
278 case Y_IDENTIF_ARG:
279 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
280 break;
281 case Y_PREF_IDENTIF_ARG:
282 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
283 break;
284 case Y_STR_ARG:
285 case Y_MAYBE_STR_ARG:
286 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
287 break;
288 }
289 }
290
291 return LY_SUCCESS;
292}
293
David Sedlákb4e44562019-07-04 15:42:12 +0200294/**
Michal Vaskob36053d2020-03-26 15:49:30 +0100295 * @brief Parse yin attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200296 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200297 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák4a650532019-07-10 11:55:18 +0200298 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
299 * special argument).
David Sedlákbf8a2b72019-08-14 16:48:10 +0200300 * @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 +0200301 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200302 * @param[in] current_element Identification of current element, used for logging.
303 *
304 * @return LY_ERR values.
305 */
306static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100307yin_parse_attribute(struct lys_yin_parser_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
308 enum ly_stmt current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200309{
David Sedlákc5b20842019-08-13 10:18:31 +0200310 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák619db942019-07-03 14:47:30 +0200311 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200312
David Sedlák1bccdfa2019-06-17 15:55:27 +0200313 /* validation of attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100314 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedlák00250342019-06-21 14:19:39 +0200315 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
Michal Vaskob36053d2020-03-26 15:49:30 +0100316 if (!ctx->xmlctx->prefix) {
317 arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200318 if (arg == YIN_ARG_NONE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100319 /* skip it */
320 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák7ff55a92019-06-17 11:11:41 +0200321 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200322 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200323 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200324 found = true;
Michal Vaskob36053d2020-03-26 15:49:30 +0100325
326 /* go to value */
327 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
328 LY_CHECK_RET(yin_validate_value(ctx, val_type));
329 *arg_val = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlák169cc522019-08-15 13:23:45 +0200330 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák2b214ac2019-06-06 16:11:03 +0200331 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100332 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, ctx->xmlctx->name_len,
333 ctx->xmlctx->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200334 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200335 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100336 } else {
337 /* skip it */
338 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200339 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100340
341 /* next attribute */
342 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedláka7406952019-04-05 10:33:07 +0200343 }
344
David Sedlák292763b2019-07-09 11:10:53 +0200345 /* anything else than Y_MAYBE_STR_ARG is mandatory */
346 if (val_type != Y_MAYBE_STR_ARG && !found) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100347 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
348 yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200349 return LY_EVALID;
350 }
351
352 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200353}
354
David Sedlákd6e56892019-07-01 15:40:24 +0200355/**
Radek Krejci12b1c152019-09-05 16:20:48 +0200356 * @brief Get record with given type.
David Sedlákd6e56892019-07-01 15:40:24 +0200357 *
358 * @param[in] type Type of wanted record.
359 * @param[in] array_size Size of array.
360 * @param[in] array Searched array.
361 *
362 * @return Pointer to desired record on success, NULL if element is not in the array.
363 */
David Sedlákb4e44562019-07-04 15:42:12 +0200364static struct yin_subelement *
Radek Krejci12b1c152019-09-05 16:20:48 +0200365get_record(enum ly_stmt type, size_t array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200366{
Radek Krejci12b1c152019-09-05 16:20:48 +0200367 for (unsigned int u = 0; u < array_size; ++u) {
368 if (array[u].type == type) {
369 return &array[u];
David Sedlákd6e56892019-07-01 15:40:24 +0200370 }
371 }
David Sedlákd6e56892019-07-01 15:40:24 +0200372 return NULL;
373}
374
David Sedlákbba38e52019-07-09 15:20:01 +0200375/**
376 * @brief Helper function to check mandatory constraint of subelement.
377 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200378 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200379 * @param[in] subelem_info Array of information about subelements.
380 * @param[in] subelem_info_size Size of subelem_info array.
381 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
382 *
383 * @return LY_ERR values.
384 */
385static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100386yin_check_subelem_mandatory_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200387 signed char subelem_info_size, enum ly_stmt current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200388{
David Sedlákb0faad82019-07-04 14:28:59 +0200389 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200390 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
Radek Krejci12b1c152019-09-05 16:20:48 +0200391 if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200392 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200393 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200394 return LY_EVALID;
395 }
396 }
397
398 return LY_SUCCESS;
399}
400
David Sedlákbba38e52019-07-09 15:20:01 +0200401/**
402 * @brief Helper function to check "first" constraint of subelement.
403 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200404 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200405 * @param[in] subelem_info Array of information about subelements.
406 * @param[in] subelem_info_size Size of subelem_info array.
407 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200408 * @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 +0200409 *
410 * @return LY_ERR values.
411 */
412static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100413yin_check_subelem_first_constraint(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
Radek Krejcid6b76452019-09-03 17:03:03 +0200414 signed char subelem_info_size, enum ly_stmt current_element,
David Sedláke1a30302019-07-10 13:49:38 +0200415 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200416{
David Sedlákb0faad82019-07-04 14:28:59 +0200417 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200418 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200419 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
420 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200421 return LY_EVALID;
422 }
423 }
424
425 return LY_SUCCESS;
426}
427
David Sedlákbba38e52019-07-09 15:20:01 +0200428/**
David Sedlákb4e44562019-07-04 15:42:12 +0200429 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
430 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200431 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200432 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákb4e44562019-07-04 15:42:12 +0200433 * @param[in] kw Type of current element.
434 * @param[out] value Where value of attribute should be stored.
435 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200436 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200437 * @param[in,out] exts Extension instances to add to.
David Sedlákd6e56892019-07-01 15:40:24 +0200438 * @return LY_ERR values.
439 */
David Sedlákb4e44562019-07-04 15:42:12 +0200440static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100441yin_parse_simple_element(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char **value,
442 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200443{
Michal Vaskob36053d2020-03-26 15:49:30 +0100444 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
445 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200446 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200447 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200448 };
David Sedlákb4e44562019-07-04 15:42:12 +0200449
Michal Vaskob36053d2020-03-26 15:49:30 +0100450 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200451}
452
453/**
David Sedlák6542aed2019-08-14 10:47:43 +0200454 * @brief Parse path element.
455 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200456 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200457 * @param[in] kw Type of current element.
458 * @param[out] type Type structure to store parsed value, flags and extension instances.
David Sedlák6542aed2019-08-14 10:47:43 +0200459 * @return LY_ERR values.
460 */
461static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100462yin_parse_path(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200463{
Michal Vasko004d3152020-06-11 19:59:22 +0200464 LY_ERR ret;
465 const char *str_path;
466
467 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
468 ret = ly_path_parse(ctx->xmlctx->ctx, str_path, 0, LY_PATH_BEGIN_EITHER, LY_PATH_LREF_TRUE,
469 LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
470 lydict_remove(ctx->xmlctx->ctx, str_path);
471 LY_CHECK_RET(ret);
David Sedlák6542aed2019-08-14 10:47:43 +0200472 type->flags |= LYS_SET_PATH;
473
474 return LY_SUCCESS;
475}
476
477/**
David Sedlákd3983112019-07-12 11:20:56 +0200478 * @brief Parse pattern element.
479 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200480 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200481 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlákd3983112019-07-12 11:20:56 +0200482 * @return LY_ERR values.
483 */
484static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100485yin_parse_pattern(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákd3983112019-07-12 11:20:56 +0200486{
487 const char *real_value = NULL;
488 char *saved_value = NULL;
489 struct lysp_restr *restr;
490
Michal Vaskob36053d2020-03-26 15:49:30 +0100491 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
492 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
493 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 +0200494 size_t len = strlen(real_value);
495
496 saved_value = malloc(len + 2);
Michal Vaskob36053d2020-03-26 15:49:30 +0100497 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200498 memmove(saved_value + 1, real_value, len);
Michal Vaskob36053d2020-03-26 15:49:30 +0100499 FREE_STRING(ctx->xmlctx->ctx, real_value);
David Sedlákd3983112019-07-12 11:20:56 +0200500 saved_value[0] = 0x06;
501 saved_value[len + 1] = '\0';
Michal Vaskob36053d2020-03-26 15:49:30 +0100502 restr->arg = lydict_insert_zc(ctx->xmlctx->ctx, saved_value);
503 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200504 type->flags |= LYS_SET_PATTERN;
505
506 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200507 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
508 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
509 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
510 {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
511 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
512 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákd3983112019-07-12 11:20:56 +0200513 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100514 return yin_parse_content(ctx, subelems, 6, LY_STMT_PATTERN, NULL, &restr->exts);
David Sedlákd3983112019-07-12 11:20:56 +0200515}
516
David Sedlákc5b20842019-08-13 10:18:31 +0200517/**
518 * @brief Parse fraction-digits element.
519 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200520 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc5b20842019-08-13 10:18:31 +0200521 * @param[in,out] type Type structure to store value, flags and extension instances.
David Sedlákc5b20842019-08-13 10:18:31 +0200522 * @return LY_ERR values.
523 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200524static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100525yin_parse_fracdigits(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákf75d55e2019-07-12 16:52:50 +0200526{
527 const char *temp_val = NULL;
528 char *ptr;
529 unsigned long int num;
530
Michal Vaskob36053d2020-03-26 15:49:30 +0100531 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
532 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 +0200533
534 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200535 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100536 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200537 return LY_EVALID;
538 }
539
540 errno = 0;
541 num = strtoul(temp_val, &ptr, 10);
542 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200543 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100544 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200545 return LY_EVALID;
546 }
547 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200548 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
Michal Vaskob36053d2020-03-26 15:49:30 +0100549 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200550 return LY_EVALID;
551 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100552 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200553 type->fraction_digits = num;
554 type->flags |= LYS_SET_FRDIGITS;
555 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200556 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200557 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100558 return yin_parse_content(ctx, subelems, 1, LY_STMT_FRACTION_DIGITS, NULL, &type->exts);
David Sedlákf75d55e2019-07-12 16:52:50 +0200559}
560
David Sedlák07869a52019-07-12 14:28:19 +0200561/**
David Sedlák43801c92019-08-05 15:58:54 +0200562 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200563 *
564 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200565 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200566 * @return LY_ERR values.
567 */
David Sedlákca36c422019-07-12 12:47:55 +0200568static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100569yin_parse_enum(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200570{
David Sedlák07869a52019-07-12 14:28:19 +0200571 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200572
Michal Vaskob36053d2020-03-26 15:49:30 +0100573 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200574 type->flags |= LYS_SET_ENUM;
Michal Vaskob36053d2020-03-26 15:49:30 +0100575 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
576 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 +0200577 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
Michal Vaskob36053d2020-03-26 15:49:30 +0100578 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák43801c92019-08-05 15:58:54 +0200579 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200580
581 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200582 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
583 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
584 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
585 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
586 {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
587 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákca36c422019-07-12 12:47:55 +0200588 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100589 return yin_parse_content(ctx, subelems, 6, LY_STMT_ENUM, NULL, &en->exts);
David Sedlák43801c92019-08-05 15:58:54 +0200590}
591
592/**
593 * @brief Parse bit element.
594 *
595 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200596 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200597 * @return LY_ERR values.
598 */
599static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100600yin_parse_bit(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák43801c92019-08-05 15:58:54 +0200601{
602 struct lysp_type_enum *en;
603
Michal Vaskob36053d2020-03-26 15:49:30 +0100604 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
David Sedlák43801c92019-08-05 15:58:54 +0200605 type->flags |= LYS_SET_BIT;
Michal Vaskob36053d2020-03-26 15:49:30 +0100606 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
607 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 +0200608 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
609
610 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200611 {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
612 {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
613 {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
614 {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
615 {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
616 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák43801c92019-08-05 15:58:54 +0200617 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100618 return yin_parse_content(ctx, subelems, 6, LY_STMT_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200619}
620
David Sedlákd3983112019-07-12 11:20:56 +0200621/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200622 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
623 * more instances, such as base or if-feature.
624 *
625 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5f8191e2019-07-08 16:35:52 +0200626 * @param[in] kw Type of current element.
627 * @param[out] values Parsed values to add to.
628 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200629 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200630 * @param[in,out] exts Extension instances to add to.
David Sedlák5f8191e2019-07-08 16:35:52 +0200631 * @return LY_ERR values.
632 */
633static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100634yin_parse_simple_elements(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, const char ***values, enum yin_argument arg_type,
635 enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200636{
637 const char **value;
Michal Vaskob36053d2020-03-26 15:49:30 +0100638 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200639 LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200640 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200641 {LY_STMT_EXTENSION_INSTANCE, &index, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200642 };
643
Michal Vaskob36053d2020-03-26 15:49:30 +0100644 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
645 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200646
Michal Vaskob36053d2020-03-26 15:49:30 +0100647 return yin_parse_content(ctx, subelems, 1, kw, NULL, exts);
David Sedlák5f8191e2019-07-08 16:35:52 +0200648}
649
650/**
David Sedlák6542aed2019-08-14 10:47:43 +0200651 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
652 *
653 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200654 * @param[in] kw Type of current element.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200655 * @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 +0200656 * @param[in] arg_type Expected type of attribute.
657 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200658 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200659 * @return LY_ERR values.
660 */
661static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100662yin_parse_simple_elem(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, struct yin_subelement *subinfo,
663 enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák6542aed2019-08-14 10:47:43 +0200664{
665 if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100666 LY_CHECK_RET(yin_parse_simple_element(ctx, kw, (const char **)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200667 arg_type, arg_val_type, exts));
668 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100669 LY_CHECK_RET(yin_parse_simple_elements(ctx, kw, (const char ***)subinfo->dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200670 arg_type, arg_val_type, exts));
671 }
672
673 return LY_SUCCESS;
674}
675
676/**
677 * @brief Parse base element.
678 *
679 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200680 * @param[in] parent Identification of parent element.
681 * @param[out] dest Where parsed values should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200682 * @param[in,out] exts Extension instances to add to.
David Sedlák6542aed2019-08-14 10:47:43 +0200683 * @return LY_ERR values.
684 */
685static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100686yin_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 +0200687{
688 struct lysp_type *type = NULL;
689
Radek Krejcid6b76452019-09-03 17:03:03 +0200690 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +0200691 type = (struct lysp_type *)dest;
Michal Vaskob36053d2020-03-26 15:49:30 +0100692 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME,
David Sedlák6542aed2019-08-14 10:47:43 +0200693 Y_PREF_IDENTIF_ARG, exts));
694 type->flags |= LYS_SET_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +0200695 } else if (parent == LY_STMT_IDENTITY) {
Michal Vaskob36053d2020-03-26 15:49:30 +0100696 LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest,
David Sedlák6542aed2019-08-14 10:47:43 +0200697 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
698 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +0100699 LOGINT(ctx->xmlctx->ctx);
David Sedlák6542aed2019-08-14 10:47:43 +0200700 return LY_EINT;
701 }
702
703 return LY_SUCCESS;
704}
705
706/**
David Sedlákbf8a2b72019-08-14 16:48:10 +0200707 * @brief Parse require-instance element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200708 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200709 * @param[in,out] ctx YIN parser context for logging and to store current state.
Michal Vaskob36053d2020-03-26 15:49:30 +0100710 * @param[out] type Type structure to store value, flag and extensions.
David Sedlákcf5569a2019-07-11 13:31:34 +0200711 * @return LY_ERR values.
712 */
713static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100714yin_pasrse_reqinstance(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlákcf5569a2019-07-11 13:31:34 +0200715{
716 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200717 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200718 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200719 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200720
721 type->flags |= LYS_SET_REQINST;
Michal Vaskob36053d2020-03-26 15:49:30 +0100722 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
723 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 +0200724 if (strcmp(temp_val, "true") == 0) {
725 type->require_instance = 1;
726 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200727 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
728 "require-instance", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +0100729 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200730 return LY_EVALID;
731 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100732 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákcf5569a2019-07-11 13:31:34 +0200733
Michal Vaskob36053d2020-03-26 15:49:30 +0100734 return yin_parse_content(ctx, subelems, 1, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts);
David Sedlákcf5569a2019-07-11 13:31:34 +0200735}
736
737/**
David Sedlákce77bf52019-07-11 16:59:31 +0200738 * @brief Parse modifier element.
739 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200740 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákce77bf52019-07-11 16:59:31 +0200741 * @param[in,out] pat Value to write to.
742 * @param[in,out] exts Extension instances to add to.
743 *
744 * @return LY_ERR values.
745 */
746static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100747yin_parse_modifier(struct lys_yin_parser_ctx *ctx, const char **pat, struct lysp_ext_instance **exts)
David Sedlákce77bf52019-07-11 16:59:31 +0200748{
David Sedlákd3983112019-07-12 11:20:56 +0200749 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200750 const char *temp_val;
751 char *modified_val;
752 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200753 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákce77bf52019-07-11 16:59:31 +0200754 };
755
Michal Vaskob36053d2020-03-26 15:49:30 +0100756 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
757 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 +0200758 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák26ea1432019-08-14 13:42:23 +0200759 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
760 "modifier", "invert-match");
Michal Vaskob36053d2020-03-26 15:49:30 +0100761 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200762 return LY_EVALID;
763 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100764 lydict_remove(ctx->xmlctx->ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200765
766 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200767 modified_val = malloc(strlen(*pat) + 1);
Michal Vaskob36053d2020-03-26 15:49:30 +0100768 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200769 strcpy(modified_val, *pat);
Michal Vaskob36053d2020-03-26 15:49:30 +0100770 lydict_remove(ctx->xmlctx->ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200771
772 /* modify the new value */
773 modified_val[0] = 0x15;
Michal Vaskob36053d2020-03-26 15:49:30 +0100774 *pat = lydict_insert_zc(ctx->xmlctx->ctx, modified_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200775
Michal Vaskob36053d2020-03-26 15:49:30 +0100776 return yin_parse_content(ctx, subelems, 1, LY_STMT_MODIFIER, NULL, exts);
David Sedlákce77bf52019-07-11 16:59:31 +0200777}
778
779/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200780 * @brief Parse a restriction element (length, range or one instance of must).
781 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200782 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200783 * @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 +0200784 * @param[in] restr Value to write to.
David Sedlákb7296dd2019-07-11 14:58:38 +0200785 */
786static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100787yin_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 +0200788{
Radek Krejcid6b76452019-09-03 17:03:03 +0200789 assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
David Sedlákb7296dd2019-07-11 14:58:38 +0200790 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200791 {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
792 {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
793 {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
794 {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
795 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200796 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200797 /* argument of must is called condition, but argument of length and range is called value */
Radek Krejcid6b76452019-09-03 17:03:03 +0200798 enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200799
Michal Vaskob36053d2020-03-26 15:49:30 +0100800 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
801 LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
802
803 return yin_parse_content(ctx, subelems, 5, restr_kw, NULL, &restr->exts);
David Sedlákb7296dd2019-07-11 14:58:38 +0200804}
805
806/**
David Sedlák6542aed2019-08-14 10:47:43 +0200807 * @brief Parse range element.
808 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200809 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200810 * @param[out] type Type structure to store parsed value and flags.
811 *
812 * @return LY_ERR values.
813 */
814static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100815yin_parse_range(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200816{
817 type->range = calloc(1, sizeof *type->range);
Michal Vaskob36053d2020-03-26 15:49:30 +0100818 LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
819 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
David Sedlák6542aed2019-08-14 10:47:43 +0200820 type->flags |= LYS_SET_RANGE;
821
822 return LY_SUCCESS;
823}
824
825/**
826 * @brief Parse length element.
827 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200828 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +0200829 * @param[out] type Type structure to store parsed value and flags.
830 *
831 * @return LY_ERR values.
832 */
833static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100834yin_parse_length(struct lys_yin_parser_ctx *ctx, struct lysp_type *type)
David Sedlák6542aed2019-08-14 10:47:43 +0200835{
836 type->length = calloc(1, sizeof *type->length);
Michal Vaskob36053d2020-03-26 15:49:30 +0100837 LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
838 LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
David Sedlák6542aed2019-08-14 10:47:43 +0200839 type->flags |= LYS_SET_LENGTH;
840
841 return LY_SUCCESS;
842}
843
844/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200845 * @brief Parse must element.
846 *
847 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200848 * @param[in,out] restrs Restrictions to add to.
849 *
850 * @return LY_ERR values.
851 */
852static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100853yin_parse_must(struct lys_yin_parser_ctx *ctx, struct lysp_restr **restrs)
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200854{
855 struct lysp_restr *restr;
856
Michal Vaskob36053d2020-03-26 15:49:30 +0100857 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
858 return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200859}
860
861/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200862 * @brief Parse position or value element.
863 *
864 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200865 * @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 +0200866 * @param[out] enm Enum structure to save value, flags and extension instances.
David Sedlák5545f5d2019-07-11 11:55:16 +0200867 *
868 * @return LY_ERR values.
869 */
870static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100871yin_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 +0200872{
Radek Krejcid6b76452019-09-03 17:03:03 +0200873 assert(kw == LY_STMT_POSITION || kw == LY_STMT_VALUE);
David Sedlák5545f5d2019-07-11 11:55:16 +0200874 const char *temp_val = NULL;
875 char *ptr;
Michal Vaskoed4fcfe2020-07-08 10:38:56 +0200876 long int num = 0;
877 unsigned long int unum = 0;
David Sedlák5545f5d2019-07-11 11:55:16 +0200878
879 /* set value flag */
880 enm->flags |= LYS_SET_VALUE;
881
882 /* get attribute value */
Michal Vaskob36053d2020-03-26 15:49:30 +0100883 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
884 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200885 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
Radek Krejcid6b76452019-09-03 17:03:03 +0200886 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200887 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 +0200888 goto error;
889 }
890
891 /* convert value */
892 errno = 0;
Radek Krejcid6b76452019-09-03 17:03:03 +0200893 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200894 num = strtol(temp_val, &ptr, 10);
895 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200896 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 +0200897 goto error;
898 }
899 } else {
900 unum = strtoul(temp_val, &ptr, 10);
901 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200902 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 +0200903 goto error;
904 }
905 }
906 /* check if whole argument value was converted */
907 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200908 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 +0200909 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200910 }
911 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200912 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 +0200913 goto error;
914 }
915 /* save correctly ternary operator can't be used because num and unum have different signes */
Radek Krejcid6b76452019-09-03 17:03:03 +0200916 if (kw == LY_STMT_VALUE) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200917 enm->value = num;
918 } else {
919 enm->value = unum;
920 }
Michal Vaskob36053d2020-03-26 15:49:30 +0100921 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák5545f5d2019-07-11 11:55:16 +0200922
923 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200924 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200925 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák968ac342019-07-11 15:17:59 +0200926 };
Michal Vaskob36053d2020-03-26 15:49:30 +0100927 return yin_parse_content(ctx, subelems, 1, kw, NULL, &enm->exts);
David Sedlák5545f5d2019-07-11 11:55:16 +0200928
David Sedlákbf8a2b72019-08-14 16:48:10 +0200929error:
Michal Vaskob36053d2020-03-26 15:49:30 +0100930 FREE_STRING(ctx->xmlctx->ctx, temp_val);
931 return LY_EVALID;
David Sedlák5545f5d2019-07-11 11:55:16 +0200932}
933
David Sedlák05404f62019-07-24 14:11:53 +0200934/**
935 * @brief Parse belongs-to element.
936 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200937 * @param[in] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +0200938 * @param[out] submod Structure of submodule that is being parsed.
939 * @param[in,out] exts Extension instances to add to.
940 *
941 * @return LY_ERR values
942 */
943static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100944yin_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 +0200945{
946 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200947 {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
948 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák05404f62019-07-24 14:11:53 +0200949 };
David Sedlák05404f62019-07-24 14:11:53 +0200950
Michal Vaskob36053d2020-03-26 15:49:30 +0100951 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
952 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
953
954 return yin_parse_content(ctx, subelems, 2, LY_STMT_BELONGS_TO, NULL, exts);
David Sedlák05404f62019-07-24 14:11:53 +0200955}
956
David Sedlák5545f5d2019-07-11 11:55:16 +0200957/**
David Sedlákc1771b12019-07-10 15:55:46 +0200958 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákbf8a2b72019-08-14 16:48:10 +0200959 * text element as child.
David Sedlákb4e44562019-07-04 15:42:12 +0200960 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200961 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +0200962 * @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 +0200963 * @param[out] value Where the content of meta element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200964 * @param[in,out] exts Extension instances to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200965 *
966 * @return LY_ERR values.
967 */
968static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100969yin_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 +0200970{
Radek Krejcid6b76452019-09-03 17:03:03 +0200971 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 +0200972
David Sedlák968ac342019-07-11 15:17:59 +0200973 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200974 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
975 {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +0200976 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200977 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +0100978 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
979 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 +0200980
David Sedlákdf2a9732019-08-07 13:23:16 +0200981 /* parse content */
Michal Vaskob36053d2020-03-26 15:49:30 +0100982 return yin_parse_content(ctx, subelems, 2, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200983}
984
985/**
David Sedlákc1771b12019-07-10 15:55:46 +0200986 * @brief Parse error-message element.
987 *
David Sedlákbf8a2b72019-08-14 16:48:10 +0200988 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákc1771b12019-07-10 15:55:46 +0200989 * @param[out] value Where the content of error-message element should be stored.
David Sedlákbf8a2b72019-08-14 16:48:10 +0200990 * @param[in,out] exts Extension instances to add to.
David Sedlákc1771b12019-07-10 15:55:46 +0200991 *
992 * @return LY_ERR values.
993 */
994static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +0100995yin_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 +0200996{
David Sedlák968ac342019-07-11 15:17:59 +0200997 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +0200998 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
999 {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
David Sedlák968ac342019-07-11 15:17:59 +02001000 };
David Sedlákc1771b12019-07-10 15:55:46 +02001001
David Sedlákdf2a9732019-08-07 13:23:16 +02001002 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001003 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1004 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 +02001005
Michal Vaskob36053d2020-03-26 15:49:30 +01001006 return yin_parse_content(ctx, subelems, 2, LY_STMT_ERROR_MESSAGE, NULL, exts);
David Sedlákc1771b12019-07-10 15:55:46 +02001007}
1008
1009/**
David Sedlák6542aed2019-08-14 10:47:43 +02001010 * @brief Parse type element.
David Sedlák374d2b32019-07-17 15:06:55 +02001011 *
1012 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák6542aed2019-08-14 10:47:43 +02001013 * @param[in] parent Identification of parent element.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001014 * @param[in,out] type Type to write to.
David Sedlák374d2b32019-07-17 15:06:55 +02001015 *
1016 * @return LY_ERR values.
1017 */
1018static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001019yin_parse_type(struct lys_yin_parser_ctx *ctx, enum ly_stmt parent, struct yin_subelement *subinfo)
David Sedlák374d2b32019-07-17 15:06:55 +02001020{
David Sedlák6542aed2019-08-14 10:47:43 +02001021 struct lysp_type *type = NULL;
Radek Krejcid6b76452019-09-03 17:03:03 +02001022 if (parent == LY_STMT_DEVIATE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001023 *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
Michal Vaskob36053d2020-03-26 15:49:30 +01001024 LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001025 type = *((struct lysp_type **)subinfo->dest);
1026 } else {
1027 type = (struct lysp_type *)subinfo->dest;
1028 }
1029 /* type as child of another type */
Radek Krejcid6b76452019-09-03 17:03:03 +02001030 if (parent == LY_STMT_TYPE) {
David Sedlák6542aed2019-08-14 10:47:43 +02001031 struct lysp_type *nested_type = NULL;
Michal Vaskob36053d2020-03-26 15:49:30 +01001032 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
David Sedlák6542aed2019-08-14 10:47:43 +02001033 type->flags |= LYS_SET_TYPE;
1034 type = nested_type;
1035 }
David Sedlák374d2b32019-07-17 15:06:55 +02001036 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001037 {LY_STMT_BASE, type, 0},
1038 {LY_STMT_BIT, type, 0},
1039 {LY_STMT_ENUM, type, 0},
1040 {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1041 {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1042 {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1043 {LY_STMT_PATTERN, type, 0},
1044 {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1045 {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1046 {LY_STMT_TYPE, type},
1047 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák374d2b32019-07-17 15:06:55 +02001048 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001049
1050 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1051 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1052 return yin_parse_content(ctx, subelems, 11, LY_STMT_TYPE, NULL, &type->exts);
David Sedlák374d2b32019-07-17 15:06:55 +02001053}
1054
David Sedlák1af868e2019-07-17 17:03:14 +02001055/**
1056 * @brief Parse max-elements element.
1057 *
1058 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák1af868e2019-07-17 17:03:14 +02001059 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001060 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +02001061 * @param[in,out] exts Extension instances to add to.
1062 *
1063 * @return LY_ERR values.
1064 */
1065static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001066yin_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 +02001067{
1068 const char *temp_val = NULL;
1069 char *ptr;
1070 unsigned long int num;
1071 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001072 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák1af868e2019-07-17 17:03:14 +02001073 };
David Sedlák374d2b32019-07-17 15:06:55 +02001074
David Sedlák1af868e2019-07-17 17:03:14 +02001075 *flags |= LYS_SET_MAX;
Michal Vaskob36053d2020-03-26 15:49:30 +01001076 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1077 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS));
David Sedlák1af868e2019-07-17 17:03:14 +02001078 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 +02001079 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001080 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001081 return LY_EVALID;
1082 }
1083
1084 if (strcmp(temp_val, "unbounded")) {
1085 errno = 0;
1086 num = strtoul(temp_val, &ptr, 10);
1087 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +02001088 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001089 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001090 return LY_EVALID;
1091 }
1092 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +02001093 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001094 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák1af868e2019-07-17 17:03:14 +02001095 return LY_EVALID;
1096 }
1097 *max = num;
1098 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001099 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1100 return yin_parse_content(ctx, subelems, 1, LY_STMT_MAX_ELEMENTS, NULL, exts);
David Sedlák1af868e2019-07-17 17:03:14 +02001101}
David Sedlák374d2b32019-07-17 15:06:55 +02001102
1103/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001104 * @brief Parse min-elements element.
David Sedlák09e18c92019-07-18 11:17:11 +02001105 *
1106 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák09e18c92019-07-18 11:17:11 +02001107 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +02001108 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +02001109 * @param[in,out] exts Extension instances to add to.
1110 *
1111 * @return LY_ERR values.
1112 */
1113static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001114yin_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 +02001115{
1116 const char *temp_val = NULL;
1117 char *ptr;
1118 unsigned long int num;
1119 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001120 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák09e18c92019-07-18 11:17:11 +02001121 };
1122
1123 *flags |= LYS_SET_MIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01001124 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1125 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 +02001126
1127 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001128 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001129 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001130 return LY_EVALID;
1131 }
1132
1133 errno = 0;
1134 num = strtoul(temp_val, &ptr, 10);
1135 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001136 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001137 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001138 return LY_EVALID;
1139 }
1140 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001141 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
Michal Vaskob36053d2020-03-26 15:49:30 +01001142 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák09e18c92019-07-18 11:17:11 +02001143 return LY_EVALID;
1144 }
1145 *min = num;
Michal Vaskob36053d2020-03-26 15:49:30 +01001146 FREE_STRING(ctx->xmlctx->ctx, temp_val);
1147 return yin_parse_content(ctx, subelems, 1, LY_STMT_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001148}
1149
David Sedláka2dad212019-07-18 12:45:19 +02001150/**
1151 * @brief Parse min-elements or max-elements element.
1152 *
1153 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001154 * @param[in] parent Identification of parent element.
1155 * @param[in] current Identification of current element.
1156 * @param[in] dest Where the parsed value and flags should be stored.
1157 *
1158 * @return LY_ERR values.
1159 */
David Sedlák09e18c92019-07-18 11:17:11 +02001160static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001161yin_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 +02001162{
Radek Krejcid6b76452019-09-03 17:03:03 +02001163 assert(current == LY_STMT_MAX_ELEMENTS || current == LY_STMT_MIN_ELEMENTS);
1164 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 +02001165 uint32_t *lim;
1166 uint16_t *flags;
1167 struct lysp_ext_instance **exts;
1168
Radek Krejcid6b76452019-09-03 17:03:03 +02001169 if (parent == LY_STMT_LEAF_LIST) {
1170 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 +02001171 flags = &((struct lysp_node_leaflist *)dest)->flags;
1172 exts = &((struct lysp_node_leaflist *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001173 } else if (parent == LY_STMT_REFINE) {
1174 lim = (current == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
David Sedlák09e18c92019-07-18 11:17:11 +02001175 flags = &((struct lysp_refine *)dest)->flags;
1176 exts = &((struct lysp_refine *)dest)->exts;
Radek Krejcid6b76452019-09-03 17:03:03 +02001177 } else if (parent == LY_STMT_LIST) {
1178 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 +02001179 flags = &((struct lysp_node_list *)dest)->flags;
1180 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001181 } else {
1182 lim = ((struct minmax_dev_meta *)dest)->lim;
1183 flags = ((struct minmax_dev_meta *)dest)->flags;
1184 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001185 }
1186
Radek Krejcid6b76452019-09-03 17:03:03 +02001187 if (current == LY_STMT_MAX_ELEMENTS) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001188 LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001189 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01001190 LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
David Sedlák09e18c92019-07-18 11:17:11 +02001191 }
1192
1193 return LY_SUCCESS;
1194}
1195
1196/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001197 * @brief Parse ordered-by element.
David Sedláka2dad212019-07-18 12:45:19 +02001198 *
1199 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedláka2dad212019-07-18 12:45:19 +02001200 * @param[out] flags Flags to write to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001201 * @param[in,out] exts Extension instances to add to.
David Sedláka2dad212019-07-18 12:45:19 +02001202 *
1203 * @return LY_ERR values.
1204 */
1205static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001206yin_parse_orderedby(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedláka2dad212019-07-18 12:45:19 +02001207{
1208 const char *temp_val;
1209 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001210 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedláka2dad212019-07-18 12:45:19 +02001211 };
1212
Michal Vaskob36053d2020-03-26 15:49:30 +01001213 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1214 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 +02001215 if (strcmp(temp_val, "system") == 0) {
1216 *flags |= LYS_ORDBY_SYSTEM;
1217 } else if (strcmp(temp_val, "user") == 0) {
1218 *flags |= LYS_ORDBY_USER;
1219 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001220 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1221 "ordered-by", "system", "user");
Michal Vaskob36053d2020-03-26 15:49:30 +01001222 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001223 return LY_EVALID;
1224 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001225 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001226
Michal Vaskob36053d2020-03-26 15:49:30 +01001227 return yin_parse_content(ctx, subelems, 1, LY_STMT_ORDERED_BY, NULL, exts);
David Sedláka2dad212019-07-18 12:45:19 +02001228}
1229
1230/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001231 * @brief Parse any-data or any-xml element.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001232 *
1233 * @param[in,out] ctx YIN parser context for logging and to store current state.
Radek Krejcid6b76452019-09-03 17:03:03 +02001234 * @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 +02001235 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001236 *
1237 * @return LY_ERR values.
1238 */
1239static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001240yin_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 +02001241{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001242 struct lysp_node_anydata *any;
1243
David Sedlák8d552d62019-08-06 15:29:05 +02001244 /* create new sibling */
Michal Vaskob36053d2020-03-26 15:49:30 +01001245 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
Radek Krejcid6b76452019-09-03 17:03:03 +02001246 any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
David Sedlák8a83bbb2019-07-18 14:46:00 +02001247 any->parent = node_meta->parent;
1248
David Sedlákbf8a2b72019-08-14 16:48:10 +02001249 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001250 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1251 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 +02001252
1253 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001254 {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1255 {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1256 {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1257 {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1258 {LY_STMT_MUST, &any->musts, 0},
1259 {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1260 {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1261 {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1262 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8a83bbb2019-07-18 14:46:00 +02001263 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001264 return yin_parse_content(ctx, subelems, 9, any_kw, NULL, &any->exts);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001265}
1266
1267/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001268 * @brief parse leaf element.
1269 *
1270 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001271 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001272 *
1273 * @return LY_ERR values.
1274 */
1275static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001276yin_parse_leaf(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák203ca3a2019-07-18 15:26:25 +02001277{
David Sedlák203ca3a2019-07-18 15:26:25 +02001278 struct lysp_node_leaf *leaf;
1279
David Sedlák8d552d62019-08-06 15:29:05 +02001280 /* create structure new leaf */
Michal Vaskob36053d2020-03-26 15:49:30 +01001281 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
David Sedlák203ca3a2019-07-18 15:26:25 +02001282 leaf->nodetype = LYS_LEAF;
1283 leaf->parent = node_meta->parent;
1284
David Sedlák203ca3a2019-07-18 15:26:25 +02001285 /* parser argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001286 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1287 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 +02001288
1289 /* parse content */
1290 struct yin_subelement subelems[12] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001291 {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1292 {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1293 {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1294 {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1295 {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1296 {LY_STMT_MUST, &leaf->musts, 0},
1297 {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1298 {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1299 {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1300 {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1301 {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1302 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001303 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001304 return yin_parse_content(ctx, subelems, 12, LY_STMT_LEAF, NULL, &leaf->exts);
David Sedlák203ca3a2019-07-18 15:26:25 +02001305}
1306
1307/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001308 * @brief Parse leaf-list element.
1309 *
1310 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001311 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001312 *
1313 * @return LY_ERR values.
1314 */
1315static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001316yin_parse_leaflist(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákc3da3ef2019-07-19 12:56:08 +02001317{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001318 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001319
Michal Vaskob36053d2020-03-26 15:49:30 +01001320 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02001321
David Sedlákc3da3ef2019-07-19 12:56:08 +02001322 llist->nodetype = LYS_LEAFLIST;
1323 llist->parent = node_meta->parent;
1324
David Sedlákc3da3ef2019-07-19 12:56:08 +02001325 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001326 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1327 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 +02001328
1329 /* parse content */
1330 struct yin_subelement subelems[14] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001331 {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1332 {LY_STMT_DEFAULT, &llist->dflts, 0},
1333 {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1334 {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1335 {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1336 {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1337 {LY_STMT_MUST, &llist->musts, 0},
1338 {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1339 {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1340 {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1341 {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1342 {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1343 {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1344 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001345 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001346 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, LY_STMT_LEAF_LIST, NULL, &llist->exts));
David Sedlákc3da3ef2019-07-19 12:56:08 +02001347
David Sedlákbf8a2b72019-08-14 16:48:10 +02001348 /* check invalid combination of subelements */
David Sedlákc3da3ef2019-07-19 12:56:08 +02001349 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001350 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001351 return LY_EVALID;
1352 }
1353 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001354 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001355 return LY_EVALID;
1356 }
1357
1358 return LY_SUCCESS;
1359}
1360
1361/**
David Sedlák04e17b22019-07-19 15:29:48 +02001362 * @brief Parse typedef element.
1363 *
1364 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02001365 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001366 *
1367 * @return LY_ERR values.
1368 */
1369static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001370yin_parse_typedef(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001371{
1372 struct lysp_tpdf *tpdf;
David Sedlákbf8a2b72019-08-14 16:48:10 +02001373 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
Michal Vaskob36053d2020-03-26 15:49:30 +01001374 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001375
1376 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001377 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1378 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
David Sedlák04e17b22019-07-19 15:29:48 +02001379
1380 /* parse content */
1381 struct yin_subelement subelems[7] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001382 {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1383 {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1384 {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1385 {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1386 {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1387 {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1388 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001389 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001390 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
David Sedlák04e17b22019-07-19 15:29:48 +02001391
1392 /* store data for collision check */
Michal Vasko1bf09392020-03-27 12:38:10 +01001393 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_RPC | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
David Sedláke8b74df2019-08-14 14:18:22 +02001394 LY_CHECK_RET(ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0) == -1, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001395 }
1396
1397 return LY_SUCCESS;
1398}
1399
1400/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001401 * @brief Parse refine element.
1402 *
1403 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákd2d676a2019-07-22 11:28:19 +02001404 * @param[in,out] refines Refines to add to.
1405 *
1406 * @return LY_ERR values.
1407 */
1408static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001409yin_parse_refine(struct lys_yin_parser_ctx *ctx, struct lysp_refine **refines)
David Sedlákd2d676a2019-07-22 11:28:19 +02001410{
1411 struct lysp_refine *rf;
1412
1413 /* allocate new refine */
Michal Vaskob36053d2020-03-26 15:49:30 +01001414 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
David Sedlákd2d676a2019-07-22 11:28:19 +02001415
1416 /* parse attribute */
Michal Vaskob36053d2020-03-26 15:49:30 +01001417 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1418 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1419 CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
David Sedlákd2d676a2019-07-22 11:28:19 +02001420
1421 /* parse content */
1422 struct yin_subelement subelems[11] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001423 {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1424 {LY_STMT_DEFAULT, &rf->dflts, 0},
1425 {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1426 {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1427 {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1428 {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1429 {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1430 {LY_STMT_MUST, &rf->musts, 0},
1431 {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1432 {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1433 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001434 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001435 return yin_parse_content(ctx, subelems, 11, LY_STMT_REFINE, NULL, &rf->exts);
David Sedlákd2d676a2019-07-22 11:28:19 +02001436}
1437
1438/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001439 * @brief Parse uses element.
1440 *
1441 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001442 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001443 *
1444 * @return LY_ERR values.
1445 */
1446static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001447yin_parse_uses(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák0d6de5a2019-07-22 13:25:44 +02001448{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001449 struct lysp_node_uses *uses;
1450
David Sedlák8d552d62019-08-06 15:29:05 +02001451 /* create new uses */
Michal Vaskob36053d2020-03-26 15:49:30 +01001452 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001453 uses->nodetype = LYS_USES;
1454 uses->parent = node_meta->parent;
1455
David Sedlák0d6de5a2019-07-22 13:25:44 +02001456 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001457 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1458 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 +02001459
1460 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001461 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001462 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001463 {LY_STMT_AUGMENT, &augments, 0},
1464 {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1465 {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1466 {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1467 {LY_STMT_REFINE, &uses->refines, 0},
1468 {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1469 {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1470 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001471 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001472 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, LY_STMT_USES, NULL, &uses->exts));
David Sedlák0d6de5a2019-07-22 13:25:44 +02001473 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1474
1475 return LY_SUCCESS;
1476}
1477
1478/**
David Sedlákaa854b02019-07-22 14:17:10 +02001479 * @brief Parse revision element.
1480 *
1481 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákaa854b02019-07-22 14:17:10 +02001482 * @param[in,out] revs Parsed revisions to add to.
1483 *
1484 * @return LY_ERR values.
1485 */
1486static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001487yin_parse_revision(struct lys_yin_parser_ctx *ctx, struct lysp_revision **revs)
David Sedlákaa854b02019-07-22 14:17:10 +02001488{
1489 struct lysp_revision *rev;
1490 const char *temp_date = NULL;
1491
1492 /* allocate new reivison */
Michal Vaskob36053d2020-03-26 15:49:30 +01001493 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
David Sedlákaa854b02019-07-22 14:17:10 +02001494
1495 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001496 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1497 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 +02001498 /* check value */
1499 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
Michal Vaskob36053d2020-03-26 15:49:30 +01001500 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001501 return LY_EVALID;
1502 }
1503 strcpy(rev->date, temp_date);
Michal Vaskob36053d2020-03-26 15:49:30 +01001504 FREE_STRING(ctx->xmlctx->ctx, temp_date);
David Sedlákaa854b02019-07-22 14:17:10 +02001505
1506 /* parse content */
1507 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001508 {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1509 {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1510 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001511 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001512 return yin_parse_content(ctx, subelems, 3, LY_STMT_REVISION, NULL, &rev->exts);
David Sedlákaa854b02019-07-22 14:17:10 +02001513}
1514
David Sedlák5e13dea2019-07-22 16:06:45 +02001515/**
1516 * @brief Parse include element.
1517 *
1518 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001519 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1520 *
1521 * @return LY_ERR values.
1522 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001523static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001524yin_parse_include(struct lys_yin_parser_ctx *ctx, struct include_meta *inc_meta)
David Sedlák0c2bab92019-07-22 15:33:19 +02001525{
1526 struct lysp_include *inc;
1527
1528 /* allocate new include */
Michal Vaskob36053d2020-03-26 15:49:30 +01001529 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
David Sedlák0c2bab92019-07-22 15:33:19 +02001530
1531 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001532 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1533 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 +02001534
1535 /* submodules share the namespace with the module names, so there must not be
1536 * a module of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01001537 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 +02001538 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001539 return LY_EVALID;
1540 }
1541
1542 /* parse content */
1543 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001544 {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1545 {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1546 {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1547 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák0c2bab92019-07-22 15:33:19 +02001548 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001549 return yin_parse_content(ctx, subelems, 4, LY_STMT_INCLUDE, NULL, &inc->exts);
David Sedlák0c2bab92019-07-22 15:33:19 +02001550}
1551
David Sedlákaa854b02019-07-22 14:17:10 +02001552/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02001553 * @brief Parse revision-date element.
David Sedlákdfbbb442019-08-06 16:33:21 +02001554 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001555 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001556 * @param[in,out] rev Array to store the parsed value in.
1557 * @param[in,out] exts Extension instances to add to.
1558 *
1559 * @return LY_ERR values.
1560 */
1561static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001562yin_parse_revision_date(struct lys_yin_parser_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001563{
1564 const char *temp_rev;
1565 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001566 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001567 };
1568
Michal Vaskob36053d2020-03-26 15:49:30 +01001569 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1570 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 +02001571 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 +01001572 FREE_STRING(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
David Sedlákdfbbb442019-08-06 16:33:21 +02001573
1574 strcpy(rev, temp_rev);
Michal Vaskob36053d2020-03-26 15:49:30 +01001575 FREE_STRING(ctx->xmlctx->ctx, temp_rev);
David Sedlákdfbbb442019-08-06 16:33:21 +02001576
Michal Vaskob36053d2020-03-26 15:49:30 +01001577 return yin_parse_content(ctx, subelems, 1, LY_STMT_REVISION_DATE, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001578}
1579
1580/**
1581 * @brief Parse config element.
1582 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001583 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001584 * @param[in,out] flags Flags to add to.
1585 * @param[in,out] exts Extension instances to add to.
1586 *
1587 * @return LY_ERR values.
1588 */
1589static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001590yin_parse_config(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001591{
1592 const char *temp_val = NULL;
1593 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001594 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001595 };
1596
Michal Vaskob36053d2020-03-26 15:49:30 +01001597 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1598 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 +02001599 if (strcmp(temp_val, "true") == 0) {
1600 *flags |= LYS_CONFIG_W;
1601 } else if (strcmp(temp_val, "false") == 0) {
1602 *flags |= LYS_CONFIG_R;
1603 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001604 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1605 "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001606 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001607 return LY_EVALID;
1608 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001609 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001610
Michal Vaskob36053d2020-03-26 15:49:30 +01001611 return yin_parse_content(ctx, subelems, 1, LY_STMT_CONFIG, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001612}
1613
1614/**
1615 * @brief Parse yang-version element.
1616 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001617 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001618 * @param[out] version Storage for the parsed information.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001619 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001620 *
1621 * @return LY_ERR values.
1622 */
1623static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001624yin_parse_yangversion(struct lys_yin_parser_ctx *ctx, uint8_t *version, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001625{
1626 const char *temp_version = NULL;
1627 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001628 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001629 };
1630
Michal Vaskob36053d2020-03-26 15:49:30 +01001631 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1632 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
David Sedlákdfbbb442019-08-06 16:33:21 +02001633 if (strcmp(temp_version, "1.0") == 0) {
1634 *version = LYS_VERSION_1_0;
1635 } else if (strcmp(temp_version, "1.1") == 0) {
1636 *version = LYS_VERSION_1_1;
1637 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001638 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1639 "yang-version", "1.0", "1.1");
Michal Vaskob36053d2020-03-26 15:49:30 +01001640 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001641 return LY_EVALID;
1642 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001643 FREE_STRING(ctx->xmlctx->ctx, temp_version);
David Sedlákdfbbb442019-08-06 16:33:21 +02001644 ctx->mod_version = *version;
1645
Michal Vaskob36053d2020-03-26 15:49:30 +01001646 return yin_parse_content(ctx, subelems, 1, LY_STMT_YANG_VERSION, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001647}
1648
1649/**
1650 * @brief Parse import element.
1651 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001652 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001653 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1654 *
1655 * @return LY_ERR values.
1656 */
1657static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001658yin_parse_import(struct lys_yin_parser_ctx *ctx, struct import_meta *imp_meta)
David Sedlákdfbbb442019-08-06 16:33:21 +02001659{
1660 struct lysp_import *imp;
1661 /* allocate new element in sized array for import */
Michal Vaskob36053d2020-03-26 15:49:30 +01001662 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlákdfbbb442019-08-06 16:33:21 +02001663
1664 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001665 {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1666 {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1667 {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1668 {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1669 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001670 };
1671
1672 /* parse import attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01001673 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1674 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
1675 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, LY_STMT_IMPORT, NULL, &imp->exts));
David Sedlákdfbbb442019-08-06 16:33:21 +02001676 /* check prefix validity */
1677 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1678
1679 return LY_SUCCESS;
1680}
1681
1682/**
1683 * @brief Parse mandatory element.
1684 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001685 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001686 * @param[in,out] flags Flags to add to.
1687 * @param[in,out] exts Extension instances to add to.
1688 *
1689 * @return LY_ERR values.
1690 */
1691static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001692yin_parse_mandatory(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001693{
1694 const char *temp_val = NULL;
1695 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001696 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001697 };
1698
Michal Vaskob36053d2020-03-26 15:49:30 +01001699 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1700 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 +02001701 if (strcmp(temp_val, "true") == 0) {
1702 *flags |= LYS_MAND_TRUE;
1703 } else if (strcmp(temp_val, "false") == 0) {
1704 *flags |= LYS_MAND_FALSE;
1705 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001706 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1707 "mandatory", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001708 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001709 return LY_EVALID;
1710 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001711 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001712
Michal Vaskob36053d2020-03-26 15:49:30 +01001713 return yin_parse_content(ctx, subelems, 1, LY_STMT_MANDATORY, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001714}
1715
1716/**
1717 * @brief Parse status element.
1718 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001719 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001720 * @param[in,out] flags Flags to add to.
1721 * @param[in,out] exts Extension instances to add to.
1722 *
1723 * @return LY_ERR values.
1724 */
1725static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001726yin_parse_status(struct lys_yin_parser_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlákdfbbb442019-08-06 16:33:21 +02001727{
1728 const char *value = NULL;
1729 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001730 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001731 };
1732
Michal Vaskob36053d2020-03-26 15:49:30 +01001733 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1734 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 +02001735 if (strcmp(value, "current") == 0) {
1736 *flags |= LYS_STATUS_CURR;
1737 } else if (strcmp(value, "deprecated") == 0) {
1738 *flags |= LYS_STATUS_DEPRC;
1739 } else if (strcmp(value, "obsolete") == 0) {
1740 *flags |= LYS_STATUS_OBSLT;
1741 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001742 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
1743 "status", "current", "deprecated", "obsolete");
Michal Vaskob36053d2020-03-26 15:49:30 +01001744 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001745 return LY_EVALID;
1746 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001747 FREE_STRING(ctx->xmlctx->ctx, value);
David Sedlákdfbbb442019-08-06 16:33:21 +02001748
Michal Vaskob36053d2020-03-26 15:49:30 +01001749 return yin_parse_content(ctx, subelems, 1, LY_STMT_STATUS, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001750}
1751
1752/**
1753 * @brief Parse when element.
1754 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001755 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001756 * @param[out] when_p When pointer to parse to.
1757 */
1758static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001759yin_parse_when(struct lys_yin_parser_ctx *ctx, struct lysp_when **when_p)
David Sedlákdfbbb442019-08-06 16:33:21 +02001760{
1761 struct lysp_when *when;
David Sedláka56e0012019-08-15 13:21:25 +02001762 LY_ERR ret = LY_SUCCESS;
1763
David Sedlákdfbbb442019-08-06 16:33:21 +02001764 when = calloc(1, sizeof *when);
Michal Vaskob36053d2020-03-26 15:49:30 +01001765 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
Radek Krejcif6923e82020-07-02 16:36:53 +02001766
1767 ret = lyxml_ctx_next(ctx->xmlctx);
1768 LY_CHECK_ERR_RET(ret, free(when), ret);
1769
Michal Vaskob36053d2020-03-26 15:49:30 +01001770 ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
David Sedláka56e0012019-08-15 13:21:25 +02001771 LY_CHECK_ERR_RET(ret, free(when), ret);
1772
David Sedlákdfbbb442019-08-06 16:33:21 +02001773 *when_p = when;
1774 struct yin_subelement subelems[3] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001775 {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1776 {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1777 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001778 };
1779
Michal Vaskob36053d2020-03-26 15:49:30 +01001780 return yin_parse_content(ctx, subelems, 3, LY_STMT_WHEN, NULL, &when->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001781}
1782
1783/**
1784 * @brief Parse yin-elemenet element.
1785 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001786 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001787 * @param[in,out] data Data to read from, always moved to currently handled position.
1788 * @param[in,out] flags Flags to add to.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001789 * @prama[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001790 *
1791 * @return LY_ERR values.
1792 */
1793static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001794yin_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 +02001795{
1796 const char *temp_val = NULL;
1797 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001798 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001799 };
1800
Michal Vaskob36053d2020-03-26 15:49:30 +01001801 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1802 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 +02001803 if (strcmp(temp_val, "true") == 0) {
1804 *flags |= LYS_YINELEM_TRUE;
1805 } else if (strcmp(temp_val, "false") == 0) {
1806 *flags |= LYS_YINELEM_FALSE;
1807 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02001808 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1809 "yin-element", "true", "false");
Michal Vaskob36053d2020-03-26 15:49:30 +01001810 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001811 return LY_EVALID;
1812 }
Michal Vaskob36053d2020-03-26 15:49:30 +01001813 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlákdfbbb442019-08-06 16:33:21 +02001814
Michal Vaskob36053d2020-03-26 15:49:30 +01001815 return yin_parse_content(ctx, subelems, 1, LY_STMT_YIN_ELEMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001816}
1817
1818/**
1819 * @brief Parse argument element.
1820 *
Michal Vaskob36053d2020-03-26 15:49:30 +01001821 * @param[in,out] xmlctx Xml context.
David Sedlákbf8a2b72019-08-14 16:48:10 +02001822 * @param[in,out] arg_meta Meta information about destionation of parsed data.
1823 * @param[in,out] exts Extension instances to add to.
David Sedlákdfbbb442019-08-06 16:33:21 +02001824 *
1825 * @return LY_ERR values.
1826 */
1827static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001828yin_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 +02001829{
1830 struct yin_subelement subelems[2] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001831 {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1832 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001833 };
1834
Michal Vaskob36053d2020-03-26 15:49:30 +01001835 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1836 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 +02001837
Michal Vaskob36053d2020-03-26 15:49:30 +01001838 return yin_parse_content(ctx, subelems, 2, LY_STMT_ARGUMENT, NULL, exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001839}
1840
1841/**
1842 * @brief Parse the extension statement.
1843 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02001844 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákdfbbb442019-08-06 16:33:21 +02001845 * @param[in,out] extensions Extensions to add to.
1846 *
1847 * @return LY_ERR values.
1848 */
1849static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001850yin_parse_extension(struct lys_yin_parser_ctx *ctx, struct lysp_ext **extensions)
David Sedlákdfbbb442019-08-06 16:33:21 +02001851{
1852 struct lysp_ext *ex;
Michal Vaskob36053d2020-03-26 15:49:30 +01001853 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
1854 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1855 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 +02001856
1857 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1858 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001859 {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1860 {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1861 {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1862 {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1863 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlákdfbbb442019-08-06 16:33:21 +02001864 };
1865
Michal Vaskob36053d2020-03-26 15:49:30 +01001866 return yin_parse_content(ctx, subelems, 5, LY_STMT_EXTENSION, NULL, &ex->exts);
David Sedlákdfbbb442019-08-06 16:33:21 +02001867}
1868
1869/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001870 * @brief Parse feature element.
1871 *
1872 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák5e13dea2019-07-22 16:06:45 +02001873 * @param[in,out] features Features to add to.
1874 *
1875 * @return LY_ERR values.
1876 */
1877static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001878yin_parse_feature(struct lys_yin_parser_ctx *ctx, struct lysp_feature **features)
David Sedlák5e13dea2019-07-22 16:06:45 +02001879{
1880 struct lysp_feature *feat;
1881
1882 /* allocate new feature */
Michal Vaskob36053d2020-03-26 15:49:30 +01001883 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
David Sedlák5e13dea2019-07-22 16:06:45 +02001884
1885 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001886 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1887 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 +02001888
1889 /* parse content */
1890 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001891 {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1892 {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
1893 {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1894 {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1895 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák5e13dea2019-07-22 16:06:45 +02001896 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001897 return yin_parse_content(ctx, subelems, 5, LY_STMT_FEATURE, NULL, &feat->exts);
David Sedlák5e13dea2019-07-22 16:06:45 +02001898}
1899
1900/**
David Sedlák28794f22019-07-22 16:45:00 +02001901 * @brief Parse identity element.
1902 *
1903 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák28794f22019-07-22 16:45:00 +02001904 * @param[in,out] identities Identities to add to.
1905 *
1906 * @return LY_ERR values.
1907 */
1908static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001909yin_parse_identity(struct lys_yin_parser_ctx *ctx, struct lysp_ident **identities)
David Sedlák28794f22019-07-22 16:45:00 +02001910{
1911 struct lysp_ident *ident;
1912
1913 /* allocate new identity */
Michal Vaskob36053d2020-03-26 15:49:30 +01001914 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
David Sedlák28794f22019-07-22 16:45:00 +02001915
1916 /* parse argument */
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, &ident->name, Y_IDENTIF_ARG, LY_STMT_IDENTITY));
David Sedlák28794f22019-07-22 16:45:00 +02001919
1920 /* parse content */
1921 struct yin_subelement subelems[6] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02001922 {LY_STMT_BASE, &ident->bases, 0},
1923 {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1924 {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1925 {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1926 {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1927 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák28794f22019-07-22 16:45:00 +02001928 };
Michal Vaskob36053d2020-03-26 15:49:30 +01001929 return yin_parse_content(ctx, subelems, 6, LY_STMT_IDENTITY, NULL, &ident->exts);
David Sedlák28794f22019-07-22 16:45:00 +02001930}
1931
1932/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001933 * @brief Parse list element.
1934 *
1935 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02001936 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001937 *
1938 * @return LY_ERR values.
1939 */
1940static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01001941yin_parse_list(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001942{
David Sedlákaf536aa2019-07-23 13:42:23 +02001943 struct lysp_node_list *list;
David Sedlák81497a32019-08-13 16:56:26 +02001944 LY_ERR ret = LY_SUCCESS;
1945 struct yin_subelement *subelems = NULL;
David Sedlákaf536aa2019-07-23 13:42:23 +02001946
Michal Vaskob36053d2020-03-26 15:49:30 +01001947 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
David Sedlákaf536aa2019-07-23 13:42:23 +02001948 list->nodetype = LYS_LIST;
1949 list->parent = node_meta->parent;
1950
David Sedlákaf536aa2019-07-23 13:42:23 +02001951 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01001952 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1953 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 +02001954
1955 /* parse list content */
David Sedlák81497a32019-08-13 16:56:26 +02001956 LY_CHECK_RET(subelems_allocator(ctx, 25, (struct lysp_node *)list, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02001957 LY_STMT_ACTION, &list->actions, 0,
1958 LY_STMT_ANYDATA, &list->child, 0,
1959 LY_STMT_ANYXML, &list->child, 0,
1960 LY_STMT_CHOICE, &list->child, 0,
1961 LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
1962 LY_STMT_CONTAINER, &list->child, 0,
1963 LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
1964 LY_STMT_GROUPING, &list->groupings, 0,
1965 LY_STMT_IF_FEATURE, &list->iffeatures, 0,
1966 LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
1967 LY_STMT_LEAF, &list->child, 0,
1968 LY_STMT_LEAF_LIST, &list->child, 0,
1969 LY_STMT_LIST, &list->child, 0,
1970 LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1971 LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
1972 LY_STMT_MUST, &list->musts, 0,
1973 LY_STMT_NOTIFICATION, &list->notifs, 0,
1974 LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
1975 LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
1976 LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
1977 LY_STMT_TYPEDEF, &list->typedefs, 0,
1978 LY_STMT_UNIQUE, &list->uniques, 0,
1979 LY_STMT_USES, &list->child, 0,
1980 LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
1981 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02001982 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01001983 ret = yin_parse_content(ctx, subelems, 25, LY_STMT_LIST, NULL, &list->exts);
David Sedlák81497a32019-08-13 16:56:26 +02001984 subelems_deallocator(25, subelems);
1985 LY_CHECK_RET(ret);
David Sedlákaf536aa2019-07-23 13:42:23 +02001986
1987 /* finalize parent pointers to the reallocated items */
1988 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1989
1990 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001991 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001992 return LY_EVALID;
1993 }
1994
1995 return LY_SUCCESS;
1996}
1997
1998/**
David Sedlák031b9e72019-07-23 15:19:37 +02001999 * @brief Parse notification element.
2000 *
2001 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák05404f62019-07-24 14:11:53 +02002002 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02002003 *
2004 * @return LY_ERR values.
2005 */
2006static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002007yin_parse_notification(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02002008{
2009 struct lysp_notif *notif;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002010 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002011 LY_ERR ret = LY_SUCCESS;
2012 struct yin_subelement *subelems = NULL;
David Sedlák031b9e72019-07-23 15:19:37 +02002013
2014 /* allocate new notification */
Michal Vaskob36053d2020-03-26 15:49:30 +01002015 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02002016 notif->nodetype = LYS_NOTIF;
2017 notif->parent = notif_meta->parent;
2018
2019 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002020 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2021 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
David Sedlák031b9e72019-07-23 15:19:37 +02002022
2023 /* parse notification content */
David Sedlák81497a32019-08-13 16:56:26 +02002024 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)notif, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002025 LY_STMT_ANYDATA, &notif->data, 0,
2026 LY_STMT_ANYXML, &notif->data, 0,
2027 LY_STMT_CHOICE, &notif->data, 0,
2028 LY_STMT_CONTAINER, &notif->data, 0,
2029 LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2030 LY_STMT_GROUPING, &notif->groupings, 0,
2031 LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2032 LY_STMT_LEAF, &notif->data, 0,
2033 LY_STMT_LEAF_LIST, &notif->data, 0,
2034 LY_STMT_LIST, &notif->data, 0,
2035 LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2036 LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2037 LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2038 LY_STMT_TYPEDEF, &notif->typedefs, 0,
2039 LY_STMT_USES, &notif->data, 0,
2040 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002041 ));
2042
Michal Vaskob36053d2020-03-26 15:49:30 +01002043 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_NOTIFICATION, NULL, &notif->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002044 subelems_deallocator(16, subelems);
2045 LY_CHECK_RET(ret);
David Sedlák031b9e72019-07-23 15:19:37 +02002046
2047 /* finalize parent pointers to the reallocated items */
2048 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
2049
2050 return LY_SUCCESS;
2051}
2052
2053/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002054 * @brief Parse grouping element.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002055 *
2056 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002057 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02002058 *
2059 * @return LY_ERR values.
2060 */
2061static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002062yin_parse_grouping(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02002063{
2064 struct lysp_grp *grp;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002065 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002066 LY_ERR ret = LY_SUCCESS;
2067 struct yin_subelement *subelems = NULL;
David Sedláke3ce9ef2019-07-23 16:34:30 +02002068
2069 /* create new grouping */
Michal Vaskob36053d2020-03-26 15:49:30 +01002070 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02002071 grp->nodetype = LYS_GROUPING;
2072 grp->parent = gr_meta->parent;
2073
2074 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002075 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2076 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 +02002077
2078 /* parse grouping content */
David Sedlák81497a32019-08-13 16:56:26 +02002079 LY_CHECK_RET(subelems_allocator(ctx, 16, (struct lysp_node *)grp, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002080 LY_STMT_ACTION, &grp->actions, 0,
2081 LY_STMT_ANYDATA, &grp->data, 0,
2082 LY_STMT_ANYXML, &grp->data, 0,
2083 LY_STMT_CHOICE, &grp->data, 0,
2084 LY_STMT_CONTAINER, &grp->data, 0,
2085 LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2086 LY_STMT_GROUPING, &grp->groupings, 0,
2087 LY_STMT_LEAF, &grp->data, 0,
2088 LY_STMT_LEAF_LIST, &grp->data, 0,
2089 LY_STMT_LIST, &grp->data, 0,
2090 LY_STMT_NOTIFICATION, &grp->notifs, 0,
2091 LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2092 LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2093 LY_STMT_TYPEDEF, &grp->typedefs, 0,
2094 LY_STMT_USES, &grp->data, 0,
2095 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002096 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002097 ret = yin_parse_content(ctx, subelems, 16, LY_STMT_GROUPING, NULL, &grp->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002098 subelems_deallocator(16, subelems);
2099 LY_CHECK_RET(ret);
2100
David Sedláke3ce9ef2019-07-23 16:34:30 +02002101 /* finalize parent pointers to the reallocated items */
2102 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2103
2104 return LY_SUCCESS;
2105}
2106
2107/**
David Sedlákbf8a2b72019-08-14 16:48:10 +02002108 * @brief Parse container element.
David Sedlákf111bcb2019-07-23 17:15:51 +02002109 *
2110 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002111 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002112 *
2113 * @return LY_ERR values.
2114 */
2115static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002116yin_parse_container(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákf111bcb2019-07-23 17:15:51 +02002117{
David Sedlákf111bcb2019-07-23 17:15:51 +02002118 struct lysp_node_container *cont;
David Sedlák81497a32019-08-13 16:56:26 +02002119 LY_ERR ret = LY_SUCCESS;
2120 struct yin_subelement *subelems = NULL;
David Sedlákf111bcb2019-07-23 17:15:51 +02002121
2122 /* create new container */
Michal Vaskob36053d2020-03-26 15:49:30 +01002123 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
David Sedlákf111bcb2019-07-23 17:15:51 +02002124 cont->nodetype = LYS_CONTAINER;
2125 cont->parent = node_meta->parent;
2126
David Sedlákf111bcb2019-07-23 17:15:51 +02002127 /* parse aegument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002128 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2129 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 +02002130
2131 /* parse container content */
David Sedlák81497a32019-08-13 16:56:26 +02002132 LY_CHECK_RET(subelems_allocator(ctx, 21, (struct lysp_node *)cont, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002133 LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2134 LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2135 LY_STMT_ANYXML, &cont->child, 0,
2136 LY_STMT_CHOICE, &cont->child, 0,
2137 LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2138 LY_STMT_CONTAINER, &cont->child, 0,
2139 LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2140 LY_STMT_GROUPING, &cont->groupings, 0,
2141 LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2142 LY_STMT_LEAF, &cont->child, 0,
2143 LY_STMT_LEAF_LIST, &cont->child, 0,
2144 LY_STMT_LIST, &cont->child, 0,
2145 LY_STMT_MUST, &cont->musts, 0,
2146 LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2147 LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2148 LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2149 LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2150 LY_STMT_TYPEDEF, &cont->typedefs, 0,
2151 LY_STMT_USES, &cont->child, 0,
2152 LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2153 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002154 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002155 ret = yin_parse_content(ctx, subelems, 21, LY_STMT_CONTAINER, NULL, &cont->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002156 subelems_deallocator(21, subelems);
2157 LY_CHECK_RET(ret);
2158
David Sedlákf111bcb2019-07-23 17:15:51 +02002159 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2160
2161 return LY_SUCCESS;
2162}
2163
2164/**
David Sedlák5379d392019-07-24 10:42:03 +02002165 * @brief Parse case element.
2166 *
2167 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002168 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002169 *
2170 * @return LY_ERR values.
2171 */
2172static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002173yin_parse_case(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlák5379d392019-07-24 10:42:03 +02002174{
David Sedlák5379d392019-07-24 10:42:03 +02002175 struct lysp_node_case *cas;
David Sedlák81497a32019-08-13 16:56:26 +02002176 LY_ERR ret = LY_SUCCESS;
2177 struct yin_subelement *subelems = NULL;;
David Sedlák5379d392019-07-24 10:42:03 +02002178
2179 /* create new case */
Michal Vaskob36053d2020-03-26 15:49:30 +01002180 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
David Sedlák5379d392019-07-24 10:42:03 +02002181 cas->nodetype = LYS_CASE;
2182 cas->parent = node_meta->parent;
2183
David Sedlák5379d392019-07-24 10:42:03 +02002184 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002185 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2186 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 +02002187
2188 /* parse case content */
David Sedlák81497a32019-08-13 16:56:26 +02002189 LY_CHECK_RET(subelems_allocator(ctx, 14, (struct lysp_node *)cas, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002190 LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2191 LY_STMT_ANYXML, &cas->child, 0,
2192 LY_STMT_CHOICE, &cas->child, 0,
2193 LY_STMT_CONTAINER, &cas->child, 0,
2194 LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2195 LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2196 LY_STMT_LEAF, &cas->child, 0,
2197 LY_STMT_LEAF_LIST, &cas->child, 0,
2198 LY_STMT_LIST, &cas->child, 0,
2199 LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2200 LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2201 LY_STMT_USES, &cas->child, 0,
2202 LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2203 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002204 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002205 ret = yin_parse_content(ctx, subelems, 14, LY_STMT_CASE, NULL, &cas->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002206 subelems_deallocator(14, subelems);
2207
2208 return ret;
David Sedlák5379d392019-07-24 10:42:03 +02002209}
2210
2211/**
David Sedlák05404f62019-07-24 14:11:53 +02002212 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002213 *
2214 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákad83cf92019-08-13 12:53:53 +02002215 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002216 *
2217 * @return LY_ERR values.
2218 */
2219LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002220yin_parse_choice(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *node_meta)
David Sedlákb7abcfa2019-07-24 12:33:35 +02002221{
David Sedlák81497a32019-08-13 16:56:26 +02002222 LY_ERR ret = LY_SUCCESS;
2223 struct yin_subelement *subelems = NULL;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002224 struct lysp_node_choice *choice;
2225
2226 /* create new choice */
Michal Vaskob36053d2020-03-26 15:49:30 +01002227 LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
David Sedlák8d552d62019-08-06 15:29:05 +02002228
David Sedlákb7abcfa2019-07-24 12:33:35 +02002229 choice->nodetype = LYS_CHOICE;
2230 choice->parent = node_meta->parent;
2231
David Sedlákb7abcfa2019-07-24 12:33:35 +02002232 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002233 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2234 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, LY_STMT_CHOICE));
David Sedlákb7abcfa2019-07-24 12:33:35 +02002235
2236 /* parse choice content */
David Sedlák81497a32019-08-13 16:56:26 +02002237 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)choice, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002238 LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2239 LY_STMT_ANYXML, &choice->child, 0,
2240 LY_STMT_CASE, &choice->child, 0,
2241 LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2242 LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2243 LY_STMT_CONTAINER, &choice->child, 0,
2244 LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2245 LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2246 LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2247 LY_STMT_LEAF, &choice->child, 0,
2248 LY_STMT_LEAF_LIST, &choice->child, 0,
2249 LY_STMT_LIST, &choice->child, 0,
2250 LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2251 LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2252 LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2253 LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2254 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002255 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002256 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_CHOICE, NULL, &choice->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002257 subelems_deallocator(17, subelems);
2258 return ret;
David Sedlákb7abcfa2019-07-24 12:33:35 +02002259}
2260
2261/**
David Sedlák05404f62019-07-24 14:11:53 +02002262 * @brief Parse input or output element.
2263 *
2264 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbf8a2b72019-08-14 16:48:10 +02002265 * @param[in] inout_kw Identification of input/output element.
David Sedlák05404f62019-07-24 14:11:53 +02002266 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2267 *
2268 * @return LY_ERR values.
2269 */
2270static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002271yin_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 +02002272{
David Sedlák81497a32019-08-13 16:56:26 +02002273 LY_ERR ret = LY_SUCCESS;
2274 struct yin_subelement *subelems = NULL;
2275
David Sedlák05404f62019-07-24 14:11:53 +02002276 /* initiate structure */
Radek Krejcid6b76452019-09-03 17:03:03 +02002277 inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
David Sedlák05404f62019-07-24 14:11:53 +02002278 inout_meta->inout_p->parent = inout_meta->parent;
2279
2280 /* check attributes */
Michal Vaskob36053d2020-03-26 15:49:30 +01002281 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2282 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 +02002283
2284 /* parser input/output content */
David Sedlák81497a32019-08-13 16:56:26 +02002285 LY_CHECK_RET(subelems_allocator(ctx, 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002286 LY_STMT_ANYDATA, &inout_meta->inout_p->data, YIN_SUBELEM_VER2,
2287 LY_STMT_ANYXML, &inout_meta->inout_p->data, 0,
2288 LY_STMT_CHOICE, &inout_meta->inout_p->data, 0,
2289 LY_STMT_CONTAINER, &inout_meta->inout_p->data, 0,
2290 LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2291 LY_STMT_LEAF, &inout_meta->inout_p->data, 0,
2292 LY_STMT_LEAF_LIST, &inout_meta->inout_p->data, 0,
2293 LY_STMT_LIST, &inout_meta->inout_p->data, 0,
2294 LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2295 LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2296 LY_STMT_USES, &inout_meta->inout_p->data, 0,
2297 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002298 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002299 ret = yin_parse_content(ctx, subelems, 12, inout_kw, NULL, &inout_meta->inout_p->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002300 subelems_deallocator(12, subelems);
2301 LY_CHECK_RET(ret);
David Sedlák05404f62019-07-24 14:11:53 +02002302
Michal Vaskob83af8a2020-01-06 09:49:22 +01002303 if (!inout_meta->inout_p->data) {
2304 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", ly_stmt2str(inout_kw));
2305 return LY_EVALID;
2306 }
2307
David Sedlák05404f62019-07-24 14:11:53 +02002308 /* finalize parent pointers to the reallocated items */
David Sedlák81497a32019-08-13 16:56:26 +02002309 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 +02002310
2311 return LY_SUCCESS;
2312}
2313
David Sedlák992fb7c2019-07-24 16:51:01 +02002314/**
2315 * @brief Parse action element.
2316 *
2317 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002318 * @param[in] act_meta Meta information about parent node and actions to add to.
2319 *
2320 * @return LY_ERR values.
2321 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002322static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002323yin_parse_action(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002324{
David Sedlákbf8a2b72019-08-14 16:48:10 +02002325 struct lysp_action *act, **acts = (struct lysp_action **)act_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002326 LY_ERR ret = LY_SUCCESS;
2327 struct yin_subelement *subelems = NULL;
David Sedlák85d0eca2019-07-24 15:15:21 +02002328
2329 /* create new action */
Michal Vaskob36053d2020-03-26 15:49:30 +01002330 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *acts, act, LY_EMEM);
Michal Vasko1bf09392020-03-27 12:38:10 +01002331 act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
David Sedlák85d0eca2019-07-24 15:15:21 +02002332 act->parent = act_meta->parent;
2333
2334 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002335 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2336 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 +02002337
2338 /* parse content */
David Sedlák81497a32019-08-13 16:56:26 +02002339 LY_CHECK_RET(subelems_allocator(ctx, 9, (struct lysp_node *)act, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002340 LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2341 LY_STMT_GROUPING, &act->groupings, 0,
2342 LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2343 LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2344 LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2345 LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2346 LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2347 LY_STMT_TYPEDEF, &act->typedefs, 0,
2348 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002349 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002350 ret = (yin_parse_content(ctx, subelems, 9, LY_STMT_ACTION, NULL, &act->exts));
David Sedlák81497a32019-08-13 16:56:26 +02002351 subelems_deallocator(9, subelems);
2352 LY_CHECK_RET(ret);
2353
David Sedlák85d0eca2019-07-24 15:15:21 +02002354 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2355
2356 return LY_SUCCESS;
2357}
2358
David Sedlák05404f62019-07-24 14:11:53 +02002359/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002360 * @brief Parse augment element.
2361 *
2362 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák992fb7c2019-07-24 16:51:01 +02002363 * @param[in] aug_meta Meta information about parent node and augments to add to.
2364 *
2365 * @return LY_ERR values.
2366 */
2367static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002368yin_parse_augment(struct lys_yin_parser_ctx *ctx, struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002369{
2370 struct lysp_augment *aug;
David Sedlákbf8a2b72019-08-14 16:48:10 +02002371 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->nodes;
David Sedlák81497a32019-08-13 16:56:26 +02002372 LY_ERR ret = LY_SUCCESS;
2373 struct yin_subelement *subelems = NULL;
David Sedlák992fb7c2019-07-24 16:51:01 +02002374
2375 /* create new augment */
Michal Vaskob36053d2020-03-26 15:49:30 +01002376 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002377 aug->nodetype = LYS_AUGMENT;
2378 aug->parent = aug_meta->parent;
2379
2380 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002381 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2382 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2383 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
David Sedlák992fb7c2019-07-24 16:51:01 +02002384
2385 /* parser augment content */
David Sedlák81497a32019-08-13 16:56:26 +02002386 LY_CHECK_RET(subelems_allocator(ctx, 17, (struct lysp_node *)aug, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02002387 LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2388 LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2389 LY_STMT_ANYXML, &aug->child, 0,
2390 LY_STMT_CASE, &aug->child, 0,
2391 LY_STMT_CHOICE, &aug->child, 0,
2392 LY_STMT_CONTAINER, &aug->child, 0,
2393 LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2394 LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2395 LY_STMT_LEAF, &aug->child, 0,
2396 LY_STMT_LEAF_LIST, &aug->child, 0,
2397 LY_STMT_LIST, &aug->child, 0,
2398 LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2399 LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2400 LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2401 LY_STMT_USES, &aug->child, 0,
2402 LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2403 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02002404 ));
Michal Vaskob36053d2020-03-26 15:49:30 +01002405 ret = yin_parse_content(ctx, subelems, 17, LY_STMT_AUGMENT, NULL, &aug->exts);
David Sedlák81497a32019-08-13 16:56:26 +02002406 subelems_deallocator(17, subelems);
2407 LY_CHECK_RET(ret);
David Sedlák992fb7c2019-07-24 16:51:01 +02002408
2409 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2410
2411 return LY_SUCCESS;
2412}
2413
David Sedlák8b754462019-07-25 16:22:13 +02002414/**
2415 * @brief Parse deviate element.
2416 *
2417 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002418 * @param[in] deviates Deviates to add to.
2419 *
2420 * @return LY_ERR values.
2421 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002422static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002423yin_parse_deviate(struct lys_yin_parser_ctx *ctx, struct lysp_deviate **deviates)
David Sedlák4ffcec82019-07-25 15:10:21 +02002424{
2425 LY_ERR ret = LY_SUCCESS;
2426 uint8_t dev_mod;
2427 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002428 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002429 struct lysp_deviate_add *d_add = NULL;
2430 struct lysp_deviate_rpl *d_rpl = NULL;
2431 struct lysp_deviate_del *d_del = NULL;
2432
2433 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002434 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2435 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 +02002436
2437 if (strcmp(temp_val, "not-supported") == 0) {
2438 dev_mod = LYS_DEV_NOT_SUPPORTED;
2439 } else if (strcmp(temp_val, "add") == 0) {
2440 dev_mod = LYS_DEV_ADD;
2441 } else if (strcmp(temp_val, "replace") == 0) {
2442 dev_mod = LYS_DEV_REPLACE;
2443 } else if (strcmp(temp_val, "delete") == 0) {
2444 dev_mod = LYS_DEV_DELETE;
2445 } else {
David Sedlák26ea1432019-08-14 13:42:23 +02002446 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2447 "not-supported", "add", "replace", "delete");
Michal Vaskob36053d2020-03-26 15:49:30 +01002448 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002449 return LY_EVALID;
2450 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002451 FREE_STRING(ctx->xmlctx->ctx, temp_val);
David Sedlák4ffcec82019-07-25 15:10:21 +02002452
2453 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2454 d = calloc(1, sizeof *d);
Michal Vaskob36053d2020-03-26 15:49:30 +01002455 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002456 struct yin_subelement subelems[1] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002457 {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
David Sedlák4ffcec82019-07-25 15:10:21 +02002458 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002459 ret = yin_parse_content(ctx, subelems, 1, LY_STMT_DEVIATE, NULL, &d->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002460
2461 } else if (dev_mod == LYS_DEV_ADD) {
2462 d_add = calloc(1, sizeof *d_add);
Michal Vaskob36053d2020-03-26 15:49:30 +01002463 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002464 d = (struct lysp_deviate *)d_add;
2465 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2466 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2467 struct yin_subelement subelems[9] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002468 {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2469 {LY_STMT_DEFAULT, &d_add->dflts, 0},
2470 {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2471 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2472 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2473 {LY_STMT_MUST, &d_add->musts, 0},
2474 {LY_STMT_UNIQUE, &d_add->uniques, 0},
2475 {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2476 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002477 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002478 ret = yin_parse_content(ctx, subelems, 9, LY_STMT_DEVIATE, NULL, &d_add->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002479
2480 } else if (dev_mod == LYS_DEV_REPLACE) {
2481 d_rpl = calloc(1, sizeof *d_rpl);
Michal Vaskob36053d2020-03-26 15:49:30 +01002482 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002483 d = (struct lysp_deviate *)d_rpl;
2484 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2485 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2486 struct yin_subelement subelems[8] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002487 {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2488 {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2489 {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2490 {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2491 {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2492 {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2493 {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2494 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002495 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002496 ret = yin_parse_content(ctx, subelems, 8, LY_STMT_DEVIATE, NULL, &d_rpl->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002497
2498 } else {
2499 d_del = calloc(1, sizeof *d_del);
Michal Vaskob36053d2020-03-26 15:49:30 +01002500 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
David Sedlák4ffcec82019-07-25 15:10:21 +02002501 d = (struct lysp_deviate *)d_del;
2502 struct yin_subelement subelems[5] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002503 {LY_STMT_DEFAULT, &d_del->dflts, 0},
2504 {LY_STMT_MUST, &d_del->musts, 0},
2505 {LY_STMT_UNIQUE, &d_del->uniques, 0},
2506 {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2507 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák4ffcec82019-07-25 15:10:21 +02002508 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002509 ret = yin_parse_content(ctx, subelems, 5, LY_STMT_DEVIATE, NULL, &d_del->exts);
David Sedlák4ffcec82019-07-25 15:10:21 +02002510 }
2511 LY_CHECK_GOTO(ret, cleanup);
2512
2513 d->mod = dev_mod;
2514 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002515 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002516
2517 return ret;
2518
2519cleanup:
2520 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002521 return ret;
2522}
2523
David Sedlák992fb7c2019-07-24 16:51:01 +02002524/**
David Sedlák8b754462019-07-25 16:22:13 +02002525 * @brief Parse deviation element.
2526 *
2527 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlák8b754462019-07-25 16:22:13 +02002528 * @param[in] deviations Deviations to add to.
2529 *
2530 * @return LY_ERR values.
2531 */
2532static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002533yin_parse_deviation(struct lys_yin_parser_ctx *ctx, struct lysp_deviation **deviations)
David Sedlák8b754462019-07-25 16:22:13 +02002534{
2535 struct lysp_deviation *dev;
2536
2537 /* create new deviation */
Michal Vaskob36053d2020-03-26 15:49:30 +01002538 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
David Sedlák8b754462019-07-25 16:22:13 +02002539
2540 /* parse argument */
Michal Vaskob36053d2020-03-26 15:49:30 +01002541 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2542 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION));
2543 CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
David Sedlák8b754462019-07-25 16:22:13 +02002544 struct yin_subelement subelems[4] = {
Radek Krejcid6b76452019-09-03 17:03:03 +02002545 {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2546 {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2547 {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2548 {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
David Sedlák8b754462019-07-25 16:22:13 +02002549 };
Michal Vaskob36053d2020-03-26 15:49:30 +01002550 return yin_parse_content(ctx, subelems, 4, LY_STMT_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002551}
2552
2553/**
David Sedlákb4e44562019-07-04 15:42:12 +02002554 * @brief Map keyword type to substatement info.
2555 *
2556 * @param[in] kw Keyword type.
2557 *
2558 * @return correct LYEXT_SUBSTMT information.
2559 */
2560static LYEXT_SUBSTMT
Radek Krejcid6b76452019-09-03 17:03:03 +02002561kw2lyext_substmt(enum ly_stmt kw)
David Sedlákb4e44562019-07-04 15:42:12 +02002562{
2563 switch (kw) {
Radek Krejcid6b76452019-09-03 17:03:03 +02002564 case LY_STMT_ARGUMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002565 return LYEXT_SUBSTMT_ARGUMENT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002566 case LY_STMT_BASE:
David Sedlákb4e44562019-07-04 15:42:12 +02002567 return LYEXT_SUBSTMT_BASE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002568 case LY_STMT_BELONGS_TO:
David Sedlákb4e44562019-07-04 15:42:12 +02002569 return LYEXT_SUBSTMT_BELONGSTO;
Radek Krejcid6b76452019-09-03 17:03:03 +02002570 case LY_STMT_CONTACT:
David Sedlákb4e44562019-07-04 15:42:12 +02002571 return LYEXT_SUBSTMT_CONTACT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002572 case LY_STMT_DEFAULT:
David Sedlákb4e44562019-07-04 15:42:12 +02002573 return LYEXT_SUBSTMT_DEFAULT;
Radek Krejcid6b76452019-09-03 17:03:03 +02002574 case LY_STMT_DESCRIPTION:
David Sedlákb4e44562019-07-04 15:42:12 +02002575 return LYEXT_SUBSTMT_DESCRIPTION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002576 case LY_STMT_ERROR_APP_TAG:
David Sedlákb4e44562019-07-04 15:42:12 +02002577 return LYEXT_SUBSTMT_ERRTAG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002578 case LY_STMT_ERROR_MESSAGE:
David Sedlákb4e44562019-07-04 15:42:12 +02002579 return LYEXT_SUBSTMT_ERRMSG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002580 case LY_STMT_KEY:
David Sedlákb4e44562019-07-04 15:42:12 +02002581 return LYEXT_SUBSTMT_KEY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002582 case LY_STMT_NAMESPACE:
David Sedlákb4e44562019-07-04 15:42:12 +02002583 return LYEXT_SUBSTMT_NAMESPACE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002584 case LY_STMT_ORGANIZATION:
David Sedlákb4e44562019-07-04 15:42:12 +02002585 return LYEXT_SUBSTMT_ORGANIZATION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002586 case LY_STMT_PATH:
David Sedlákb4e44562019-07-04 15:42:12 +02002587 return LYEXT_SUBSTMT_PATH;
Radek Krejcid6b76452019-09-03 17:03:03 +02002588 case LY_STMT_PREFIX:
David Sedlákb4e44562019-07-04 15:42:12 +02002589 return LYEXT_SUBSTMT_PREFIX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002590 case LY_STMT_PRESENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002591 return LYEXT_SUBSTMT_PRESENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002592 case LY_STMT_REFERENCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002593 return LYEXT_SUBSTMT_REFERENCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002594 case LY_STMT_REVISION_DATE:
David Sedlákb4e44562019-07-04 15:42:12 +02002595 return LYEXT_SUBSTMT_REVISIONDATE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002596 case LY_STMT_UNITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002597 return LYEXT_SUBSTMT_UNITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002598 case LY_STMT_VALUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002599 return LYEXT_SUBSTMT_VALUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002600 case LY_STMT_YANG_VERSION:
David Sedlákb4e44562019-07-04 15:42:12 +02002601 return LYEXT_SUBSTMT_VERSION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002602 case LY_STMT_MODIFIER:
David Sedlákb4e44562019-07-04 15:42:12 +02002603 return LYEXT_SUBSTMT_MODIFIER;
Radek Krejcid6b76452019-09-03 17:03:03 +02002604 case LY_STMT_REQUIRE_INSTANCE:
David Sedlákb4e44562019-07-04 15:42:12 +02002605 return LYEXT_SUBSTMT_REQINSTANCE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002606 case LY_STMT_YIN_ELEMENT:
David Sedlákb4e44562019-07-04 15:42:12 +02002607 return LYEXT_SUBSTMT_YINELEM;
Radek Krejcid6b76452019-09-03 17:03:03 +02002608 case LY_STMT_CONFIG:
David Sedlákb4e44562019-07-04 15:42:12 +02002609 return LYEXT_SUBSTMT_CONFIG;
Radek Krejcid6b76452019-09-03 17:03:03 +02002610 case LY_STMT_MANDATORY:
David Sedlákb4e44562019-07-04 15:42:12 +02002611 return LYEXT_SUBSTMT_MANDATORY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002612 case LY_STMT_ORDERED_BY:
David Sedlákb4e44562019-07-04 15:42:12 +02002613 return LYEXT_SUBSTMT_ORDEREDBY;
Radek Krejcid6b76452019-09-03 17:03:03 +02002614 case LY_STMT_STATUS:
David Sedlákb4e44562019-07-04 15:42:12 +02002615 return LYEXT_SUBSTMT_STATUS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002616 case LY_STMT_FRACTION_DIGITS:
David Sedlákb4e44562019-07-04 15:42:12 +02002617 return LYEXT_SUBSTMT_FRACDIGITS;
Radek Krejcid6b76452019-09-03 17:03:03 +02002618 case LY_STMT_MAX_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002619 return LYEXT_SUBSTMT_MAX;
Radek Krejcid6b76452019-09-03 17:03:03 +02002620 case LY_STMT_MIN_ELEMENTS:
David Sedlákb4e44562019-07-04 15:42:12 +02002621 return LYEXT_SUBSTMT_MIN;
Radek Krejcid6b76452019-09-03 17:03:03 +02002622 case LY_STMT_POSITION:
David Sedlákb4e44562019-07-04 15:42:12 +02002623 return LYEXT_SUBSTMT_POSITION;
Radek Krejcid6b76452019-09-03 17:03:03 +02002624 case LY_STMT_UNIQUE:
David Sedlákb4e44562019-07-04 15:42:12 +02002625 return LYEXT_SUBSTMT_UNIQUE;
Radek Krejcid6b76452019-09-03 17:03:03 +02002626 case LY_STMT_IF_FEATURE:
David Sedlákb4e44562019-07-04 15:42:12 +02002627 return LYEXT_SUBSTMT_IFFEATURE;
2628 default:
2629 return LYEXT_SUBSTMT_SELF;
2630 }
2631}
2632
David Sedlákc5b20842019-08-13 10:18:31 +02002633/**
2634 * @brief map keyword to keyword-group.
2635 *
2636 * @param[in] ctx YIN parser context used for logging.
2637 * @param[in] kw Keyword that is child of module or submodule.
2638 * @param[out] group Group of keyword.
2639 *
2640 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2641 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002642static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002643kw2kw_group(struct lys_yin_parser_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
David Sedláke6cd89e2019-08-07 12:46:02 +02002644{
2645 switch (kw) {
2646 /* module header */
Radek Krejcid6b76452019-09-03 17:03:03 +02002647 case LY_STMT_NONE:
2648 case LY_STMT_NAMESPACE:
2649 case LY_STMT_PREFIX:
2650 case LY_STMT_BELONGS_TO:
2651 case LY_STMT_YANG_VERSION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002652 *group = Y_MOD_MODULE_HEADER;
2653 break;
2654 /* linkage */
Radek Krejcid6b76452019-09-03 17:03:03 +02002655 case LY_STMT_INCLUDE:
2656 case LY_STMT_IMPORT:
David Sedláke6cd89e2019-08-07 12:46:02 +02002657 *group = Y_MOD_LINKAGE;
2658 break;
2659 /* meta */
Radek Krejcid6b76452019-09-03 17:03:03 +02002660 case LY_STMT_ORGANIZATION:
2661 case LY_STMT_CONTACT:
2662 case LY_STMT_DESCRIPTION:
2663 case LY_STMT_REFERENCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002664 *group = Y_MOD_META;
2665 break;
2666 /* revision */
Radek Krejcid6b76452019-09-03 17:03:03 +02002667 case LY_STMT_REVISION:
David Sedláke6cd89e2019-08-07 12:46:02 +02002668 *group = Y_MOD_REVISION;
2669 break;
2670 /* body */
Radek Krejcid6b76452019-09-03 17:03:03 +02002671 case LY_STMT_ANYDATA:
2672 case LY_STMT_ANYXML:
2673 case LY_STMT_AUGMENT:
2674 case LY_STMT_CHOICE:
2675 case LY_STMT_CONTAINER:
2676 case LY_STMT_DEVIATION:
2677 case LY_STMT_EXTENSION:
2678 case LY_STMT_FEATURE:
2679 case LY_STMT_GROUPING:
2680 case LY_STMT_IDENTITY:
2681 case LY_STMT_LEAF:
2682 case LY_STMT_LEAF_LIST:
2683 case LY_STMT_LIST:
2684 case LY_STMT_NOTIFICATION:
2685 case LY_STMT_RPC:
2686 case LY_STMT_TYPEDEF:
2687 case LY_STMT_USES:
2688 case LY_STMT_EXTENSION_INSTANCE:
David Sedláke6cd89e2019-08-07 12:46:02 +02002689 *group = Y_MOD_BODY;
2690 break;
2691 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01002692 LOGINT(ctx->xmlctx->ctx);
David Sedláke6cd89e2019-08-07 12:46:02 +02002693 return LY_EINT;
2694 }
2695
2696 return LY_SUCCESS;
2697}
2698
David Sedlákc5b20842019-08-13 10:18:31 +02002699/**
2700 * @brief Check if relative order of two keywords is valid.
2701 *
2702 * @param[in] ctx YIN parser context used for logging.
2703 * @param[in] kw Current keyword.
2704 * @param[in] next_kw Next keyword.
Radek Krejcid6b76452019-09-03 17:03:03 +02002705 * @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 +02002706 * because relative order is required only in module and submodule sub-elements, used for logging.
2707 *
David Sedlákbf8a2b72019-08-14 16:48:10 +02002708 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
David Sedlákc5b20842019-08-13 10:18:31 +02002709 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002710static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002711yin_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 +02002712{
Radek Krejcid6b76452019-09-03 17:03:03 +02002713 assert(parrent == LY_STMT_MODULE || parrent == LY_STMT_SUBMODULE);
David Sedláke6cd89e2019-08-07 12:46:02 +02002714 enum yang_module_stmt gr, next_gr;
2715
2716 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2717 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2718
2719 if (gr > next_gr) {
2720 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2721 return LY_EVALID;
2722 }
2723
2724 return LY_SUCCESS;
2725}
2726
David Sedlákc5dd0942019-09-13 10:23:59 +02002727/**
2728 * @brief Get element name prefixed by full URI of xml namespace.
2729 *
2730 * @param[in] ctx YIN parser context used for logging and to get inormation about xml namespaces.
2731 * @param[in] name Name of element.
2732 * @param[in] name_len Length of element name.
2733 * @param[in] prefix Prefix of element.
2734 * @param[in] prefix_len Length of element prefix.
2735 *
2736 * @return Element name prefixed by URI on success, NULL on failure.
2737 */
2738static const char *
Michal Vaskob36053d2020-03-26 15:49:30 +01002739name2nsname(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 +02002740{
Michal Vaskob36053d2020-03-26 15:49:30 +01002741 const struct lyxml_ns *ns = lyxml_ns_get(ctx->xmlctx, prefix, prefix_len);
2742 LY_CHECK_ERR_RET(!ns, LOGINT(ctx->xmlctx->ctx), NULL);
David Sedlák068dd352019-09-13 09:08:22 +02002743
Radek Krejci02728562019-09-18 14:13:05 +02002744 if (!strcmp(ns->uri, YIN_NS_URI)) {
2745 /* standard YANG statement in YIN namespace - keep it unprefixed as in case of YANG */
Michal Vaskob36053d2020-03-26 15:49:30 +01002746 return lydict_insert(ctx->xmlctx->ctx, name, name_len);
Radek Krejci02728562019-09-18 14:13:05 +02002747 }
2748 /* some statement in special namespace (extension instance) */
David Sedláke0ef1c62019-09-13 10:05:55 +02002749 size_t ns_len = strlen(ns->uri);
2750 size_t len = ns_len + name_len + 1; /* +1 because of ':' delimiter between ns and actual name */
2751
2752 char *result;
2753 char *temp;
2754 temp = result = malloc(sizeof(*temp) * (len + 1)); /* +1 for '\0' terminator */
Michal Vaskob36053d2020-03-26 15:49:30 +01002755 LY_CHECK_ERR_RET(!temp, LOGMEM(ctx->xmlctx->ctx), NULL);
David Sedláke0ef1c62019-09-13 10:05:55 +02002756
2757 strcpy(result, ns->uri);
2758 result[ns_len] = ':';
2759 temp = &result[ns_len + 1];
2760 strncpy(temp, name, name_len);
2761 result[len] = '\0';
2762
Michal Vaskob36053d2020-03-26 15:49:30 +01002763 return lydict_insert_zc(ctx->xmlctx->ctx, result);
David Sedlák068dd352019-09-13 09:08:22 +02002764}
2765
David Sedlákd6e56892019-07-01 15:40:24 +02002766LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01002767yin_parse_content(struct lys_yin_parser_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
2768 enum ly_stmt current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002769{
2770 LY_ERR ret = LY_SUCCESS;
Michal Vaskob36053d2020-03-26 15:49:30 +01002771 enum LYXML_PARSER_STATUS next_status;
Radek Krejcid6b76452019-09-03 17:03:03 +02002772 enum ly_stmt kw = LY_STMT_NONE, last_kw = LY_STMT_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002773 struct yin_subelement *subelem = NULL;
David Sedlák09e18c92019-07-18 11:17:11 +02002774
Michal Vaskob36053d2020-03-26 15:49:30 +01002775 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
David Sedlákd6e56892019-07-01 15:40:24 +02002776
Michal Vaskob36053d2020-03-26 15:49:30 +01002777 if (ctx->xmlctx->ws_only) {
2778 /* check whether there are any children */
2779 LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
2780 } else {
2781 /* we want to parse the value */
2782 next_status = LYXML_ELEM_CLOSE;
2783 }
2784
2785 if (next_status == LYXML_ELEMENT) {
2786 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2787
2788 /* current element has subelements as content */
2789 while (ctx->xmlctx->status == LYXML_ELEMENT) {
2790 /* match keyword */
2791 last_kw = kw;
2792 kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
2793 ctx->xmlctx->prefix_len, current_element);
2794
2795 /* check if this element can be child of current element */
2796 subelem = get_record(kw, subelem_info_size, subelem_info);
2797 if (!subelem) {
2798 if (current_element == LY_STMT_DEVIATE && isdevsub(kw)) {
2799 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2800 } else {
2801 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len,
2802 ctx->xmlctx->name, ly_stmt2str(current_element));
2803 }
2804 ret = LY_EVALID;
2805 goto cleanup;
2806 }
2807
2808 /* relative order is required only in module and submodule sub-elements */
2809 if (current_element == LY_STMT_MODULE || current_element == LY_STMT_SUBMODULE) {
2810 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2811 LY_CHECK_GOTO(ret, cleanup);
2812 }
2813
2814 /* flag check */
2815 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
2816 /* subelement uniquenes */
2817 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
2818 return LY_EVALID;
2819 }
2820 if (subelem->flags & YIN_SUBELEM_FIRST) {
2821 /* subelement is supposed to be defined as first subelement */
2822 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
2823 LY_CHECK_GOTO(ret, cleanup);
2824 }
2825 if (subelem->flags & YIN_SUBELEM_VER2) {
2826 /* subelement is supported only in version 1.1 or higher */
2827 if (ctx->mod_version < 2) {
2828 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 +02002829 ret = LY_EVALID;
2830 goto cleanup;
2831 }
David Sedlákd6e56892019-07-01 15:40:24 +02002832 }
Michal Vaskob36053d2020-03-26 15:49:30 +01002833 /* note that element was parsed for easy uniqueness check in next iterations */
2834 subelem->flags |= YIN_SUBELEM_PARSED;
2835
2836 switch (kw) {
2837 /* call responsible function */
2838 case LY_STMT_EXTENSION_INSTANCE:
2839 ret = yin_parse_extension_instance(ctx, kw2lyext_substmt(current_element),
Michal Vaskofd69e1d2020-07-03 11:57:17 +02002840 (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE*)subelem->dest) : 0, exts);
Michal Vaskob36053d2020-03-26 15:49:30 +01002841 break;
2842 case LY_STMT_ACTION:
2843 case LY_STMT_RPC:
2844 ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
2845 break;
2846 case LY_STMT_ANYDATA:
2847 case LY_STMT_ANYXML:
2848 ret = yin_parse_any(ctx, kw, (struct tree_node_meta *)subelem->dest);
2849 break;
2850 case LY_STMT_ARGUMENT:
2851 ret = yin_parse_argument(ctx, (struct yin_argument_meta *)subelem->dest, exts);
2852 break;
2853 case LY_STMT_AUGMENT:
2854 ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
2855 break;
2856 case LY_STMT_BASE:
2857 ret = yin_parse_base(ctx, current_element, subelem->dest, exts);
2858 break;
2859 case LY_STMT_BELONGS_TO:
2860 ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
2861 break;
2862 case LY_STMT_BIT:
2863 ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
2864 break;
2865 case LY_STMT_CASE:
2866 ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
2867 break;
2868 case LY_STMT_CHOICE:
2869 ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
2870 break;
2871 case LY_STMT_CONFIG:
2872 ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
2873 break;
2874 case LY_STMT_CONTACT:
2875 case LY_STMT_DESCRIPTION:
2876 case LY_STMT_ORGANIZATION:
2877 case LY_STMT_REFERENCE:
2878 ret = yin_parse_meta(ctx, kw, (const char **)subelem->dest, exts);
2879 break;
2880 case LY_STMT_CONTAINER:
2881 ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
2882 break;
2883 case LY_STMT_DEFAULT:
2884 case LY_STMT_ERROR_APP_TAG:
2885 case LY_STMT_KEY:
2886 case LY_STMT_PRESENCE:
2887 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
2888 break;
2889 case LY_STMT_DEVIATE:
2890 ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
2891 break;
2892 case LY_STMT_DEVIATION:
2893 ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
2894 break;
2895 case LY_STMT_ENUM:
2896 ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
2897 break;
2898 case LY_STMT_ERROR_MESSAGE:
2899 ret = yin_parse_err_msg(ctx, (const char **)subelem->dest, exts);
2900 break;
2901 case LY_STMT_EXTENSION:
2902 ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
2903 break;
2904 case LY_STMT_FEATURE:
2905 ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
2906 break;
2907 case LY_STMT_FRACTION_DIGITS:
2908 ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
2909 break;
2910 case LY_STMT_GROUPING:
2911 ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
2912 break;
2913 case LY_STMT_IDENTITY:
2914 ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
2915 break;
2916 case LY_STMT_IF_FEATURE:
2917 case LY_STMT_UNITS:
2918 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
2919 break;
2920 case LY_STMT_IMPORT:
2921 ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
2922 break;
2923 case LY_STMT_INCLUDE:
2924 ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
2925 break;
2926 case LY_STMT_INPUT:
2927 case LY_STMT_OUTPUT:
2928 ret = yin_parse_inout(ctx, kw, (struct inout_meta *)subelem->dest);
2929 break;
2930 case LY_STMT_LEAF:
2931 ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
2932 break;
2933 case LY_STMT_LEAF_LIST:
2934 ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
2935 break;
2936 case LY_STMT_LENGTH:
2937 ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
2938 break;
2939 case LY_STMT_LIST:
2940 ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
2941 break;
2942 case LY_STMT_MANDATORY:
2943 ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
2944 break;
2945 case LY_STMT_MAX_ELEMENTS:
2946 case LY_STMT_MIN_ELEMENTS:
2947 ret = yin_parse_minmax(ctx, current_element, kw, subelem->dest);
2948 break;
2949 case LY_STMT_MODIFIER:
2950 ret = yin_parse_modifier(ctx, (const char **)subelem->dest, exts);
2951 break;
2952 case LY_STMT_MUST:
2953 ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
2954 break;
2955 case LY_STMT_NAMESPACE:
2956 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
2957 break;
2958 case LY_STMT_NOTIFICATION:
2959 ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
2960 break;
2961 case LY_STMT_ORDERED_BY:
2962 ret = yin_parse_orderedby(ctx, (uint16_t *)subelem->dest, exts);
2963 break;
2964 case LY_STMT_PATH:
2965 ret = yin_parse_path(ctx, kw, (struct lysp_type *)subelem->dest);
2966 break;
2967 case LY_STMT_PATTERN:
2968 ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
2969 break;
2970 case LY_STMT_VALUE:
2971 case LY_STMT_POSITION:
2972 ret = yin_parse_value_pos(ctx, kw, (struct lysp_type_enum *)subelem->dest);
2973 break;
2974 case LY_STMT_PREFIX:
2975 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
2976 break;
2977 case LY_STMT_RANGE:
2978 ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
2979 break;
2980 case LY_STMT_REFINE:
2981 ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
2982 break;
2983 case LY_STMT_REQUIRE_INSTANCE:
2984 ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
2985 break;
2986 case LY_STMT_REVISION:
2987 ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
2988 break;
2989 case LY_STMT_REVISION_DATE:
2990 ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
2991 break;
2992 case LY_STMT_STATUS:
2993 ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
2994 break;
2995 case LY_STMT_TYPE:
2996 ret = yin_parse_type(ctx, current_element, subelem);
2997 break;
2998 case LY_STMT_TYPEDEF:
2999 ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3000 break;
3001 case LY_STMT_UNIQUE:
3002 ret = yin_parse_simple_elem(ctx, kw, subelem, YIN_ARG_TAG, Y_STR_ARG, exts);
3003 break;
3004 case LY_STMT_USES:
3005 ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3006 break;
3007 case LY_STMT_WHEN:
3008 ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3009 break;
3010 case LY_STMT_YANG_VERSION:
3011 ret = yin_parse_yangversion(ctx, (uint8_t *)subelem->dest, exts);
3012 break;
3013 case LY_STMT_YIN_ELEMENT:
3014 ret = yin_parse_yin_element(ctx, (uint16_t *)subelem->dest, exts);
3015 break;
3016 case LY_STMT_ARG_TEXT:
3017 case LY_STMT_ARG_VALUE:
3018 /* TODO what to do with content/attributes? */
3019 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3020 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3021 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3022 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3023 }
3024 ret = yin_parse_content(ctx, NULL, 0, kw, (const char **)subelem->dest, NULL);
3025 break;
3026 default:
3027 LOGINT(ctx->xmlctx->ctx);
3028 ret = LY_EINT;
David Sedlák3ffbc522019-07-02 17:49:28 +02003029 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003030 LY_CHECK_GOTO(ret, cleanup);
3031 subelem = NULL;
3032
3033 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003034 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003035 } else {
3036 LY_CHECK_RET(ret);
3037 /* elements with text or none content */
3038 /* save text content, if text_content isn't set, it's just ignored */
3039 /* no resources are allocated in this branch, no need to use cleanup label */
3040 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3041 if (text_content) {
3042 *text_content = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3043 LY_CHECK_RET(!*text_content, LY_EMEM);
3044 }
3045
3046 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákd6e56892019-07-01 15:40:24 +02003047 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003048
David Sedlák8b754462019-07-25 16:22:13 +02003049 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
3050 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02003051
3052cleanup:
David Sedlákd6e56892019-07-01 15:40:24 +02003053 return ret;
3054}
3055
David Sedlák619db942019-07-03 14:47:30 +02003056LY_ERR
Michal Vaskofd69e1d2020-07-03 11:57:17 +02003057yin_parse_extension_instance(struct lys_yin_parser_ctx *ctx, LYEXT_SUBSTMT subelem, LY_ARRAY_COUNT_TYPE subelem_index,
Michal Vaskob36053d2020-03-26 15:49:30 +01003058 struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02003059{
David Sedlák1e2cdd02019-06-27 14:17:43 +02003060 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003061 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003062
Michal Vaskob36053d2020-03-26 15:49:30 +01003063 assert(ctx->xmlctx->status == LYXML_ELEMENT);
3064
3065 LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003066
3067 e->yin = 0;
3068 /* store name and insubstmt info */
Michal Vaskob36053d2020-03-26 15:49:30 +01003069 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 +02003070 LY_CHECK_RET(!e->name, LY_EMEM);
David Sedlák619db942019-07-03 14:47:30 +02003071 e->insubstmt = subelem;
3072 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003073 e->yin |= LYS_YIN;
Michal Vaskob36053d2020-03-26 15:49:30 +01003074 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003075
David Sedlákb1a78352019-06-28 16:16:29 +02003076 /* store attributes as subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003077 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3078 if (!ctx->xmlctx->prefix) {
David Sedlákb1a78352019-06-28 16:16:29 +02003079 new_subelem = calloc(1, sizeof(*new_subelem));
3080 if (!e->child) {
3081 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003082 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003083 last_subelem->next = new_subelem;
3084 }
3085 last_subelem = new_subelem;
3086
3087 last_subelem->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003088 last_subelem->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlák169cc522019-08-15 13:23:45 +02003089 LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003090 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák169cc522019-08-15 13:23:45 +02003091
Michal Vaskob36053d2020-03-26 15:49:30 +01003092 last_subelem->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlák169cc522019-08-15 13:23:45 +02003093 LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003094 } else {
3095 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003096 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003097
3098 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlák1e2cdd02019-06-27 14:17:43 +02003099 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003100
David Sedlákf250ecf2019-07-01 11:02:05 +02003101 /* parse subelements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003102 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3103 if (ctx->xmlctx->ws_only) {
3104 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3105 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3106 LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3107 if (!e->child) {
3108 e->child = new_subelem;
3109 } else {
3110 last_subelem->next = new_subelem;
David Sedlákb1a78352019-06-28 16:16:29 +02003111 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003112 last_subelem = new_subelem;
David Sedlák169cc522019-08-15 13:23:45 +02003113
Michal Vaskob36053d2020-03-26 15:49:30 +01003114 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3115 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003116 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003117 } else if (ctx->xmlctx->value_len) {
3118 /* save text content */
3119 e->argument = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3120 LY_CHECK_RET(!e->argument, LY_EMEM);
3121
3122 /* parser next */
3123 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
David Sedlákb1a78352019-06-28 16:16:29 +02003124 }
3125
3126 return LY_SUCCESS;
3127}
3128
David Sedlákaa98bba2019-09-12 11:52:14 +02003129/**
3130 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3131 *
3132 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákaa98bba2019-09-12 11:52:14 +02003133 * @param[in] elem_type Type of element that is currently being parsed.
3134 * @param[out] arg Value to write to.
3135 *
3136 * @return LY_ERR values.
3137 */
3138static LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003139yin_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 +02003140{
David Sedlák071f7662019-09-12 02:02:51 +02003141 enum ly_stmt child;
David Sedláke6284fc2019-09-10 11:57:02 +02003142
Michal Vaskob36053d2020-03-26 15:49:30 +01003143 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3144
David Sedláke6284fc2019-09-10 11:57:02 +02003145 switch (elem_type) {
3146 case LY_STMT_ACTION:
3147 case LY_STMT_ANYDATA:
3148 case LY_STMT_ANYXML:
3149 case LY_STMT_ARGUMENT:
3150 case LY_STMT_BASE:
3151 case LY_STMT_BIT:
3152 case LY_STMT_CASE:
3153 case LY_STMT_CHOICE:
3154 case LY_STMT_CONTAINER:
3155 case LY_STMT_ENUM:
3156 case LY_STMT_EXTENSION:
3157 case LY_STMT_FEATURE:
3158 case LY_STMT_GROUPING:
3159 case LY_STMT_IDENTITY:
3160 case LY_STMT_IF_FEATURE:
3161 case LY_STMT_LEAF:
3162 case LY_STMT_LEAF_LIST:
3163 case LY_STMT_LIST:
3164 case LY_STMT_MODULE:
3165 case LY_STMT_NOTIFICATION:
3166 case LY_STMT_RPC:
3167 case LY_STMT_SUBMODULE:
3168 case LY_STMT_TYPE:
3169 case LY_STMT_TYPEDEF:
3170 case LY_STMT_UNITS:
3171 case LY_STMT_USES:
Michal Vaskob36053d2020-03-26 15:49:30 +01003172 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 +02003173 break;
3174 case LY_STMT_AUGMENT:
3175 case LY_STMT_DEVIATION:
3176 case LY_STMT_REFINE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003177 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 +02003178 break;
3179 case LY_STMT_CONFIG:
3180 case LY_STMT_DEFAULT:
3181 case LY_STMT_DEVIATE:
3182 case LY_STMT_ERROR_APP_TAG:
David Sedláke6284fc2019-09-10 11:57:02 +02003183 case LY_STMT_FRACTION_DIGITS:
3184 case LY_STMT_KEY:
3185 case LY_STMT_LENGTH:
3186 case LY_STMT_MANDATORY:
3187 case LY_STMT_MAX_ELEMENTS:
3188 case LY_STMT_MIN_ELEMENTS:
3189 case LY_STMT_MODIFIER:
3190 case LY_STMT_ORDERED_BY:
3191 case LY_STMT_PATH:
3192 case LY_STMT_PATTERN:
3193 case LY_STMT_POSITION:
3194 case LY_STMT_PREFIX:
3195 case LY_STMT_PRESENCE:
3196 case LY_STMT_RANGE:
3197 case LY_STMT_REQUIRE_INSTANCE:
3198 case LY_STMT_STATUS:
3199 case LY_STMT_VALUE:
3200 case LY_STMT_YANG_VERSION:
3201 case LY_STMT_YIN_ELEMENT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003202 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 +02003203 break;
3204 case LY_STMT_IMPORT:
3205 case LY_STMT_INCLUDE:
3206 case LY_STMT_BELONGS_TO:
Michal Vaskob36053d2020-03-26 15:49:30 +01003207 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 +02003208 break;
3209 case LY_STMT_INPUT:
3210 case LY_STMT_OUTPUT:
Michal Vaskob36053d2020-03-26 15:49:30 +01003211 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 +02003212 break;
3213 case LY_STMT_MUST:
3214 case LY_STMT_WHEN:
Michal Vaskob36053d2020-03-26 15:49:30 +01003215 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 +02003216 break;
3217 case LY_STMT_NAMESPACE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003218 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 +02003219 break;
3220 case LY_STMT_REVISION:
3221 case LY_STMT_REVISION_DATE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003222 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 +02003223 break;
3224 case LY_STMT_UNIQUE:
Michal Vaskob36053d2020-03-26 15:49:30 +01003225 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 +02003226 break;
David Sedlák071f7662019-09-12 02:02:51 +02003227 /* argument is mapped to yin element */
3228 case LY_STMT_CONTACT:
3229 case LY_STMT_DESCRIPTION:
3230 case LY_STMT_ORGANIZATION:
3231 case LY_STMT_REFERENCE:
3232 case LY_STMT_ERROR_MESSAGE:
David Sedlákaa98bba2019-09-12 11:52:14 +02003233 /* there shouldn't be any attribute, argument is supposed to be first subelement */
Michal Vaskob36053d2020-03-26 15:49:30 +01003234 LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
3235
3236 /* no content */
3237 assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3238 if (ctx->xmlctx->ws_only) {
3239 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3240 }
3241 if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3242 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3243 elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type));
David Sedlák071f7662019-09-12 02:02:51 +02003244 return LY_EVALID;
3245 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003246
3247 /* parse child element */
3248 child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix, ctx->xmlctx->prefix_len, elem_type);
3249 if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) ||
3250 (elem_type != LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_TEXT)) {
3251 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3252 ly_stmt2str(elem_type));
3253 return LY_EVALID;
David Sedlákaa98bba2019-09-12 11:52:14 +02003254 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003255 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3256
3257 /* no attributes expected? TODO */
3258 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3259 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3260 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3261 }
3262
3263 /* load and save content */
3264 *arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3265 LY_CHECK_RET(!*arg, LY_EMEM);
3266
3267 /* load closing tag of subelement */
3268 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3269
3270 /* if only subelement was parsed as argument, load also closing tag TODO what? */
3271 /*if (ctx->xmlctx->status == LYXML_ELEMENT) {
3272 LY_CHECK_RET(lyxml_get_element(&ctx->xmlctx, data, &prefix, &prefix_len, &name, &name_len));
3273 }*/
David Sedlákb0ca07d2019-09-11 11:54:05 +02003274 break;
David Sedláke6284fc2019-09-10 11:57:02 +02003275 default:
Michal Vaskob36053d2020-03-26 15:49:30 +01003276 LOGINT(ctx->xmlctx->ctx);
David Sedlák071f7662019-09-12 02:02:51 +02003277 return LY_EINT;
David Sedláke6284fc2019-09-10 11:57:02 +02003278 }
3279
David Sedlák071f7662019-09-12 02:02:51 +02003280 return LY_SUCCESS;
David Sedláke6284fc2019-09-10 11:57:02 +02003281}
3282
3283LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003284yin_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 +02003285{
3286 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02003287 struct lysp_stmt *last = NULL, *new = NULL;
3288
Michal Vaskob36053d2020-03-26 15:49:30 +01003289 assert(ctx->xmlctx->status == LYXML_ELEMENT);
David Sedláke0ef1c62019-09-13 10:05:55 +02003290
3291 /* allocate new structure for element */
3292 *element = calloc(1, sizeof(**element));
Michal Vaskob36053d2020-03-26 15:49:30 +01003293 LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3294 (*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 +02003295 LY_CHECK_ERR_GOTO(!(*element)->stmt, ret = LY_EMEM, cleanup);
David Sedláke0ef1c62019-09-13 10:05:55 +02003296
Michal Vaskob36053d2020-03-26 15:49:30 +01003297 (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3298 ctx->xmlctx->prefix_len, parent);
David Sedlákb1a78352019-06-28 16:16:29 +02003299
3300 last = (*element)->child;
David Sedláke6284fc2019-09-10 11:57:02 +02003301 if ((*element)->kw == LY_STMT_NONE) {
3302 /* unrecognized element */
Michal Vaskob36053d2020-03-26 15:49:30 +01003303 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, ctx->xmlctx->name_len, ctx->xmlctx->name,
3304 ly_stmt2str(parent));
David Sedlákaa98bba2019-09-12 11:52:14 +02003305 ret = LY_EVALID;
3306 goto cleanup;
David Sedláke6284fc2019-09-10 11:57:02 +02003307 } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3308 /* element is known yang keyword, which means argument can be parsed correctly. */
Michal Vaskob36053d2020-03-26 15:49:30 +01003309 ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
David Sedlákaa98bba2019-09-12 11:52:14 +02003310 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003311 } else {
Michal Vaskob36053d2020-03-26 15:49:30 +01003312 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3313
David Sedlákaa98bba2019-09-12 11:52:14 +02003314 /* load attributes in generic way, save all attributes in linked list */
Michal Vaskob36053d2020-03-26 15:49:30 +01003315 while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
David Sedláke6284fc2019-09-10 11:57:02 +02003316 new = calloc(1, sizeof(*last));
Michal Vaskob36053d2020-03-26 15:49:30 +01003317 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
David Sedláke6284fc2019-09-10 11:57:02 +02003318 if (!(*element)->child) {
3319 /* save first */
3320 (*element)->child = new;
3321 } else {
3322 last->next = new;
3323 }
3324 last = new;
David Sedlákb1a78352019-06-28 16:16:29 +02003325
David Sedláke6284fc2019-09-10 11:57:02 +02003326 last->flags |= LYS_YIN_ATTR;
Michal Vaskob36053d2020-03-26 15:49:30 +01003327 last->stmt = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len);
David Sedlákb0ca07d2019-09-11 11:54:05 +02003328 last->kw = LY_STMT_NONE;
David Sedláke6284fc2019-09-10 11:57:02 +02003329 /* attributes with prefix are ignored */
Michal Vaskob36053d2020-03-26 15:49:30 +01003330 if (!ctx->xmlctx->prefix) {
3331 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3332
3333 last->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
David Sedlákaa98bba2019-09-12 11:52:14 +02003334 LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003335 } else {
3336 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003337 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003338 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003339 }
3340 }
3341
Michal Vaskob36053d2020-03-26 15:49:30 +01003342 if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3343 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3344 while (ctx->xmlctx->status == LYXML_ELEMENT) {
3345 /* parse subelements */
3346 ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
David Sedlákaa98bba2019-09-12 11:52:14 +02003347 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskob36053d2020-03-26 15:49:30 +01003348 if (!(*element)->child) {
3349 /* save first */
3350 (*element)->child = new;
3351 } else {
3352 last->next = new;
David Sedláka82ecff2019-08-16 10:51:48 +02003353 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003354 last = new;
David Sedlák169cc522019-08-15 13:23:45 +02003355
Michal Vaskob36053d2020-03-26 15:49:30 +01003356 assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3357 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedláka82ecff2019-08-16 10:51:48 +02003358 }
Michal Vaskob36053d2020-03-26 15:49:30 +01003359 } else {
3360 /* save element content */
3361 if (ctx->xmlctx->value_len) {
3362 (*element)->arg = INSERT_STRING(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic);
3363 LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3364 }
3365
3366 /* read closing tag */
3367 LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
David Sedlákb1a78352019-06-28 16:16:29 +02003368 }
3369
David Sedlákb0ca07d2019-09-11 11:54:05 +02003370cleanup:
David Sedlákb0ca07d2019-09-11 11:54:05 +02003371 return ret;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003372}
3373
3374LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003375yin_parse_mod(struct lys_yin_parser_ctx *ctx, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003376{
David Sedlák81497a32019-08-13 16:56:26 +02003377 LY_ERR ret = LY_SUCCESS;
3378 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003379 struct lysp_submodule *dup;
David Sedlák3b4db242018-10-19 16:11:01 +02003380
Michal Vaskob36053d2020-03-26 15:49:30 +01003381 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3382 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 +02003383 LY_CHECK_RET(subelems_allocator(ctx, 28, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003384 LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3385 LY_STMT_ANYXML, &mod->data, 0,
3386 LY_STMT_AUGMENT, &mod->augments, 0,
3387 LY_STMT_CHOICE, &mod->data, 0,
3388 LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3389 LY_STMT_CONTAINER, &mod->data, 0,
3390 LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3391 LY_STMT_DEVIATION, &mod->deviations, 0,
3392 LY_STMT_EXTENSION, &mod->extensions, 0,
3393 LY_STMT_FEATURE, &mod->features, 0,
3394 LY_STMT_GROUPING, &mod->groupings, 0,
3395 LY_STMT_IDENTITY, &mod->identities, 0,
3396 LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3397 LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3398 LY_STMT_LEAF, &mod->data, 0,
3399 LY_STMT_LEAF_LIST, &mod->data, 0,
3400 LY_STMT_LIST, &mod->data, 0,
3401 LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3402 LY_STMT_NOTIFICATION, &mod->notifs, 0,
3403 LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3404 LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3405 LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3406 LY_STMT_REVISION, &mod->revs, 0,
3407 LY_STMT_RPC, &mod->rpcs, 0,
3408 LY_STMT_TYPEDEF, &mod->typedefs, 0,
3409 LY_STMT_USES, &mod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003410 LY_STMT_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003411 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003412 ));
3413
Michal Vaskob36053d2020-03-26 15:49:30 +01003414 ret = yin_parse_content(ctx, subelems, 28, LY_STMT_MODULE, NULL, &mod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003415 subelems_deallocator(28, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003416 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003417
David Sedláked809f12019-09-13 10:15:11 +02003418 /* finalize parent pointers to the reallocated items */
3419 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, mod->groupings, mod->augments, mod->rpcs, mod->notifs));
3420
3421 /* submodules share the namespace with the module names, so there must not be
3422 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003423 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, mod->mod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003424 if (dup) {
3425 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", mod->mod->name);
3426 return LY_EVALID;
3427 }
3428
3429 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +02003430}
3431
3432LY_ERR
Michal Vaskob36053d2020-03-26 15:49:30 +01003433yin_parse_submod(struct lys_yin_parser_ctx *ctx, struct lysp_submodule *submod)
David Sedlák298ff6d2019-07-26 14:29:03 +02003434{
David Sedlák81497a32019-08-13 16:56:26 +02003435 LY_ERR ret = LY_SUCCESS;
3436 struct yin_subelement *subelems = NULL;
David Sedláked809f12019-09-13 10:15:11 +02003437 struct lysp_submodule *dup;
David Sedlák298ff6d2019-07-26 14:29:03 +02003438
Michal Vaskob36053d2020-03-26 15:49:30 +01003439 LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3440 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 +02003441 LY_CHECK_RET(subelems_allocator(ctx, 27, NULL, &subelems,
Radek Krejcid6b76452019-09-03 17:03:03 +02003442 LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3443 LY_STMT_ANYXML, &submod->data, 0,
3444 LY_STMT_AUGMENT, &submod->augments, 0,
3445 LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3446 LY_STMT_CHOICE, &submod->data, 0,
3447 LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3448 LY_STMT_CONTAINER, &submod->data, 0,
3449 LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3450 LY_STMT_DEVIATION, &submod->deviations, 0,
3451 LY_STMT_EXTENSION, &submod->extensions, 0,
3452 LY_STMT_FEATURE, &submod->features, 0,
3453 LY_STMT_GROUPING, &submod->groupings, 0,
3454 LY_STMT_IDENTITY, &submod->identities, 0,
3455 LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3456 LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3457 LY_STMT_LEAF, &submod->data, 0,
3458 LY_STMT_LEAF_LIST, &submod->data, 0,
3459 LY_STMT_LIST, &submod->data, 0,
3460 LY_STMT_NOTIFICATION, &submod->notifs, 0,
3461 LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3462 LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3463 LY_STMT_REVISION, &submod->revs, 0,
3464 LY_STMT_RPC, &submod->rpcs, 0,
3465 LY_STMT_TYPEDEF, &submod->typedefs, 0,
3466 LY_STMT_USES, &submod->data, 0,
Radek Krejcicd1c5e32019-09-06 16:28:42 +02003467 LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
Radek Krejcid6b76452019-09-03 17:03:03 +02003468 LY_STMT_EXTENSION_INSTANCE, NULL, 0
David Sedlák81497a32019-08-13 16:56:26 +02003469 ));
3470
Michal Vaskob36053d2020-03-26 15:49:30 +01003471 ret = yin_parse_content(ctx, subelems, 27, LY_STMT_SUBMODULE, NULL, &submod->exts);
David Sedlák81497a32019-08-13 16:56:26 +02003472 subelems_deallocator(27, subelems);
David Sedláked809f12019-09-13 10:15:11 +02003473 LY_CHECK_RET(ret);
David Sedlák81497a32019-08-13 16:56:26 +02003474
David Sedláked809f12019-09-13 10:15:11 +02003475 /* finalize parent pointers to the reallocated items */
3476 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, submod->groupings, submod->augments, submod->rpcs, submod->notifs));
3477
3478 /* submodules share the namespace with the module names, so there must not be
3479 * a submodule of the same name in the context, no need for revision matching */
Michal Vaskob36053d2020-03-26 15:49:30 +01003480 dup = ly_ctx_get_submodule(ctx->xmlctx->ctx, NULL, submod->name, NULL);
David Sedláked809f12019-09-13 10:15:11 +02003481 if (dup && strcmp(dup->belongsto, submod->belongsto)) {
3482 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG, "Name collision between submodules of name \"%s\".", dup->name);
3483 return LY_EVALID;
3484 }
3485
3486 return LY_SUCCESS;
David Sedlák298ff6d2019-07-26 14:29:03 +02003487}
3488
3489LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003490yin_parse_submodule(struct lys_yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx,
3491 struct ly_in *in, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003492{
Radek Krejcid6b76452019-09-03 17:03:03 +02003493 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák8985a142019-07-31 16:43:06 +02003494 LY_ERR ret = LY_SUCCESS;
David Sedlák8985a142019-07-31 16:43:06 +02003495 struct lysp_submodule *mod_p = NULL;
3496
3497 /* create context */
3498 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003499 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003500 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003501 LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
David Sedlák8985a142019-07-31 16:43:06 +02003502
David Sedlák1b623122019-08-05 15:27:49 +02003503 /* map the typedefs and groupings list from main context to the submodule's context */
3504 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3505 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3506
David Sedlák8985a142019-07-31 16:43:06 +02003507 /* check submodule */
Michal Vaskob36053d2020-03-26 15:49:30 +01003508 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3509 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003510 if (kw == LY_STMT_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003511 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3512 ret = LY_EINVAL;
3513 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003514 } else if (kw != LY_STMT_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003515 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003516 ret = LY_EVALID;
3517 goto cleanup;
3518 }
3519
3520 mod_p = calloc(1, sizeof *mod_p);
3521 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3522 mod_p->parsing = 1;
3523
Michal Vaskob36053d2020-03-26 15:49:30 +01003524 ret = yin_parse_submod(*yin_ctx, mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003525 LY_CHECK_GOTO(ret, cleanup);
3526
David Sedlákbf8a2b72019-08-14 16:48:10 +02003527 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003528 while (isspace(in->current[0])) {
3529 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003530 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003531 if (in->current[0]) {
3532 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
3533 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003534 ret = LY_EVALID;
3535 goto cleanup;
3536 }
3537
David Sedlák8985a142019-07-31 16:43:06 +02003538 mod_p->parsing = 0;
3539 *submod = mod_p;
3540
3541cleanup:
3542 if (ret) {
3543 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003544 yin_parser_ctx_free(*yin_ctx);
3545 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003546 }
David Sedlák8985a142019-07-31 16:43:06 +02003547 return ret;
3548}
3549
3550LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02003551yin_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 +02003552{
David Sedláke4889912018-11-02 09:52:40 +01003553 LY_ERR ret = LY_SUCCESS;
Radek Krejcid6b76452019-09-03 17:03:03 +02003554 enum ly_stmt kw = LY_STMT_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003555 struct lysp_module *mod_p = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003556
David Sedlák8985a142019-07-31 16:43:06 +02003557 /* create context */
3558 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003559 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
Michal Vaskob36053d2020-03-26 15:49:30 +01003560 (*yin_ctx)->format = LYS_IN_YIN;
Michal Vasko63f3d842020-07-08 10:10:14 +02003561 LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
David Sedlákda8ffa32019-07-08 14:17:10 +02003562
David Sedlák8985a142019-07-31 16:43:06 +02003563 /* check module */
Michal Vaskob36053d2020-03-26 15:49:30 +01003564 kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3565 (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
Radek Krejcid6b76452019-09-03 17:03:03 +02003566 if (kw == LY_STMT_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003567 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 +01003568 ret = LY_EINVAL;
3569 goto cleanup;
Radek Krejcid6b76452019-09-03 17:03:03 +02003570 } else if (kw != LY_STMT_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003571 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003572 ret = LY_EVALID;
3573 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003574 }
3575
David Sedlák3017da42019-02-15 09:48:04 +01003576 /* allocate module */
3577 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003578 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003579 mod_p->mod = mod;
3580 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003581
David Sedlák00250342019-06-21 14:19:39 +02003582 /* parse module substatements */
Michal Vaskob36053d2020-03-26 15:49:30 +01003583 ret = yin_parse_mod(*yin_ctx, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003584 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003585
David Sedlákbf8a2b72019-08-14 16:48:10 +02003586 /* skip possible trailing whitespaces at end of the input */
Michal Vasko63f3d842020-07-08 10:10:14 +02003587 while (isspace(in->current[0])) {
3588 ly_in_skip(in, 1);
David Sedlák6d781b62019-08-02 15:22:52 +02003589 }
Michal Vasko63f3d842020-07-08 10:10:14 +02003590 if (in->current[0]) {
3591 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
3592 strlen(in->current) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003593 ret = LY_EVALID;
3594 goto cleanup;
3595 }
3596
David Sedlák3017da42019-02-15 09:48:04 +01003597 mod_p->parsing = 0;
3598 mod->parsed = mod_p;
3599
3600cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003601 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003602 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003603 yin_parser_ctx_free(*yin_ctx);
3604 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003605 }
David Sedlák2e411422018-12-17 02:35:39 +01003606 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003607}