blob: 811b18352c9251eccc541d5866753a8ab7095f74 [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
David Sedlákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlákf824ad52018-10-14 23:58:15 +020024
David Sedlákf824ad52018-10-14 23:58:15 +020025#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020026#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020027#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020028#include "tree.h"
29#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020030#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020031#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020032
David Sedlák2b214ac2019-06-06 16:11:03 +020033/**
34 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020035 *
David Sedlák2b214ac2019-06-06 16:11:03 +020036 * @param ns Namespace URI to check.
37 *
38 * @return true if ns equals YIN_NS_URI false otherwise.
39 */
40#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
41
David Sedláke1a30302019-07-10 13:49:38 +020042static LY_ERR
43yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
44 struct lysp_ext_instance **exts);
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ákf6251182019-06-06 10:22:13 +020056};
57
David Sedlák1bccdfa2019-06-17 15:55:27 +020058enum yang_keyword
David Sedlákc1771b12019-07-10 15:55:46 +020059yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
60 const char *prefix, size_t prefix_len, enum yang_keyword parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020061{
David Sedlák8f7a1172019-06-20 14:42:18 +020062 const char *start = NULL;
63 enum yang_keyword kw = YANG_NONE;
64 const struct lyxml_ns *ns = NULL;
65
66 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020067 return YANG_NONE;
68 }
69
David Sedlákda8ffa32019-07-08 14:17:10 +020070 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020071 if (ns) {
72 if (!IS_YIN_NS(ns->uri)) {
73 return YANG_CUSTOM;
74 }
75 } else {
76 /* elements without namespace are automatically unknown */
77 return YANG_NONE;
78 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020079
David Sedlák8f7a1172019-06-20 14:42:18 +020080 start = name;
81 kw = lysp_match_kw(NULL, &name);
82
83 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020084 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
85 if (kw == YANG_VALUE && parrent == YANG_ERROR_MESSAGE) {
86 return YIN_VALUE;
87 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020088 return kw;
89 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020090 if (strncmp(start, "text", name_len) == 0) {
91 return YIN_TEXT;
92 } else if (strncmp(start, "value", name_len) == 0) {
93 return YIN_VALUE;
94 } else {
95 return YANG_NONE;
96 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020097 }
98}
99
David Sedlák872c7b42018-10-26 13:15:20 +0200100enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +0200101yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200102{
David Sedláka7406952019-04-05 10:33:07 +0200103 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200104 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200105 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200106
David Sedlák94de2aa2019-02-15 12:42:11 +0100107#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
108#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100109#define IF_ARG_PREFIX_END }
110
David Sedlák1c8b2702019-02-22 11:03:02 +0100111 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100112 case 'c':
113 already_read += 1;
114 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200115 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200116
David Sedlák94de2aa2019-02-15 12:42:11 +0100117 case 'd':
118 already_read += 1;
119 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200120 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200121
David Sedlák94de2aa2019-02-15 12:42:11 +0100122 case 'm':
123 already_read += 1;
124 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200125 break;
126
David Sedlák94de2aa2019-02-15 12:42:11 +0100127 case 'n':
128 already_read += 1;
129 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200130 break;
131
David Sedlák94de2aa2019-02-15 12:42:11 +0100132 case 't':
133 already_read += 1;
134 IF_ARG_PREFIX("a", 1)
135 IF_ARG("g", 1, YIN_ARG_TAG)
136 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
137 IF_ARG_PREFIX_END
138 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200139 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200140
David Sedlák94de2aa2019-02-15 12:42:11 +0100141 case 'u':
142 already_read += 1;
143 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200144 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200145
David Sedlák94de2aa2019-02-15 12:42:11 +0100146 case 'v':
147 already_read += 1;
148 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200149 break;
150 }
151
David Sedlákc10e7902018-12-17 02:17:59 +0100152 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200153 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200154 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200155 }
156
David Sedlák18730132019-03-15 15:51:34 +0100157#undef IF_ARG
158#undef IF_ARG_PREFIX
159#undef IF_ARG_PREFIX_END
160
David Sedlák872c7b42018-10-26 13:15:20 +0200161 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200162}
163
David Sedlák4f03b932019-07-26 13:01:47 +0200164void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200165 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200166 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200167 free(record->content);
168 }
169}
170
David Sedlák8f7a1172019-06-20 14:42:18 +0200171LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200172yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200173{
174 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200175 struct yin_arg_record *argument_record = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200176 struct sized_string prefix, name;
David Sedláka7406952019-04-05 10:33:07 +0200177
David Sedlák555c7202019-07-04 12:14:12 +0200178 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200179 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
180 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlák00250342019-06-21 14:19:39 +0200181 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200182
David Sedlákda8ffa32019-07-08 14:17:10 +0200183 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
184 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlák555c7202019-07-04 12:14:12 +0200185 argument_record->name = name.value;
186 argument_record->name_len = name.len;
187 argument_record->prefix = prefix.value;
188 argument_record->prefix_len = prefix.len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200189 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200190 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200191 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200192 }
193 }
194
David Sedlák8f7a1172019-06-20 14:42:18 +0200195cleanup:
196 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200197 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200198 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200199 }
200 return ret;
201}
202
David Sedlák4a650532019-07-10 11:55:18 +0200203LY_ERR
204yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
205{
206 int prefix = 0;
207 unsigned int c;
208 size_t utf8_char_len;
209 size_t already_read = 0;
210 while (already_read < len) {
211 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
212 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
213 already_read += utf8_char_len;
214 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
215
216 switch (val_type) {
217 case Y_IDENTIF_ARG:
218 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
219 break;
220 case Y_PREF_IDENTIF_ARG:
221 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
222 break;
223 case Y_STR_ARG:
224 case Y_MAYBE_STR_ARG:
225 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
226 break;
227 }
228 }
229
230 return LY_SUCCESS;
231}
232
David Sedlákb4e44562019-07-04 15:42:12 +0200233/**
234 * @brief Parse yin argument.
235 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200236 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200237 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200238 * @param[in,out] data Data to read from.
David Sedlák4a650532019-07-10 11:55:18 +0200239 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
240 * special argument).
David Sedlákb4e44562019-07-04 15:42:12 +0200241 * @param[out] arg_val Where value of argument should be stored. Can be NULL if arg_type is specified as YIN_ARG_NONE.
David Sedlák292763b2019-07-09 11:10:53 +0200242 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200243 * @param[in] current_element Identification of current element, used for logging.
244 *
245 * @return LY_ERR values.
246 */
247static LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +0200248yin_parse_attribute(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, enum YIN_ARGUMENT arg_type,
David Sedlák292763b2019-07-09 11:10:53 +0200249 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200250{
David Sedlák8f7a1172019-06-20 14:42:18 +0200251 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
252 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200253 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200254
David Sedlák1bccdfa2019-06-17 15:55:27 +0200255 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200256 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200257 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
258 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200259 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200260 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200261 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200262 } else if (arg == arg_type) {
David Sedlák292763b2019-07-09 11:10:53 +0200263 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Duplicit definition of %s attribute in %s element",
264 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200265 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200266 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200267 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200268 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200269 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200270 /* string is no longer supposed to be freed when the sized array is freed */
271 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200272 } else {
David Sedlák99295322019-07-17 11:34:18 +0200273 if (iter->content_len == 0) {
274 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
275 } else {
276 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
277 LY_CHECK_RET(!(*arg_val), LY_EMEM);
278 }
David Sedlák57715b12019-06-17 13:05:22 +0200279 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200280 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +0200281 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\" of %s element.", iter->name_len, iter->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200282 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200283 }
284 }
285 }
286
David Sedlák292763b2019-07-09 11:10:53 +0200287 /* anything else than Y_MAYBE_STR_ARG is mandatory */
288 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200289 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.", yin_attr2str(arg_type), ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200290 return LY_EVALID;
291 }
292
293 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200294}
295
David Sedlákd6e56892019-07-01 15:40:24 +0200296/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200297 * @brief Get record with given type. Array must be sorted in ascending order by array[n].type.
David Sedlákd6e56892019-07-01 15:40:24 +0200298 *
299 * @param[in] type Type of wanted record.
300 * @param[in] array_size Size of array.
301 * @param[in] array Searched array.
302 *
303 * @return Pointer to desired record on success, NULL if element is not in the array.
304 */
David Sedlákb4e44562019-07-04 15:42:12 +0200305static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200306get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200307{
David Sedlákb0faad82019-07-04 14:28:59 +0200308 signed char left = 0, right = array_size - 1, middle;
309
310 while (left <= right) {
311 middle = left + (right - left) / 2;
312
313 if (array[middle].type == type) {
314 return &array[middle];
315 }
316
317 if (array[middle].type < type) {
318 left = middle + 1;
319 } else {
320 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200321 }
322 }
323
324 return NULL;
325}
326
David Sedlákbba38e52019-07-09 15:20:01 +0200327/**
328 * @brief Helper function to check mandatory constraint of subelement.
329 *
330 * @param[in,out] ctx Yin parser context for logging and to store current state.
331 * @param[in] subelem_info Array of information about subelements.
332 * @param[in] subelem_info_size Size of subelem_info array.
333 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
334 *
335 * @return LY_ERR values.
336 */
337static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200338yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200339 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200340{
David Sedlákb0faad82019-07-04 14:28:59 +0200341 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200342 /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
David Sedlák21f87cd2019-07-03 16:53:23 +0200343 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200344 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory subelement %s of %s element.",
David Sedlák555c7202019-07-04 12:14:12 +0200345 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200346 return LY_EVALID;
347 }
348 }
349
350 return LY_SUCCESS;
351}
352
David Sedlákbba38e52019-07-09 15:20:01 +0200353/**
354 * @brief Helper function to check "first" constraint of subelement.
355 *
356 * @param[in,out] ctx Yin parser context for logging and to store current state.
357 * @param[in] subelem_info Array of information about subelements.
358 * @param[in] subelem_info_size Size of subelem_info array.
359 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
360 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement.
361 *
362 * @return LY_ERR values.
363 */
364static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200365yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200366 signed char subelem_info_size, enum yang_keyword current_element,
367 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200368{
David Sedlákb0faad82019-07-04 14:28:59 +0200369 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200370 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200371 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Subelement %s of %s element must be defined as first subelement.",
David Sedlák555c7202019-07-04 12:14:12 +0200372 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200373 return LY_EVALID;
374 }
375 }
376
377 return LY_SUCCESS;
378}
379
David Sedlákbba38e52019-07-09 15:20:01 +0200380/**
381 * @brief Helper function to check if array of information about subelements is in ascending order.
382 *
383 * @param[in] subelem_info Array of information about subelements.
384 * @param[in] subelem_info_size Size of subelem_info array.
385 *
386 * @return True iff subelem_info array is in ascending order, False otherwise.
387 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200388#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200389static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200390is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
391{
David Sedlák292763b2019-07-09 11:10:53 +0200392 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200393
394 for (signed char i = 0; i < subelem_info_size; ++i) {
395 if (subelem_info[i].type <= current) {
396 return false;
397 }
398 current = subelem_info[i].type;
399 }
400
401 return true;
402}
David Sedlák5545f5d2019-07-11 11:55:16 +0200403#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200404
David Sedlákd6e56892019-07-01 15:40:24 +0200405/**
David Sedlákb4e44562019-07-04 15:42:12 +0200406 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
407 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200408 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200409 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200410 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200411 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200412 * @param[in] kw Type of current element.
413 * @param[out] value Where value of attribute should be stored.
414 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200415 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákda8ffa32019-07-08 14:17:10 +0200416 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200417 *
David Sedlákd6e56892019-07-01 15:40:24 +0200418 * @return LY_ERR values.
419 */
David Sedlákb4e44562019-07-04 15:42:12 +0200420static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200421yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlák292763b2019-07-09 11:10:53 +0200422 const char **value, enum YIN_ARGUMENT arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200423{
David Sedlák1f90d252019-07-10 17:09:32 +0200424 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200425 struct yin_subelement subelems[1] = {
426 {YANG_CUSTOM, NULL, 0}
427 };
David Sedlákb4e44562019-07-04 15:42:12 +0200428
David Sedlákda8ffa32019-07-08 14:17:10 +0200429 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200430}
431
432/**
David Sedlákd3983112019-07-12 11:20:56 +0200433 * @brief Parse pattern element.
434 *
435 * @param[in,out] ctx Yin parser context for logging and to store current state.
436 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
437 * @param[in,out] data Data to read from, always moved to currently handled character.
438 * @param[in,out] patterns Restrictions to add to.
439 *
440 * @return LY_ERR values.
441 */
442static LY_ERR
443yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
444 struct lysp_type *type)
445{
446 const char *real_value = NULL;
447 char *saved_value = NULL;
448 struct lysp_restr *restr;
449
450 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
451 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
452 size_t len = strlen(real_value);
453
454 saved_value = malloc(len + 2);
455 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
456 memmove(saved_value + 1, real_value, len);
457 FREE_STRING(ctx->xml_ctx.ctx, real_value);
458 saved_value[0] = 0x06;
459 saved_value[len + 1] = '\0';
460 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
461 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
462 type->flags |= LYS_SET_PATTERN;
463
464 struct yin_subelement subelems[6] = {
465 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
466 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
467 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
468 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
469 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
470 {YANG_CUSTOM, NULL, 0}
471 };
472 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
473}
474
David Sedlákf75d55e2019-07-12 16:52:50 +0200475static LY_ERR
476yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
477 struct lysp_type *type)
478{
479 const char *temp_val = NULL;
480 char *ptr;
481 unsigned long int num;
482
483 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
484
485 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
486 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
487 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
488 return LY_EVALID;
489 }
490
491 errno = 0;
492 num = strtoul(temp_val, &ptr, 10);
493 if (*ptr != '\0') {
494 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
495 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
496 return LY_EVALID;
497 }
498 if ((errno == ERANGE) || (num > 18)) {
499 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
500 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
501 return LY_EVALID;
502 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200503 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200504 type->fraction_digits = num;
505 type->flags |= LYS_SET_FRDIGITS;
506 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200507 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200508 };
509 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
510}
511
David Sedlák07869a52019-07-12 14:28:19 +0200512/**
David Sedlák43801c92019-08-05 15:58:54 +0200513 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200514 *
515 * @param[in,out] ctx YIN parser context for logging and to store current state.
516 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
517 * @param[in,out] data Data to read from, always moved to currently handled character.
518 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
519 * @param[in,out] enums Enums or bits to add to.
520 *
521 * @return LY_ERR values.
522 */
David Sedlákca36c422019-07-12 12:47:55 +0200523static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200524yin_parse_enum(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200525{
David Sedlák07869a52019-07-12 14:28:19 +0200526 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200527
David Sedlák43801c92019-08-05 15:58:54 +0200528 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
529 type->flags |= LYS_SET_ENUM;
530 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
531 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
532 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
533 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200534
535 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200536 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
537 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200538 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
539 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200540 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200541 {YANG_CUSTOM, NULL, 0}
542 };
David Sedlák43801c92019-08-05 15:58:54 +0200543 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
544}
545
546/**
547 * @brief Parse bit element.
548 *
549 * @param[in,out] ctx YIN parser context for logging and to store current state.
550 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
551 * @param[in,out] data Data to read from, always moved to currently handled character.
552 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
553 * @param[in,out] enums Enums or bits to add to.
554 *
555 * @return LY_ERR values.
556 */
557static LY_ERR
558yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
559 struct lysp_type *type)
560{
561 struct lysp_type_enum *en;
562
563 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
564 type->flags |= LYS_SET_BIT;
565 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
566 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
567
568 struct yin_subelement subelems[6] = {
569 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
570 {YANG_IF_FEATURE, &en->iffeatures, 0},
571 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
572 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
573 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
574 {YANG_CUSTOM, NULL, 0}
575 };
576 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200577}
578
David Sedlákd3983112019-07-12 11:20:56 +0200579/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200580 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
581 * more instances, such as base or if-feature.
582 *
583 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200584 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200585 * @param[in,out] data Data to read from, always moved to currently handled character.
586 * @param[in] kw Type of current element.
587 * @param[out] values Parsed values to add to.
588 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200589 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200590 * @param[in,out] exts Extension instance to add to.
591 *
592 * @return LY_ERR values.
593 */
594static LY_ERR
595yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlák292763b2019-07-09 11:10:53 +0200596 const char ***values, enum YIN_ARGUMENT arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
David Sedlák5f8191e2019-07-08 16:35:52 +0200597{
598 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200599 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200600 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200601 struct yin_subelement subelems[1] = {
602 {YANG_CUSTOM, &index, 0}
603 };
604
David Sedlák1f90d252019-07-10 17:09:32 +0200605 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200606
607 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
608}
609
610/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200611 * @brief Parse require instance element.
612 *
613 * @param[in,out] ctx Yin parser context for logging and to store current state.
614 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
615 * @param[in,out] data Data to read from, always moved to currently handled character.
616 * @prama[out] type Type structure to store value, flag and extensions.
617 *
618 * @return LY_ERR values.
619 */
620static LY_ERR
621yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
622 const char **data, struct lysp_type *type)
623{
624 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200625 struct yin_subelement subelems[1] = {
626 {YANG_CUSTOM, NULL, 0}
627 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200628
629 type->flags |= LYS_SET_REQINST;
630 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
631 if (strcmp(temp_val, "true") == 0) {
632 type->require_instance = 1;
633 } else if (strcmp(temp_val, "false") != 0) {
634 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "require-instance");
635 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
636 return LY_EVALID;
637 }
638 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
639
640 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
641}
642
643/**
David Sedlákce77bf52019-07-11 16:59:31 +0200644 * @brief Parse modifier element.
645 *
646 * @param[in,out] ctx Yin parser context for logging and to store current state.
647 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
648 * @param[in,out] data Data to read from, always moved to currently handled character.
649 * @param[in,out] pat Value to write to.
650 * @param[in,out] exts Extension instances to add to.
651 *
652 * @return LY_ERR values.
653 */
654static LY_ERR
655yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
656 const char **pat, struct lysp_ext_instance **exts)
657{
David Sedlákd3983112019-07-12 11:20:56 +0200658 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200659 const char *temp_val;
660 char *modified_val;
661 struct yin_subelement subelems[1] = {
662 {YANG_CUSTOM, NULL, 0}
663 };
664
665 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
666 if (strcmp(temp_val, "invert-match") != 0) {
667 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "modifier");
668 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
669 return LY_EVALID;
670 }
David Sedlákd3983112019-07-12 11:20:56 +0200671 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200672
673 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200674 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200675 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200676 strcpy(modified_val, *pat);
677 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200678
679 /* modify the new value */
680 modified_val[0] = 0x15;
681 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
682
683 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
684}
685
686/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200687 * @brief Parse a restriction element (length, range or one instance of must).
688 *
689 * @param[in,out] ctx Yin parser context for logging and to store current state.
690 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
691 * @param[in,out] data Data to read from, always moved to currently handled character.
692 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
693 * @param[in]
694 */
695static LY_ERR
696yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
697 enum yang_keyword restr_kw, struct lysp_restr *restr)
698{
699 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
700 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200701 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
702 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
703 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
704 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
705 {YANG_CUSTOM, NULL, 0}
706 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200707 /* argument of must is called condition, but argument of length and range is called value */
708 enum YIN_ARGUMENT arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
709 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
710
711 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
712}
713
714/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200715 * @brief Parse must element.
716 *
717 * @param[in,out] ctx YIN parser context for logging and to store current state.
718 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
719 * @param[in,out] data Data to read from, always moved to currently handled character.
720 * @param[in,out] restrs Restrictions to add to.
721 *
722 * @return LY_ERR values.
723 */
724static LY_ERR
725yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
726{
727 struct lysp_restr *restr;
728
729 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
730 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
731}
732
733/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200734 * @brief Parse position or value element.
735 *
736 * @param[in,out] ctx YIN parser context for logging and to store current state.
737 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
738 * @param[in,out] data Data to read from, always moved to currently handled character.
739 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
740 * @param[out] enm Enum structure to save value, flags and extensions.
741 *
742 * @return LY_ERR values.
743 */
744static LY_ERR
745yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
746 enum yang_keyword kw, struct lysp_type_enum *enm)
747{
748 assert(kw == YANG_POSITION || kw == YANG_VALUE);
749 const char *temp_val = NULL;
750 char *ptr;
751 long int num;
752 unsigned long int unum;
753
754 /* set value flag */
755 enm->flags |= LYS_SET_VALUE;
756
757 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200758 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, kw));
David Sedlákae5378f2019-07-17 11:37:59 +0200759 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
760 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200761 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
762 goto error;
763 }
764
765 /* convert value */
766 errno = 0;
767 if (kw == YANG_VALUE) {
768 num = strtol(temp_val, &ptr, 10);
769 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
770 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
771 goto error;
772 }
773 } else {
774 unum = strtoul(temp_val, &ptr, 10);
775 if (unum > UINT64_C(4294967295)) {
776 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
777 goto error;
778 }
779 }
780 /* check if whole argument value was converted */
781 if (*ptr != '\0') {
782 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +0200783 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200784 }
785 if (errno == ERANGE) {
786 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, ly_stmt2str(kw));
787 goto error;
788 }
789 /* save correctly ternary operator can't be used because num and unum have different signes */
790 if (kw == YANG_VALUE) {
791 enm->value = num;
792 } else {
793 enm->value = unum;
794 }
795 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
796
797 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200798 struct yin_subelement subelems[1] = {
799 {YANG_CUSTOM, NULL, 0}
800 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200801 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
802
803 error:
804 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
805 return LY_EVALID;
806}
807
David Sedlák05404f62019-07-24 14:11:53 +0200808
809/**
810 * @brief Parse belongs-to element.
811 *
812 * @param[in] ctx Yin parser context for logging and to store current state.
813 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
814 * @param[in,out] data Data to read from, always moved to currently handled character.
815 * @param[out] submod Structure of submodule that is being parsed.
816 * @param[in,out] exts Extension instances to add to.
817 *
818 * @return LY_ERR values
819 */
820static LY_ERR
821yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
822 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
823{
824 struct yin_subelement subelems[2] = {
825 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
826 {YANG_CUSTOM, NULL, 0}
827 };
828 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
829
830 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
831}
832
David Sedlák5545f5d2019-07-11 11:55:16 +0200833/**
David Sedlákc1771b12019-07-10 15:55:46 +0200834 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200835 * text element as child
836 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200837 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200838 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200839 * @param[in] Type of element can be set to YANG_ORGANIZATION or YANG_CONTACT or YANG_DESCRIPTION or YANG_REFERENCE.
David Sedlákb4e44562019-07-04 15:42:12 +0200840 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200841 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200842 *
843 * @return LY_ERR values.
844 */
845static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200846yin_parse_meta_element(struct yin_parser_ctx *ctx, const char **data, enum yang_keyword elem_type,
David Sedlákb4e44562019-07-04 15:42:12 +0200847 const char **value, struct lysp_ext_instance **exts)
848{
849 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
850
David Sedlák968ac342019-07-11 15:17:59 +0200851 struct yin_subelement subelems[2] = {
852 {YANG_CUSTOM, NULL, 0},
853 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
854 };
David Sedlákb4e44562019-07-04 15:42:12 +0200855
David Sedlákda8ffa32019-07-08 14:17:10 +0200856 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200857}
858
859/**
David Sedlákc1771b12019-07-10 15:55:46 +0200860 * @brief Parse error-message element.
861 *
862 * @param[in,out] ctx Yin parser context for logging and to store current state.
863 * @param[in,out] data Data to read from.
864 * @param[out] value Where the content of error-message element should be stored.
865 * @param[in,out] exts Extension instance to add to.
866 *
867 * @return LY_ERR values.
868 */
869static LY_ERR
870yin_parse_err_msg_element(struct yin_parser_ctx *ctx, const char **data, const char **value,
871 struct lysp_ext_instance **exts)
872{
David Sedlák968ac342019-07-11 15:17:59 +0200873 struct yin_subelement subelems[2] = {
874 {YANG_CUSTOM, NULL, 0},
875 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
876 };
David Sedlákc1771b12019-07-10 15:55:46 +0200877
878 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
879}
880
881/**
David Sedlák374d2b32019-07-17 15:06:55 +0200882 * @brief parse type element.
883 *
884 * @brief Parse position or value element.
885 *
886 * @param[in,out] ctx YIN parser context for logging and to store current state.
887 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
888 * @param[in,out] data Data to read from, always moved to currently handled character.
889 * @param[in,out] type Type to wrote to.
890 * @param[in,out] exts Extension instance to add to.
891 *
892 * @return LY_ERR values.
893 */
894static LY_ERR
895yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
896{
897 struct yin_subelement subelems[11] = {
898 {YANG_BASE, type, 0},
899 {YANG_BIT, type, 0},
900 {YANG_ENUM, type, 0},
901 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
902 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
903 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
904 {YANG_PATTERN, type, 0},
905 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
906 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
907 {YANG_TYPE, type},
908 {YANG_CUSTOM, NULL, 0},
909 };
910 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
911 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
912}
913
David Sedlák1af868e2019-07-17 17:03:14 +0200914/**
915 * @brief Parse max-elements element.
916 *
917 * @param[in,out] ctx YIN parser context for logging and to store current state.
918 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
919 * @param[in,out] data Data to read from, always moved to currently handled character.
920 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200921 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +0200922 * @param[in,out] exts Extension instances to add to.
923 *
924 * @return LY_ERR values.
925 */
926static LY_ERR
927yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
928 uint16_t *flags, struct lysp_ext_instance **exts)
929{
930 const char *temp_val = NULL;
931 char *ptr;
932 unsigned long int num;
933 struct yin_subelement subelems[1] = {
934 {YANG_CUSTOM, NULL, 0},
935 };
David Sedlák374d2b32019-07-17 15:06:55 +0200936
David Sedlák1af868e2019-07-17 17:03:14 +0200937 *flags |= LYS_SET_MAX;
938 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
939 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
940 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
941 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
942 return LY_EVALID;
943 }
944
945 if (strcmp(temp_val, "unbounded")) {
946 errno = 0;
947 num = strtoul(temp_val, &ptr, 10);
948 if (*ptr != '\0') {
949 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
950 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
951 return LY_EVALID;
952 }
953 if ((errno == ERANGE) || (num > UINT32_MAX)) {
954 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "max-elements");
955 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
956 return LY_EVALID;
957 }
958 *max = num;
959 }
960 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
961 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
962}
David Sedlák374d2b32019-07-17 15:06:55 +0200963
964/**
David Sedlák09e18c92019-07-18 11:17:11 +0200965 * @brief Parse max-elements element.
966 *
967 * @param[in,out] ctx YIN parser context for logging and to store current state.
968 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
969 * @param[in,out] data Data to read from, always moved to currently handled character.
970 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200971 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +0200972 * @param[in,out] exts Extension instances to add to.
973 *
974 * @return LY_ERR values.
975 */
976static LY_ERR
977yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
978 uint16_t *flags, struct lysp_ext_instance **exts)
979{
980 const char *temp_val = NULL;
981 char *ptr;
982 unsigned long int num;
983 struct yin_subelement subelems[1] = {
984 {YANG_CUSTOM, NULL, 0},
985 };
986
987 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +0200988 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MIN_ELEMENTS));
David Sedlák09e18c92019-07-18 11:17:11 +0200989
990 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
991 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
992 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
993 return LY_EVALID;
994 }
995
996 errno = 0;
997 num = strtoul(temp_val, &ptr, 10);
998 if (ptr[0] != 0) {
999 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
1000 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1001 return LY_EVALID;
1002 }
1003 if (errno == ERANGE || num > UINT32_MAX) {
1004 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "min-elements");
1005 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1006 return LY_EVALID;
1007 }
1008 *min = num;
1009 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001010 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001011}
1012
David Sedláka2dad212019-07-18 12:45:19 +02001013/**
1014 * @brief Parse min-elements or max-elements element.
1015 *
1016 * @param[in,out] ctx YIN parser context for logging and to store current state.
1017 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1018 * @param[in,out] data Data to read from, always moved to currently handled character.
1019 * @param[in] parent Identification of parent element.
1020 * @param[in] current Identification of current element.
1021 * @param[in] dest Where the parsed value and flags should be stored.
1022 *
1023 * @return LY_ERR values.
1024 */
David Sedlák09e18c92019-07-18 11:17:11 +02001025static LY_ERR
1026yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1027 enum yang_keyword parent, enum yang_keyword current, void *dest)
1028{
1029 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001030 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001031 uint32_t *lim;
1032 uint16_t *flags;
1033 struct lysp_ext_instance **exts;
1034
1035 if (parent == YANG_LEAF_LIST) {
1036 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1037 flags = &((struct lysp_node_leaflist *)dest)->flags;
1038 exts = &((struct lysp_node_leaflist *)dest)->exts;
1039 } else if (parent == YANG_REFINE) {
1040 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1041 flags = &((struct lysp_refine *)dest)->flags;
1042 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001043 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001044 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1045 flags = &((struct lysp_node_list *)dest)->flags;
1046 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001047 } else {
1048 lim = ((struct minmax_dev_meta *)dest)->lim;
1049 flags = ((struct minmax_dev_meta *)dest)->flags;
1050 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001051 }
1052
1053 if (current == YANG_MAX_ELEMENTS) {
1054 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1055 } else {
1056 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1057 }
1058
1059 return LY_SUCCESS;
1060}
1061
1062/**
David Sedláka2dad212019-07-18 12:45:19 +02001063 * @brief Parser ordered-by element.
1064 *
1065 * @param[in,out] ctx YIN parser context for logging and to store current state.
1066 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1067 * @param[in,out] data Data to read from, always moved to currently handled character.
1068 * @param[out] flags Flags to write to.
1069 * @param[in,out] exts Extension instance to add to.
1070 *
1071 * @return LY_ERR values.
1072 */
1073static LY_ERR
1074yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1075 uint16_t *flags, struct lysp_ext_instance **exts)
1076{
1077 const char *temp_val;
1078 struct yin_subelement subelems[1] = {
1079 {YANG_CUSTOM, NULL, 0},
1080 };
1081
1082 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1083 if (strcmp(temp_val, "system") == 0) {
1084 *flags |= LYS_ORDBY_SYSTEM;
1085 } else if (strcmp(temp_val, "user") == 0) {
1086 *flags |= LYS_ORDBY_USER;
1087 } else {
1088 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "ordered-by");
1089 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1090 return LY_EVALID;
1091 }
1092 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1093
1094 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1095}
1096
1097/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001098 * @brief parse any-data or any-xml element.
1099 *
1100 * @param[in,out] ctx YIN parser context for logging and to store current state.
1101 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1102 * @param[in,out] data Data to read from, always moved to currently handled character.
1103 * @param[in] any_kw Identification of current element, can be set to YANG_ANY_DATA or YANG_ANY_XML
David Sedlák05404f62019-07-24 14:11:53 +02001104 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001105 *
1106 * @return LY_ERR values.
1107 */
1108static LY_ERR
1109yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1110 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1111{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001112 struct lysp_node_anydata *any;
1113
David Sedlák8d552d62019-08-06 15:29:05 +02001114 /* create new sibling */
1115 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001116 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1117 any->parent = node_meta->parent;
1118
David Sedlák8a83bbb2019-07-18 14:46:00 +02001119 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001120 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &any->name, Y_IDENTIF_ARG, any_kw));
David Sedlák8a83bbb2019-07-18 14:46:00 +02001121
1122 struct yin_subelement subelems[9] = {
1123 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1124 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1125 {YANG_IF_FEATURE, &any->iffeatures, 0},
1126 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1127 {YANG_MUST, &any->musts, 0},
1128 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1129 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1130 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1131 {YANG_CUSTOM, NULL, 0},
1132 };
1133 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1134}
1135
1136/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001137 * @brief parse leaf element.
1138 *
1139 * @param[in,out] ctx YIN parser context for logging and to store current state.
1140 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1141 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001142 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák203ca3a2019-07-18 15:26:25 +02001143 *
1144 * @return LY_ERR values.
1145 */
1146static LY_ERR
1147yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1148 struct tree_node_meta *node_meta)
1149{
David Sedlák203ca3a2019-07-18 15:26:25 +02001150 struct lysp_node_leaf *leaf;
1151
David Sedlák8d552d62019-08-06 15:29:05 +02001152 /* create structure new leaf */
1153 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001154 leaf->nodetype = LYS_LEAF;
1155 leaf->parent = node_meta->parent;
1156
David Sedlák203ca3a2019-07-18 15:26:25 +02001157 /* parser argument */
1158 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1159
1160 /* parse content */
1161 struct yin_subelement subelems[12] = {
1162 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1163 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1164 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1165 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1166 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1167 {YANG_MUST, &leaf->musts, 0},
1168 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1169 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1170 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1171 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1172 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1173 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001174 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001175 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1176}
1177
1178/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001179 * @brief Parse leaf-list element.
1180 *
1181 * @param[in,out] ctx YIN parser context for logging and to store current state.
1182 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1183 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001184 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001185 *
1186 * @return LY_ERR values.
1187 */
1188static LY_ERR
1189yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1190 struct tree_node_meta *node_meta)
1191{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001192 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001193
David Sedlák8d552d62019-08-06 15:29:05 +02001194 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, llist, next);
1195
David Sedlákc3da3ef2019-07-19 12:56:08 +02001196 llist->nodetype = LYS_LEAFLIST;
1197 llist->parent = node_meta->parent;
1198
David Sedlákc3da3ef2019-07-19 12:56:08 +02001199 /* parse argument */
1200 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1201
1202 /* parse content */
1203 struct yin_subelement subelems[14] = {
1204 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1205 {YANG_DEFAULT, &llist->dflts, 0},
1206 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1207 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1208 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1209 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1210 {YANG_MUST, &llist->musts, 0},
1211 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1212 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1213 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1214 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1215 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1216 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1217 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001218 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001219 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1220
1221 /* invalid combination of subelements */
1222 if ((llist->min) && (llist->dflts)) {
1223 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
1224 return LY_EVALID;
1225 }
1226 if (llist->max && llist->min > llist->max) {
1227 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1228 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1229 llist->min, llist->max);
1230 return LY_EVALID;
1231 }
1232
1233 return LY_SUCCESS;
1234}
1235
1236/**
David Sedlák04e17b22019-07-19 15:29:48 +02001237 * @brief Parse typedef element.
1238 *
1239 * @param[in,out] ctx YIN parser context for logging and to store current state.
1240 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1241 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001242 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001243 *
1244 * @return LY_ERR values.
1245 */
1246static LY_ERR
1247yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1248 struct typedef_meta *typedef_meta)
1249{
1250 struct lysp_tpdf *tpdf;
1251 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *typedef_meta->typedefs, tpdf, LY_EMEM);
1252
1253 /* parse argument */
1254 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1255
1256 /* parse content */
1257 struct yin_subelement subelems[7] = {
1258 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1259 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1260 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1261 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1262 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1263 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1264 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001265 };
David Sedlák04e17b22019-07-19 15:29:48 +02001266 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1267
1268 /* store data for collision check */
1269 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1270 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1271 }
1272
1273 return LY_SUCCESS;
1274}
1275
1276/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001277 * @brief Parse refine element.
1278 *
1279 * @param[in,out] ctx YIN parser context for logging and to store current state.
1280 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1281 * @param[in,out] data Data to read from, always moved to currently handled character.
1282 * @param[in,out] refines Refines to add to.
1283 *
1284 * @return LY_ERR values.
1285 */
1286static LY_ERR
1287yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1288 struct lysp_refine **refines)
1289{
1290 struct lysp_refine *rf;
1291
1292 /* allocate new refine */
1293 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1294
1295 /* parse attribute */
1296 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1297 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1298
1299 /* parse content */
1300 struct yin_subelement subelems[11] = {
1301 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1302 {YANG_DEFAULT, &rf->dflts, 0},
1303 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1304 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1305 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1306 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1307 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1308 {YANG_MUST, &rf->musts, 0},
1309 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1310 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1311 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001312 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001313 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1314}
1315
1316/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001317 * @brief Parse uses element.
1318 *
1319 * @param[in,out] ctx YIN parser context for logging and to store current state.
1320 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1321 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001322 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001323 *
1324 * @return LY_ERR values.
1325 */
1326static LY_ERR
1327yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1328 struct tree_node_meta *node_meta)
1329{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001330 struct lysp_node_uses *uses;
1331
David Sedlák8d552d62019-08-06 15:29:05 +02001332 /* create new uses */
1333 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001334 uses->nodetype = LYS_USES;
1335 uses->parent = node_meta->parent;
1336
David Sedlák0d6de5a2019-07-22 13:25:44 +02001337 /* parse argument */
1338 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1339
1340 /* parse content */
1341 struct augment_meta augments = {(struct lysp_node *)uses, &uses->augments};
1342 struct yin_subelement subelems[8] = {
1343 {YANG_AUGMENT, &augments, 0},
1344 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1345 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1346 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1347 {YANG_REFINE, &uses->refines, 0},
1348 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1349 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1350 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001351 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001352 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1353 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1354
1355 return LY_SUCCESS;
1356}
1357
1358/**
David Sedlákaa854b02019-07-22 14:17:10 +02001359 * @brief Parse revision element.
1360 *
1361 * @param[in,out] ctx YIN parser context for logging and to store current state.
1362 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1363 * @param[in,out] data Data to read from, always moved to currently handled character.
1364 * @param[in,out] revs Parsed revisions to add to.
1365 *
1366 * @return LY_ERR values.
1367 */
1368static LY_ERR
1369yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1370 struct lysp_revision **revs)
1371{
1372 struct lysp_revision *rev;
1373 const char *temp_date = NULL;
1374
1375 /* allocate new reivison */
1376 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1377
1378 /* parse argument */
1379 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1380 /* check value */
1381 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1382 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1383 return LY_EVALID;
1384 }
1385 strcpy(rev->date, temp_date);
1386 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1387
1388 /* parse content */
1389 struct yin_subelement subelems[3] = {
1390 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1391 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1392 {YANG_CUSTOM, NULL, 0},
1393 };
1394 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1395}
1396
David Sedlák5e13dea2019-07-22 16:06:45 +02001397/**
1398 * @brief Parse include element.
1399 *
1400 * @param[in,out] ctx YIN parser context for logging and to store current state.
1401 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1402 * @param[in,out] data Data to read from, always moved to currently handled character.
1403 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1404 *
1405 * @return LY_ERR values.
1406 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001407static LY_ERR
1408yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1409 struct include_meta *inc_meta)
1410{
1411 struct lysp_include *inc;
1412
1413 /* allocate new include */
1414 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1415
1416 /* parse argument */
1417 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1418
1419 /* submodules share the namespace with the module names, so there must not be
1420 * a module of the same name in the context, no need for revision matching */
1421 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
1422 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG,
1423 "Name collision between module and submodule of name \"%s\".", inc->name);
1424 return LY_EVALID;
1425 }
1426
1427 /* parse content */
1428 struct yin_subelement subelems[4] = {
1429 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1430 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1431 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1432 {YANG_CUSTOM, NULL, 0},
1433 };
1434 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1435}
1436
David Sedlákaa854b02019-07-22 14:17:10 +02001437/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001438 * @brief Parse feature element.
1439 *
1440 * @param[in,out] ctx YIN parser context for logging and to store current state.
1441 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1442 * @param[in,out] data Data to read from, always moved to currently handled character.
1443 * @param[in,out] features Features to add to.
1444 *
1445 * @return LY_ERR values.
1446 */
1447static LY_ERR
1448yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1449 struct lysp_feature **features)
1450{
1451 struct lysp_feature *feat;
1452
1453 /* allocate new feature */
1454 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1455
1456 /* parse argument */
1457 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1458
1459 /* parse content */
1460 struct yin_subelement subelems[5] = {
1461 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1462 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1463 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1464 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1465 {YANG_CUSTOM, NULL, 0},
1466 };
1467 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1468}
1469
1470/**
David Sedlák28794f22019-07-22 16:45:00 +02001471 * @brief Parse identity element.
1472 *
1473 * @param[in,out] ctx YIN parser context for logging and to store current state.
1474 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1475 * @param[in,out] data Data to read from, always moved to currently handled character.
1476 * @param[in,out] identities Identities to add to.
1477 *
1478 * @return LY_ERR values.
1479 */
1480static LY_ERR
1481yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1482 struct lysp_ident **identities)
1483{
1484 struct lysp_ident *ident;
1485
1486 /* allocate new identity */
1487 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1488
1489 /* parse argument */
1490 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1491
1492 /* parse content */
1493 struct yin_subelement subelems[6] = {
1494 {YANG_BASE, &ident->bases, 0},
1495 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1496 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1497 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1498 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1499 {YANG_CUSTOM, NULL, 0},
1500 };
1501 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1502}
1503
1504/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001505 * @brief Parse list element.
1506 *
1507 * @param[in,out] ctx YIN parser context for logging and to store current state.
1508 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1509 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001510 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákaf536aa2019-07-23 13:42:23 +02001511 *
1512 * @return LY_ERR values.
1513 */
1514static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001515yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1516 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001517{
David Sedlákaf536aa2019-07-23 13:42:23 +02001518 struct lysp_node_list *list;
1519
David Sedlák8d552d62019-08-06 15:29:05 +02001520 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02001521 list->nodetype = LYS_LIST;
1522 list->parent = node_meta->parent;
1523
David Sedlákaf536aa2019-07-23 13:42:23 +02001524 /* parse argument */
1525 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1526
1527 /* parse list content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001528 struct action_meta act_meta = {(struct lysp_node *)list, &list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001529 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
1530 struct typedef_meta typedef_meta = {(struct lysp_node *)list, &list->typedefs};
David Sedlák031b9e72019-07-23 15:19:37 +02001531 struct notif_meta notif_meta = {(struct lysp_node *)list, &list->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001532 struct grouping_meta gr_meta = {(struct lysp_node *)list, &list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001533 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001534 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001535 {YANG_ANYDATA, &new_node_meta, 0},
1536 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001537 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001538 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001539 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001540 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001541 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001542 {YANG_IF_FEATURE, &list->iffeatures, 0},
1543 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1544 {YANG_LEAF, &new_node_meta, 0},
1545 {YANG_LEAF_LIST, &new_node_meta, 0},
1546 {YANG_LIST, &new_node_meta, 0},
1547 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1548 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1549 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001550 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001551 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1552 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1553 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1554 {YANG_TYPEDEF, &typedef_meta, 0},
1555 {YANG_UNIQUE, &list->uniques, 0},
1556 {YANG_USES, &new_node_meta, 0},
1557 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1558 {YANG_CUSTOM, NULL, 0},
1559 };
1560 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1561
1562 /* finalize parent pointers to the reallocated items */
1563 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1564
1565 if (list->max && list->min > list->max) {
1566 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1567 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1568 list->min, list->max);
1569 return LY_EVALID;
1570 }
1571
1572 return LY_SUCCESS;
1573}
1574
1575/**
David Sedlák031b9e72019-07-23 15:19:37 +02001576 * @brief Parse notification element.
1577 *
1578 * @param[in,out] ctx YIN parser context for logging and to store current state.
1579 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1580 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001581 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001582 *
1583 * @return LY_ERR values.
1584 */
1585static LY_ERR
1586yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1587 struct notif_meta *notif_meta)
1588{
1589 struct lysp_notif *notif;
1590
1591 /* allocate new notification */
1592 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notif_meta->notifs, notif, LY_EMEM);
1593 notif->nodetype = LYS_NOTIF;
1594 notif->parent = notif_meta->parent;
1595
1596 /* parse argument */
1597 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1598
1599 /* parse notification content */
1600 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
1601 struct typedef_meta typedef_meta = {(struct lysp_node *)notif, &notif->typedefs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001602 struct grouping_meta gr_meta = {(struct lysp_node *)notif, &notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001603 struct yin_subelement subelems[16] = {
1604 {YANG_ANYDATA, &node_meta, 0},
1605 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001606 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001607 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001608 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001609 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001610 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1611 {YANG_LEAF, &node_meta, 0},
1612 {YANG_LEAF_LIST, &node_meta, 0},
1613 {YANG_LIST, &node_meta, 0},
1614 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1615 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1616 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1617 {YANG_TYPEDEF, &typedef_meta, 0},
1618 {YANG_USES, &node_meta, 0},
1619 {YANG_CUSTOM, NULL, 0},
1620 };
1621 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1622
1623 /* finalize parent pointers to the reallocated items */
1624 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1625
1626 return LY_SUCCESS;
1627}
1628
1629/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001630 * @brief Parse notification element.
1631 *
1632 * @param[in,out] ctx YIN parser context for logging and to store current state.
1633 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1634 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001635 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001636 *
1637 * @return LY_ERR values.
1638 */
1639static LY_ERR
1640yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1641 struct grouping_meta *gr_meta)
1642{
1643 struct lysp_grp *grp;
1644
1645 /* create new grouping */
1646 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *gr_meta->groupings, grp, LY_EMEM);
1647 grp->nodetype = LYS_GROUPING;
1648 grp->parent = gr_meta->parent;
1649
1650 /* parse argument */
1651 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1652
1653 /* parse grouping content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001654 struct action_meta act_meta = {(struct lysp_node *)grp, &grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001655 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
1656 struct typedef_meta typedef_meta = {(struct lysp_node *)grp, &grp->typedefs};
1657 struct grouping_meta sub_grouping = {(struct lysp_node *)grp, &grp->groupings};
1658 struct notif_meta notif_meta = {(struct lysp_node *)grp, &grp->notifs};
1659 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001660 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001661 {YANG_ANYDATA, &node_meta, 0},
1662 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001663 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001664 {YANG_CONTAINER, &node_meta, 0},
1665 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1666 {YANG_GROUPING, &sub_grouping, 0},
1667 {YANG_LEAF, &node_meta, 0},
1668 {YANG_LEAF_LIST, &node_meta, 0},
1669 {YANG_LIST, &node_meta, 0},
1670 {YANG_NOTIFICATION, &notif_meta, 0},
1671 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
1672 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
1673 {YANG_TYPEDEF, &typedef_meta, 0},
1674 {YANG_USES, &node_meta, 0},
1675 {YANG_CUSTOM, NULL, 0},
1676 };
1677 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
1678 /* finalize parent pointers to the reallocated items */
1679 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
1680
1681 return LY_SUCCESS;
1682}
1683
1684/**
David Sedlákf111bcb2019-07-23 17:15:51 +02001685 * @brief Parse list element.
1686 *
1687 * @param[in,out] ctx YIN parser context for logging and to store current state.
1688 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1689 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001690 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákf111bcb2019-07-23 17:15:51 +02001691 *
1692 * @return LY_ERR values.
1693 */
1694static LY_ERR
1695yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1696 struct tree_node_meta *node_meta)
1697{
David Sedlákf111bcb2019-07-23 17:15:51 +02001698 struct lysp_node_container *cont;
1699
1700 /* create new container */
David Sedlák8d552d62019-08-06 15:29:05 +02001701 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02001702 cont->nodetype = LYS_CONTAINER;
1703 cont->parent = node_meta->parent;
1704
David Sedlákf111bcb2019-07-23 17:15:51 +02001705 /* parse aegument */
1706 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
1707
1708 /* parse container content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001709 struct action_meta act_meta = {(struct lysp_node *)cont, &cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02001710 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
1711 struct grouping_meta grp_meta = {(struct lysp_node *)cont, &cont->groupings};
1712 struct typedef_meta typedef_meta = {(struct lysp_node *)cont, &cont->typedefs};
1713 struct notif_meta notif_meta = {(struct lysp_node *)cont, &cont->notifs};
1714 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001715 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02001716 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1717 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001718 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001719 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
1720 {YANG_CONTAINER, &new_node_meta, 0},
1721 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
1722 {YANG_GROUPING, &grp_meta, 0},
1723 {YANG_IF_FEATURE, &cont->iffeatures, 0},
1724 {YANG_LEAF, &new_node_meta, 0},
1725 {YANG_LEAF_LIST, &new_node_meta, 0},
1726 {YANG_LIST, &new_node_meta, 0},
1727 {YANG_MUST, &cont->musts, 0},
1728 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
1729 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
1730 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
1731 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
1732 {YANG_TYPEDEF, &typedef_meta, 0},
1733 {YANG_USES, &new_node_meta, 0},
1734 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
1735 {YANG_CUSTOM, NULL, 0},
1736 };
1737 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
1738 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
1739
1740 return LY_SUCCESS;
1741}
1742
1743/**
David Sedlák5379d392019-07-24 10:42:03 +02001744 * @brief Parse case element.
1745 *
1746 * @param[in,out] ctx YIN parser context for logging and to store current state.
1747 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1748 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001749 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák5379d392019-07-24 10:42:03 +02001750 *
1751 * @return LY_ERR values.
1752 */
1753static LY_ERR
1754yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1755 struct tree_node_meta *node_meta)
1756{
David Sedlák5379d392019-07-24 10:42:03 +02001757 struct lysp_node_case *cas;
1758
1759 /* create new case */
David Sedlák8d552d62019-08-06 15:29:05 +02001760 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02001761 cas->nodetype = LYS_CASE;
1762 cas->parent = node_meta->parent;
1763
David Sedlák5379d392019-07-24 10:42:03 +02001764 /* parse argument */
1765 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
1766
1767 /* parse case content */
1768 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
1769 struct yin_subelement subelems[14] = {
1770 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1771 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001772 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02001773 {YANG_CONTAINER, &new_node_meta, 0},
1774 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
1775 {YANG_IF_FEATURE, &cas->iffeatures, 0},
1776 {YANG_LEAF, &new_node_meta, 0},
1777 {YANG_LEAF_LIST, &new_node_meta, 0},
1778 {YANG_LIST, &new_node_meta, 0},
1779 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
1780 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
1781 {YANG_USES, &new_node_meta, 0},
1782 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
1783 {YANG_CUSTOM, NULL, 0},
1784 };
1785 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
1786}
1787
1788/**
David Sedlák05404f62019-07-24 14:11:53 +02001789 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001790 *
1791 * @param[in,out] ctx YIN parser context for logging and to store current state.
1792 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1793 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001794 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001795 *
1796 * @return LY_ERR values.
1797 */
1798LY_ERR
1799yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1800 struct tree_node_meta *node_meta)
1801{
David Sedlákb7abcfa2019-07-24 12:33:35 +02001802 struct lysp_node_choice *choice;
1803
1804 /* create new choice */
David Sedlák8d552d62019-08-06 15:29:05 +02001805 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, choice, next);
1806
David Sedlákb7abcfa2019-07-24 12:33:35 +02001807 choice->nodetype = LYS_CHOICE;
1808 choice->parent = node_meta->parent;
1809
David Sedlákb7abcfa2019-07-24 12:33:35 +02001810 /* parse argument */
1811 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
1812
1813 /* parse choice content */
1814 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
1815 struct yin_subelement subelems[17] = {
1816 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1817 {YANG_ANYXML, &new_node_meta, 0},
1818 {YANG_CASE, &new_node_meta, 0},
1819 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
1820 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
1821 {YANG_CONTAINER, &new_node_meta, 0},
1822 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
1823 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
1824 {YANG_IF_FEATURE, &choice->iffeatures, 0},
1825 {YANG_LEAF, &new_node_meta, 0},
1826 {YANG_LEAF_LIST, &new_node_meta, 0},
1827 {YANG_LIST, &new_node_meta, 0},
1828 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
1829 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
1830 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
1831 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
1832 {YANG_CUSTOM, NULL, 0},
1833 };
1834 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
1835}
1836
1837/**
David Sedlák05404f62019-07-24 14:11:53 +02001838 * @brief Parse input or output element.
1839 *
1840 * @param[in,out] ctx YIN parser context for logging and to store current state.
1841 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1842 * @param[in,out] data Data to read from, always moved to currently handled character.
1843 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
1844 *
1845 * @return LY_ERR values.
1846 */
1847static LY_ERR
1848yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
1849 struct inout_meta *inout_meta)
1850{
1851 /* initiate structure */
1852 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
1853 inout_meta->inout_p->parent = inout_meta->parent;
1854
1855 /* check attributes */
1856 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
1857
1858 /* parser input/output content */
1859 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
1860 struct grouping_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->groupings};
1861 struct typedef_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->typedefs};
1862 struct yin_subelement subelems[12] = {
1863 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
1864 {YANG_ANYXML, &node_meta, 0},
1865 {YANG_CHOICE, &node_meta, 0},
1866 {YANG_CONTAINER, &node_meta, 0},
1867 {YANG_GROUPING, &grp_meta, 0},
1868 {YANG_LEAF, &node_meta, 0},
1869 {YANG_LEAF_LIST, &node_meta, 0},
1870 {YANG_LIST, &node_meta, 0},
1871 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
1872 {YANG_TYPEDEF, &typedef_meta, 0},
1873 {YANG_USES, &node_meta, 0},
1874 {YANG_CUSTOM, NULL, 0},
1875 };
1876 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
1877
1878 /* finalize parent pointers to the reallocated items */
1879 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
1880 NULL, NULL, NULL));
1881
1882 return LY_SUCCESS;
1883}
1884
David Sedlák992fb7c2019-07-24 16:51:01 +02001885/**
1886 * @brief Parse action element.
1887 *
1888 * @param[in,out] ctx YIN parser context for logging and to store current state.
1889 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1890 * @param[in,out] data Data to read from, always moved to currently handled character.
1891 * @param[in] act_meta Meta information about parent node and actions to add to.
1892 *
1893 * @return LY_ERR values.
1894 */
David Sedlák85d0eca2019-07-24 15:15:21 +02001895static LY_ERR
1896yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1897 struct action_meta *act_meta)
1898{
1899 struct lysp_action *act;
1900
1901 /* create new action */
1902 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *act_meta->actions, act, LY_EMEM);
1903 act->nodetype = LYS_ACTION;
1904 act->parent = act_meta->parent;
1905
1906 /* parse argument */
1907 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
1908
1909 /* parse content */
1910 struct grouping_meta grp_meta = {(struct lysp_node *)act, &act->groupings};
1911 struct typedef_meta typedef_meta = {(struct lysp_node *)act, &act->typedefs};
1912 struct inout_meta input = {(struct lysp_node *)act, &act->input};
1913 struct inout_meta output = {(struct lysp_node *)act, &act->output};
1914 struct yin_subelement subelems[9] = {
1915 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
1916 {YANG_GROUPING, &grp_meta, 0},
1917 {YANG_IF_FEATURE, &act->iffeatures, 0},
1918 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
1919 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
1920 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
1921 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
1922 {YANG_TYPEDEF, &typedef_meta, 0},
1923 {YANG_CUSTOM, NULL, 0},
1924 };
1925 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
1926 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
1927
1928 return LY_SUCCESS;
1929}
1930
David Sedlák05404f62019-07-24 14:11:53 +02001931/**
David Sedlák992fb7c2019-07-24 16:51:01 +02001932 * @brief Parse augment element.
1933 *
1934 * @param[in,out] ctx YIN parser context for logging and to store current state.
1935 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1936 * @param[in,out] data Data to read from, always moved to currently handled character.
1937 * @param[in] aug_meta Meta information about parent node and augments to add to.
1938 *
1939 * @return LY_ERR values.
1940 */
1941static LY_ERR
1942yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1943 struct augment_meta *aug_meta)
1944{
1945 struct lysp_augment *aug;
1946
1947 /* create new augment */
1948 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *aug_meta->augments, aug, LY_EMEM);
1949 aug->nodetype = LYS_AUGMENT;
1950 aug->parent = aug_meta->parent;
1951
1952 /* parse argument */
1953 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
1954 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
1955
1956 /* parser augment content */
1957 struct action_meta act_meta = {(struct lysp_node *)aug, &aug->actions};
1958 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
1959 struct notif_meta notif_meta = {(struct lysp_node *)aug, &aug->notifs};
1960 struct yin_subelement subelems[17] = {
1961 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
1962 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
1963 {YANG_ANYXML, &node_meta, 0},
1964 {YANG_CASE, &node_meta, 0},
1965 {YANG_CHOICE, &node_meta, 0},
1966 {YANG_CONTAINER, &node_meta, 0},
1967 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
1968 {YANG_IF_FEATURE, &aug->iffeatures, 0},
1969 {YANG_LEAF, &node_meta, 0},
1970 {YANG_LEAF_LIST, &node_meta, 0},
1971 {YANG_LIST, &node_meta, 0},
1972 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
1973 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
1974 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
1975 {YANG_USES, &node_meta, 0},
1976 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
1977 {YANG_CUSTOM, NULL, 0},
1978 };
1979 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
1980
1981 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
1982
1983 return LY_SUCCESS;
1984}
1985
David Sedlák8b754462019-07-25 16:22:13 +02001986/**
1987 * @brief Parse deviate element.
1988 *
1989 * @param[in,out] ctx YIN parser context for logging and to store current state.
1990 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1991 * @param[in,out] data Data to read from, always moved to currently handled character.
1992 * @param[in] deviates Deviates to add to.
1993 *
1994 * @return LY_ERR values.
1995 */
David Sedlák4ffcec82019-07-25 15:10:21 +02001996static LY_ERR
1997yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1998 struct lysp_deviate **deviates)
1999{
2000 LY_ERR ret = LY_SUCCESS;
2001 uint8_t dev_mod;
2002 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002003 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002004 struct lysp_deviate_add *d_add = NULL;
2005 struct lysp_deviate_rpl *d_rpl = NULL;
2006 struct lysp_deviate_del *d_del = NULL;
2007
2008 /* parse argument */
2009 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2010
2011 if (strcmp(temp_val, "not-supported") == 0) {
2012 dev_mod = LYS_DEV_NOT_SUPPORTED;
2013 } else if (strcmp(temp_val, "add") == 0) {
2014 dev_mod = LYS_DEV_ADD;
2015 } else if (strcmp(temp_val, "replace") == 0) {
2016 dev_mod = LYS_DEV_REPLACE;
2017 } else if (strcmp(temp_val, "delete") == 0) {
2018 dev_mod = LYS_DEV_DELETE;
2019 } else {
2020 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "deviate");
2021 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2022 return LY_EVALID;
2023 }
2024 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2025
2026 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2027 d = calloc(1, sizeof *d);
2028 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2029 struct yin_subelement subelems[1] = {
2030 {YANG_CUSTOM, NULL, 0}
2031 };
2032 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2033
2034 } else if (dev_mod == LYS_DEV_ADD) {
2035 d_add = calloc(1, sizeof *d_add);
2036 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2037 d = (struct lysp_deviate *)d_add;
2038 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2039 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2040 struct yin_subelement subelems[9] = {
2041 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2042 {YANG_DEFAULT, &d_add->dflts, 0},
2043 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2044 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2045 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2046 {YANG_MUST, &d_add->musts, 0},
2047 {YANG_UNIQUE, &d_add->uniques, 0},
2048 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2049 {YANG_CUSTOM, NULL, 0},
2050 };
2051 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2052
2053 } else if (dev_mod == LYS_DEV_REPLACE) {
2054 d_rpl = calloc(1, sizeof *d_rpl);
2055 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2056 d = (struct lysp_deviate *)d_rpl;
2057 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2058 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2059 struct yin_subelement subelems[8] = {
2060 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2061 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2062 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2063 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2064 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2065 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2066 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2067 {YANG_CUSTOM, NULL, 0},
2068 };
2069 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2070
2071 } else {
2072 d_del = calloc(1, sizeof *d_del);
2073 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2074 d = (struct lysp_deviate *)d_del;
2075 struct yin_subelement subelems[5] = {
2076 {YANG_DEFAULT, &d_del->dflts, 0},
2077 {YANG_MUST, &d_del->musts, 0},
2078 {YANG_UNIQUE, &d_del->uniques, 0},
2079 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2080 {YANG_CUSTOM, NULL, 0},
2081 };
2082 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2083 }
2084 LY_CHECK_GOTO(ret, cleanup);
2085
2086 d->mod = dev_mod;
2087 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002088 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002089
2090 return ret;
2091
2092cleanup:
2093 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002094 return ret;
2095}
2096
David Sedlák992fb7c2019-07-24 16:51:01 +02002097/**
David Sedlák8b754462019-07-25 16:22:13 +02002098 * @brief Parse deviation element.
2099 *
2100 * @param[in,out] ctx YIN parser context for logging and to store current state.
2101 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2102 * @param[in,out] data Data to read from, always moved to currently handled character.
2103 * @param[in] deviations Deviations to add to.
2104 *
2105 * @return LY_ERR values.
2106 */
2107static LY_ERR
2108yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2109 struct lysp_deviation **deviations)
2110{
2111 struct lysp_deviation *dev;
2112
2113 /* create new deviation */
2114 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2115
2116 /* parse argument */
2117 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATE));
2118 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2119 struct yin_subelement subelems[4] = {
2120 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2121 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2122 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2123 {YANG_CUSTOM, NULL, 0},
2124 };
2125 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATE, NULL, &dev->exts);
2126}
2127
2128/**
David Sedlákb4e44562019-07-04 15:42:12 +02002129 * @brief Map keyword type to substatement info.
2130 *
2131 * @param[in] kw Keyword type.
2132 *
2133 * @return correct LYEXT_SUBSTMT information.
2134 */
2135static LYEXT_SUBSTMT
2136kw2lyext_substmt(enum yang_keyword kw)
2137{
2138 switch (kw) {
2139 case YANG_ARGUMENT:
2140 return LYEXT_SUBSTMT_ARGUMENT;
2141 case YANG_BASE:
2142 return LYEXT_SUBSTMT_BASE;
2143 case YANG_BELONGS_TO:
2144 return LYEXT_SUBSTMT_BELONGSTO;
2145 case YANG_CONTACT:
2146 return LYEXT_SUBSTMT_CONTACT;
2147 case YANG_DEFAULT:
2148 return LYEXT_SUBSTMT_DEFAULT;
2149 case YANG_DESCRIPTION:
2150 return LYEXT_SUBSTMT_DESCRIPTION;
2151 case YANG_ERROR_APP_TAG:
2152 return LYEXT_SUBSTMT_ERRTAG;
2153 case YANG_ERROR_MESSAGE:
2154 return LYEXT_SUBSTMT_ERRMSG;
2155 case YANG_KEY:
2156 return LYEXT_SUBSTMT_KEY;
2157 case YANG_NAMESPACE:
2158 return LYEXT_SUBSTMT_NAMESPACE;
2159 case YANG_ORGANIZATION:
2160 return LYEXT_SUBSTMT_ORGANIZATION;
2161 case YANG_PATH:
2162 return LYEXT_SUBSTMT_PATH;
2163 case YANG_PREFIX:
2164 return LYEXT_SUBSTMT_PREFIX;
2165 case YANG_PRESENCE:
2166 return LYEXT_SUBSTMT_PRESENCE;
2167 case YANG_REFERENCE:
2168 return LYEXT_SUBSTMT_REFERENCE;
2169 case YANG_REVISION_DATE:
2170 return LYEXT_SUBSTMT_REVISIONDATE;
2171 case YANG_UNITS:
2172 return LYEXT_SUBSTMT_UNITS;
2173 case YANG_VALUE:
2174 return LYEXT_SUBSTMT_VALUE;
2175 case YANG_YANG_VERSION:
2176 return LYEXT_SUBSTMT_VERSION;
2177 case YANG_MODIFIER:
2178 return LYEXT_SUBSTMT_MODIFIER;
2179 case YANG_REQUIRE_INSTANCE:
2180 return LYEXT_SUBSTMT_REQINSTANCE;
2181 case YANG_YIN_ELEMENT:
2182 return LYEXT_SUBSTMT_YINELEM;
2183 case YANG_CONFIG:
2184 return LYEXT_SUBSTMT_CONFIG;
2185 case YANG_MANDATORY:
2186 return LYEXT_SUBSTMT_MANDATORY;
2187 case YANG_ORDERED_BY:
2188 return LYEXT_SUBSTMT_ORDEREDBY;
2189 case YANG_STATUS:
2190 return LYEXT_SUBSTMT_STATUS;
2191 case YANG_FRACTION_DIGITS:
2192 return LYEXT_SUBSTMT_FRACDIGITS;
2193 case YANG_MAX_ELEMENTS:
2194 return LYEXT_SUBSTMT_MAX;
2195 case YANG_MIN_ELEMENTS:
2196 return LYEXT_SUBSTMT_MIN;
2197 case YANG_POSITION:
2198 return LYEXT_SUBSTMT_POSITION;
2199 case YANG_UNIQUE:
2200 return LYEXT_SUBSTMT_UNIQUE;
2201 case YANG_IF_FEATURE:
2202 return LYEXT_SUBSTMT_IFFEATURE;
2203 default:
2204 return LYEXT_SUBSTMT_SELF;
2205 }
2206}
2207
David Sedlákd6e56892019-07-01 15:40:24 +02002208LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002209yin_parse_content(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info, signed char subelem_info_size,
David Sedlák3ffbc522019-07-02 17:49:28 +02002210 const char **data, enum yang_keyword current_element, const char **text_content, struct lysp_ext_instance **exts)
David Sedlákd6e56892019-07-01 15:40:24 +02002211{
2212 LY_ERR ret = LY_SUCCESS;
2213 struct sized_string prefix, name;
David Sedlák8e7bda82019-07-16 17:57:50 +02002214 char *out = NULL;
2215 size_t out_len = 0;
2216 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002217 struct yin_arg_record *attrs = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002218 enum yang_keyword kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002219 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002220 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002221
David Sedlákb0faad82019-07-04 14:28:59 +02002222 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002223
David Sedlákda8ffa32019-07-08 14:17:10 +02002224 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2225 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002226 /* current element has subelements as content */
2227 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002228 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2229 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlákd6e56892019-07-01 15:40:24 +02002230 LY_CHECK_GOTO(ret, cleanup);
2231 if (!name.value) {
2232 /* end of current element reached */
2233 break;
2234 }
David Sedlák1af868e2019-07-17 17:03:14 +02002235 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002236 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc1771b12019-07-10 15:55:46 +02002237 kw = yin_match_keyword(ctx, name.value, name.len, prefix.value, prefix.len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002238
2239 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002240 subelem = get_record(kw, subelem_info_size, subelem_info);
2241 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002242 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2243 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2244 } else {
2245 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
2246 }
David Sedlákd6e56892019-07-01 15:40:24 +02002247 ret = LY_EVALID;
2248 goto cleanup;
2249 }
2250
David Sedlák5f8191e2019-07-08 16:35:52 +02002251 /* TODO check relative order */
2252
David Sedlák4ffcec82019-07-25 15:10:21 +02002253 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002254 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002255 /* subelement uniquenes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002256 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Redefinition of %s element in %s element.", ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +02002257 return LY_EVALID;
2258 }
David Sedlák1af868e2019-07-17 17:03:14 +02002259 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002260 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002261 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002262 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002263 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002264 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002265 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002266 if (ctx->mod_version < 2) {
2267 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002268 ret = LY_EVALID;
2269 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002270 }
2271 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002272 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002273 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002274
David Sedlákd6e56892019-07-01 15:40:24 +02002275 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002276 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002277 case YANG_CUSTOM:
David Sedlák1af868e2019-07-17 17:03:14 +02002278 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name.value, prefix.len),
David Sedlák3ffbc522019-07-02 17:49:28 +02002279 namelen2fulllen(name.len, prefix.len),
David Sedlák1af868e2019-07-17 17:03:14 +02002280 kw2lyext_substmt(current_element),
2281 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002282 break;
2283 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002284 case YANG_RPC:
David Sedlák85d0eca2019-07-24 15:15:21 +02002285 ret = yin_parse_action(ctx, attrs, data, (struct action_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002286 break;
2287 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002288 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002289 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002290 break;
2291 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002292 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002293 break;
2294 case YANG_AUGMENT:
David Sedlák992fb7c2019-07-24 16:51:01 +02002295 ret = yin_parse_augment(ctx, attrs, data, (struct augment_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002296 break;
2297 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002298 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002299 type = (struct lysp_type *)subelem->dest;
2300 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002301 Y_PREF_IDENTIF_ARG, exts);
2302 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002303 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002304 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002305 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2306 } else {
2307 LOGINT(ctx->xml_ctx.ctx);
2308 ret = LY_EINT;
2309 }
David Sedlákd6e56892019-07-01 15:40:24 +02002310 break;
2311 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002312 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002313 break;
2314 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002315 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002316 break;
2317 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002318 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002319 break;
2320 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002321 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002322 break;
2323 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002324 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002325 break;
2326 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002327 case YANG_DESCRIPTION:
2328 case YANG_ORGANIZATION:
2329 case YANG_REFERENCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002330 ret = yin_parse_meta_element(ctx, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002331 break;
2332 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002333 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002334 break;
2335 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002336 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2337 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2338 YIN_ARG_VALUE, Y_STR_ARG, exts);
2339 } else {
2340 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2341 YIN_ARG_VALUE, Y_STR_ARG, exts);
2342 }
David Sedlákd6e56892019-07-01 15:40:24 +02002343 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002344 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002345 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002346 break;
2347 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002348 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002349 break;
David Sedlák43801c92019-08-05 15:58:54 +02002350 case YANG_ENUM:
2351 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2352 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002353 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002354 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002355 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002356 break;
2357 case YANG_ERROR_MESSAGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002358 ret = yin_parse_err_msg_element(ctx, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002359 break;
2360 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002361 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002362 break;
2363 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002364 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002365 break;
2366 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002367 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002368 break;
2369 case YANG_GROUPING:
David Sedláke3ce9ef2019-07-23 16:34:30 +02002370 ret = yin_parse_grouping(ctx, attrs, data, (struct grouping_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002371 break;
2372 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002373 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002374 break;
2375 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002376 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2377 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002378 break;
2379 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002380 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002381 break;
2382 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002383 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002384 break;
2385 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002386 case YANG_OUTPUT:
2387 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002388 break;
2389 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002390 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2391 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002392 break;
2393 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002394 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002395 break;
2396 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002397 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002398 break;
2399 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002400 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002401 type->length = calloc(1, sizeof *type->length);
2402 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002403 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002404 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002405 break;
2406 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002407 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002408 break;
2409 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002410 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002411 break;
2412 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002413 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002414 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002415 break;
2416 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002417 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002418 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002419 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002420 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002421 break;
2422 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002423 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002424 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002425 break;
2426 case YANG_NOTIFICATION:
David Sedlák031b9e72019-07-23 15:19:37 +02002427 ret = yin_parse_notification(ctx, attrs, data, (struct notif_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002428 break;
2429 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002430 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002431 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002432 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002433 type = (struct lysp_type *)subelem->dest;
2434 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlákd1144562019-08-06 12:36:14 +02002435 YIN_ARG_VALUE, Y_STR_ARG, &type->exts);
David Sedlák58979872019-07-12 11:42:43 +02002436 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002437 break;
2438 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002439 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002440 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002441 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002442 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002443 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2444 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002445 break;
2446 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002447 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2448 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002449 break;
2450 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002451 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2452 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002453 break;
2454 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002455 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002456 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002457 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002458 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002459 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002460 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002461 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002462 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002463 break;
2464 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002465 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002466 break;
2467 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002468 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002469 break;
2470 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002471 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002472 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002473 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002474 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002475 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002476 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002477 if (current_element == YANG_DEVIATE) {
2478 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2479 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2480 type = *((struct lysp_type **)subelem->dest);
2481 } else {
2482 type = (struct lysp_type *)subelem->dest;
2483 }
David Sedlák374d2b32019-07-17 15:06:55 +02002484 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002485 if (current_element == YANG_TYPE) {
2486 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002487 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002488 type = nested_type;
2489 }
David Sedlák1af868e2019-07-17 17:03:14 +02002490 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002491 break;
2492 case YANG_TYPEDEF:
David Sedlák04e17b22019-07-19 15:29:48 +02002493 ret = yin_parse_typedef(ctx, attrs, data, (struct typedef_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002494 break;
2495 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002496 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002497 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002498 break;
2499 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002500 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002501 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002502 break;
2503 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002504 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002505 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002506 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002507 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002508 break;
2509 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002510 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002511 break;
2512 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002513 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002514 break;
2515 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002516 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002517 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002518 break;
2519 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002520 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002521 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002522 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002523 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002524 FREE_ARRAY(ctx, attrs, free_arg_rec);
2525 attrs = NULL;
2526 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002527 }
2528 } else {
2529 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002530 /* save text content, if text_content isn't set, it's just ignored */
David Sedlák4ffcec82019-07-25 15:10:21 +02002531 /* no resources are allocated in this branch so no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002532 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002533 if (text_content) {
2534 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002535 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002536 if (!*text_content) {
2537 free(out);
2538 return LY_EMEM;
2539 }
2540 } else {
2541 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002542 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002543 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002544 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002545 }
2546 }
2547 }
David Sedlákd6e56892019-07-01 15:40:24 +02002548 /* load closing element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002549 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
David Sedlákd6e56892019-07-01 15:40:24 +02002550 }
2551 }
David Sedlák8b754462019-07-25 16:22:13 +02002552 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2553 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002554
2555cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002556 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002557 return ret;
2558}
2559
David Sedlák619db942019-07-03 14:47:30 +02002560LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002561yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
David Sedlák619db942019-07-03 14:47:30 +02002562 struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +02002563{
David Sedlák3ffbc522019-07-02 17:49:28 +02002564 const char *temp_rev;
David Sedlák968ac342019-07-11 15:17:59 +02002565 struct yin_subelement subelems[1] = {
2566 {YANG_CUSTOM, NULL, 0}
2567 };
David Sedlák81e04022019-04-05 15:05:46 +02002568
David Sedlák292763b2019-07-09 11:10:53 +02002569 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
David Sedláka304bc62019-07-17 10:17:58 +02002570 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
2571 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
David Sedlákda63c082019-06-04 13:52:23 +02002572
2573 strcpy(rev, temp_rev);
David Sedlákda8ffa32019-07-08 14:17:10 +02002574 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +02002575
David Sedlákda8ffa32019-07-08 14:17:10 +02002576 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002577}
David Sedlák00250342019-06-21 14:19:39 +02002578
David Sedláke1a30302019-07-10 13:49:38 +02002579/**
2580 * @brief Parse config element.
2581 *
2582 * @param[in] ctx Yin parser context for logging and to store current state.
2583 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
2584 * @param[in,out] data Data to read from, always moved to currently handled character.
2585 * @param[in,out] flags Flags to add to.
2586 * @param[in,out] exts Extension instances to add to.
2587 *
2588 * @return LY_ERR values.
2589 */
2590static LY_ERR
2591yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2592 struct lysp_ext_instance **exts)
2593{
2594 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002595 struct yin_subelement subelems[1] = {
2596 {YANG_CUSTOM, NULL, 0}
2597 };
David Sedláke1a30302019-07-10 13:49:38 +02002598
David Sedlák1f90d252019-07-10 17:09:32 +02002599 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
David Sedláke1a30302019-07-10 13:49:38 +02002600 if (strcmp(temp_val, "true") == 0) {
2601 *flags |= LYS_CONFIG_W;
2602 } else if (strcmp(temp_val, "false") == 0) {
2603 *flags |= LYS_CONFIG_R;
2604 } else {
2605 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "config");
2606 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2607 return LY_EVALID;
2608 }
2609 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2610
2611 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
2612}
2613
David Sedlák3ffbc522019-07-02 17:49:28 +02002614LY_ERR
David Sedlák92147b02019-07-09 14:01:01 +02002615yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
2616 struct lysp_ext_instance **exts)
2617{
2618 const char *temp_version = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002619 struct yin_subelement subelems[1] = {
2620 {YANG_CUSTOM, NULL, 0}
2621 };
David Sedlák92147b02019-07-09 14:01:01 +02002622
David Sedlák1f90d252019-07-10 17:09:32 +02002623 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
David Sedlák92147b02019-07-09 14:01:01 +02002624 if (strcmp(temp_version, "1.0") == 0) {
2625 *version = LYS_VERSION_1_0;
2626 } else if (strcmp(temp_version, "1.1") == 0) {
2627 *version = LYS_VERSION_1_1;
2628 } else {
2629 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "yang-version");
2630 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2631 return LY_EVALID;
2632 }
2633 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2634 ctx->mod_version = *version;
2635
2636 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
2637}
2638
2639LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02002640yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
David Sedlák736fd0d2019-02-15 16:06:31 +01002641{
David Sedlák736fd0d2019-02-15 16:06:31 +01002642 struct lysp_import *imp;
David Sedlák00250342019-06-21 14:19:39 +02002643 /* allocate new element in sized array for import */
David Sedlák298ff6d2019-07-26 14:29:03 +02002644 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02002645
David Sedlák968ac342019-07-11 15:17:59 +02002646 struct yin_subelement subelems[5] = {
2647 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2648 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2649 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2650 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2651 {YANG_CUSTOM, NULL, 0}
2652 };
David Sedlák736fd0d2019-02-15 16:06:31 +01002653
David Sedlák92147b02019-07-09 14:01:01 +02002654 /* parse import attributes */
David Sedlák292763b2019-07-09 11:10:53 +02002655 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
David Sedlákda8ffa32019-07-08 14:17:10 +02002656 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
David Sedlák619db942019-07-03 14:47:30 +02002657 /* check prefix validity */
David Sedlák298ff6d2019-07-26 14:29:03 +02002658 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
David Sedlák00250342019-06-21 14:19:39 +02002659
David Sedlák298ff6d2019-07-26 14:29:03 +02002660 return LY_SUCCESS;
David Sedlák736fd0d2019-02-15 16:06:31 +01002661}
2662
David Sedlák11900c82019-06-18 16:29:12 +02002663LY_ERR
David Sedlák1fdb2522019-07-09 16:22:57 +02002664yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2665 struct lysp_ext_instance **exts)
2666{
2667 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002668 struct yin_subelement subelems[1] = {
2669 {YANG_CUSTOM, NULL, 0}
2670 };
David Sedlák1fdb2522019-07-09 16:22:57 +02002671
David Sedlák1f90d252019-07-10 17:09:32 +02002672 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
David Sedlák1fdb2522019-07-09 16:22:57 +02002673 if (strcmp(temp_val, "true") == 0) {
2674 *flags |= LYS_MAND_TRUE;
2675 } else if (strcmp(temp_val, "false") == 0) {
2676 *flags |= LYS_MAND_FALSE;
2677 } else {
2678 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "mandatory");
2679 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2680 return LY_EVALID;
2681 }
2682 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2683
2684 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
2685}
2686
2687LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002688yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
David Sedlák1fdb2522019-07-09 16:22:57 +02002689 struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +02002690{
David Sedlák3ffbc522019-07-02 17:49:28 +02002691 const char *value = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002692 struct yin_subelement subelems[1] = {
2693 {YANG_CUSTOM, NULL, 0}
2694 };
David Sedlák3ffbc522019-07-02 17:49:28 +02002695
David Sedlák292763b2019-07-09 11:10:53 +02002696 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
David Sedlák11900c82019-06-18 16:29:12 +02002697 if (strcmp(value, "current") == 0) {
2698 *flags |= LYS_STATUS_CURR;
2699 } else if (strcmp(value, "deprecated") == 0) {
2700 *flags |= LYS_STATUS_DEPRC;
2701 } else if (strcmp(value, "obsolete") == 0) {
2702 *flags |= LYS_STATUS_OBSLT;
2703 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002704 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "status");
2705 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002706 return LY_EVALID;
2707 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002708 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002709
David Sedlákda8ffa32019-07-08 14:17:10 +02002710 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
David Sedlák11900c82019-06-18 16:29:12 +02002711}
2712
David Sedlák11900c82019-06-18 16:29:12 +02002713LY_ERR
David Sedlák32eee7b2019-07-09 12:38:44 +02002714yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
2715{
2716 struct lysp_when *when;
2717 when = calloc(1, sizeof *when);
2718 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1f90d252019-07-10 17:09:32 +02002719 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
David Sedlák32eee7b2019-07-09 12:38:44 +02002720 *when_p = when;
David Sedlák968ac342019-07-11 15:17:59 +02002721 struct yin_subelement subelems[3] = {
2722 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2723 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2724 {YANG_CUSTOM, NULL, 0}
2725 };
David Sedlák32eee7b2019-07-09 12:38:44 +02002726
2727 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
2728}
2729
2730LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002731yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +02002732 uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák2721d3d2019-06-21 15:37:41 +02002733{
David Sedlák3ffbc522019-07-02 17:49:28 +02002734 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002735 struct yin_subelement subelems[1] = {
2736 {YANG_CUSTOM, NULL, 0}
2737 };
David Sedlák2721d3d2019-06-21 15:37:41 +02002738
David Sedlák1f90d252019-07-10 17:09:32 +02002739 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
David Sedlák2721d3d2019-06-21 15:37:41 +02002740 if (strcmp(temp_val, "true") == 0) {
2741 *flags |= LYS_YINELEM_TRUE;
2742 } else if (strcmp(temp_val, "false") == 0) {
2743 *flags |= LYS_YINELEM_FALSE;
2744 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002745 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
2746 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002747 return LY_EVALID;
2748 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002749 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002750
David Sedlákda8ffa32019-07-08 14:17:10 +02002751 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
David Sedlák2721d3d2019-06-21 15:37:41 +02002752}
2753
2754LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002755yin_parse_extension_instance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, const char *ext_name,
David Sedlák619db942019-07-03 14:47:30 +02002756 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002757{
2758 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002759 char *out;
2760 const char *name, *prefix;
2761 size_t out_len, prefix_len, name_len;
2762 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002763 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02002764 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
2765 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002766
David Sedlákda8ffa32019-07-08 14:17:10 +02002767 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002768
2769 e->yin = 0;
2770 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02002771 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02002772 e->insubstmt = subelem;
2773 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002774 e->yin |= LYS_YIN;
2775
David Sedlákb1a78352019-06-28 16:16:29 +02002776 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02002777 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02002778 if (!iter->prefix) {
2779 new_subelem = calloc(1, sizeof(*new_subelem));
2780 if (!e->child) {
2781 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002782 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02002783 last_subelem->next = new_subelem;
2784 }
2785 last_subelem = new_subelem;
2786
2787 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002788 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
2789 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002790 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002791 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
2792 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002793 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002794 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
2795 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002796 }
2797 }
2798 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02002799
David Sedlákf250ecf2019-07-01 11:02:05 +02002800 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002801 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2802 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002803 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002804 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2805 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02002806 if (!name) {
2807 /* end of extension instance reached */
2808 break;
2809 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002810 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02002811 if (!e->child) {
2812 e->child = new_subelem;
2813 } else {
2814 last_subelem->next = new_subelem;
2815 }
2816 last_subelem = new_subelem;
2817 }
David Sedlák555c7202019-07-04 12:14:12 +02002818 } else {
2819 /* save text content */
2820 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002821 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02002822 if (!e->argument) {
2823 free(out);
2824 return LY_EMEM;
2825 }
2826 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002827 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02002828 LY_CHECK_RET(!e->argument, LY_EMEM);
2829 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002830 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02002831 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02002832 }
David Sedlákb1a78352019-06-28 16:16:29 +02002833 }
2834
2835 return LY_SUCCESS;
2836}
2837
2838LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02002839yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
2840 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02002841{
2842 LY_ERR ret = LY_SUCCESS;
2843 const char *temp_prefix, *temp_name;
2844 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02002845 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02002846 int dynamic;
2847 struct yin_arg_record *subelem_args = NULL;
2848 struct lysp_stmt *last = NULL, *new = NULL;
2849
2850 /* allocate new structure for element */
2851 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02002852 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
2853 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002854
2855 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02002856 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002857 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02002858 /* add new element to linked-list */
2859 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02002860 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02002861 if (!(*element)->child) {
2862 /* save first */
2863 (*element)->child = new;
2864 } else {
2865 last->next = new;
2866 }
2867 last = new;
2868
2869 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002870 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02002871 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002872 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002873 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002874 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
2875 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002876 /* attributes with prefix are ignored */
2877 if (!temp_prefix) {
2878 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002879 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02002880 if (!last->arg) {
2881 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002882 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02002883 ret = LY_EMEM;
2884 goto err;
2885 }
2886 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002887 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2888 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002889 }
2890 }
2891 }
2892
2893 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002894 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002895 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002896 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02002897 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002898 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02002899 LY_CHECK_GOTO(ret, err);
2900 if (!name) {
2901 /* end of element reached */
2902 break;
2903 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002904 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02002905 LY_CHECK_GOTO(ret, err);
2906 last = last->next;
2907 }
2908 } else {
2909 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02002910 if (out_len != 0) {
2911 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002912 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02002913 if (!(*element)->arg) {
2914 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002915 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02002916 ret = LY_EMEM;
2917 goto err;
2918 }
2919 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002920 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2921 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002922 }
David Sedlákb1a78352019-06-28 16:16:29 +02002923 }
2924 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02002925 ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &prefix_len, &temp_name, &temp_name_len);
David Sedlákb1a78352019-06-28 16:16:29 +02002926 LY_CHECK_GOTO(ret, err);
2927 }
2928
David Sedlákda8ffa32019-07-08 14:17:10 +02002929 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02002930 return LY_SUCCESS;
2931
2932err:
David Sedlákda8ffa32019-07-08 14:17:10 +02002933 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002934 return ret;
2935}
2936
2937LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002938yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +02002939 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlák9494eb22019-06-21 16:06:53 +02002940{
David Sedlák968ac342019-07-11 15:17:59 +02002941 struct yin_subelement subelems[2] = {
2942 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2943 {YANG_CUSTOM, NULL, 0}
2944 };
David Sedlák9494eb22019-06-21 16:06:53 +02002945
David Sedlák292763b2019-07-09 11:10:53 +02002946 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
David Sedlák9494eb22019-06-21 16:06:53 +02002947
David Sedlákda8ffa32019-07-08 14:17:10 +02002948 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
David Sedlák9494eb22019-06-21 16:06:53 +02002949}
2950
2951LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002952yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
David Sedlák11900c82019-06-18 16:29:12 +02002953{
David Sedlák11900c82019-06-18 16:29:12 +02002954 struct lysp_ext *ex;
David Sedlákda8ffa32019-07-08 14:17:10 +02002955 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
David Sedlák292763b2019-07-09 11:10:53 +02002956 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
David Sedlák619db942019-07-03 14:47:30 +02002957
David Sedlák3ffbc522019-07-02 17:49:28 +02002958 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
David Sedlák968ac342019-07-11 15:17:59 +02002959 struct yin_subelement subelems[5] = {
2960 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2961 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2962 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2963 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2964 {YANG_CUSTOM, NULL, 0}
2965 };
David Sedlák11900c82019-06-18 16:29:12 +02002966
David Sedlákda8ffa32019-07-08 14:17:10 +02002967 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
David Sedlák11900c82019-06-18 16:29:12 +02002968}
2969
David Sedlák4f03b932019-07-26 13:01:47 +02002970LY_ERR
2971yin_parse_mod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02002972{
David Sedlák4f03b932019-07-26 13:01:47 +02002973 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
2974 struct tree_node_meta node_meta = {NULL, &mod->data};
2975 struct augment_meta aug_meta = {NULL, &mod->augments};
2976 struct grouping_meta grp_meta = {NULL, &mod->groupings};
2977 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
2978 struct notif_meta notif_meta = {NULL, &mod->notifs};
2979 struct action_meta act_meta = {NULL, &mod->rpcs};
2980 struct typedef_meta tpdf_meta = {NULL, &mod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02002981 struct import_meta imp_meta = {mod->mod->prefix, &mod->imports};
David Sedlák4f03b932019-07-26 13:01:47 +02002982 struct yin_subelement subelems[28] = {
2983 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2984 {YANG_ANYXML, &node_meta, 0},
2985 {YANG_AUGMENT, &aug_meta, 0},
2986 {YANG_CHOICE, &node_meta, 0},
2987 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
2988 {YANG_CONTAINER, &node_meta, 0},
2989 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
2990 {YANG_DEVIATION, &mod->deviations, 0},
2991 {YANG_EXTENSION, &mod->extensions, 0},
2992 {YANG_FEATURE, &mod->features, 0},
2993 {YANG_GROUPING, &grp_meta, 0},
2994 {YANG_IDENTITY, &mod->identities, 0},
David Sedlák298ff6d2019-07-26 14:29:03 +02002995 {YANG_IMPORT, &imp_meta, 0},
David Sedlák4f03b932019-07-26 13:01:47 +02002996 {YANG_INCLUDE, &inc_meta, 0},
2997 {YANG_LEAF, &node_meta, 0},
2998 {YANG_LEAF_LIST, &node_meta, 0},
2999 {YANG_LIST, &node_meta, 0},
3000 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3001 {YANG_NOTIFICATION, &notif_meta, 0},
3002 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3003 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3004 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3005 {YANG_REVISION, &mod->revs, 0},
3006 {YANG_RPC, &act_meta, 0},
3007 {YANG_TYPEDEF, &tpdf_meta, 0},
3008 {YANG_USES, &node_meta, 0},
3009 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003010 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003011 };
David Sedlák3b4db242018-10-19 16:11:01 +02003012
David Sedlák4f03b932019-07-26 13:01:47 +02003013 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003014}
3015
3016LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003017yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3018{
3019 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3020 struct tree_node_meta node_meta = {NULL, &submod->data};
3021 struct augment_meta aug_meta = {NULL, &submod->augments};
3022 struct grouping_meta grp_meta = {NULL, &submod->groupings};
3023 struct include_meta inc_meta = {submod->name, &submod->includes};
3024 struct notif_meta notif_meta = {NULL, &submod->notifs};
3025 struct action_meta act_meta = {NULL, &submod->rpcs};
3026 struct typedef_meta tpdf_meta = {NULL, &submod->typedefs};
3027 struct import_meta imp_meta = {submod->prefix, &submod->imports};
3028 struct yin_subelement subelems[27] = {
3029 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3030 {YANG_ANYXML, &node_meta, 0},
3031 {YANG_AUGMENT, &aug_meta, 0},
3032 {YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3033 {YANG_CHOICE, &node_meta, 0},
3034 {YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE},
3035 {YANG_CONTAINER, &node_meta, 0},
3036 {YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE},
3037 {YANG_DEVIATION, &submod->deviations, 0},
3038 {YANG_EXTENSION, &submod->extensions, 0},
3039 {YANG_FEATURE, &submod->features, 0},
3040 {YANG_GROUPING, &grp_meta, 0},
3041 {YANG_IDENTITY, &submod->identities, 0},
3042 {YANG_IMPORT, &imp_meta, 0},
3043 {YANG_INCLUDE, &inc_meta, 0},
3044 {YANG_LEAF, &node_meta, 0},
3045 {YANG_LEAF_LIST, &node_meta, 0},
3046 {YANG_LIST, &node_meta, 0},
3047 {YANG_NOTIFICATION, &notif_meta, 0},
3048 {YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE},
3049 {YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE},
3050 {YANG_REVISION, &submod->revs, 0},
3051 {YANG_RPC, &act_meta, 0},
3052 {YANG_TYPEDEF, &tpdf_meta, 0},
3053 {YANG_USES, &node_meta, 0},
3054 {YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3055 {YANG_CUSTOM, NULL, 0}
3056 };
3057
3058 return yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3059}
3060
3061LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003062yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003063{
3064 enum yang_keyword kw = YANG_NONE;
3065 LY_ERR ret = LY_SUCCESS;
3066 const char *prefix, *name;
3067 size_t prefix_len, name_len;
3068 struct yin_arg_record *attrs = NULL;
3069 struct lysp_submodule *mod_p = NULL;
3070
3071 /* create context */
3072 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003073 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003074 (*yin_ctx)->xml_ctx.ctx = ctx;
3075 (*yin_ctx)->xml_ctx.line = 1;
3076
David Sedlák1b623122019-08-05 15:27:49 +02003077 /* map the typedefs and groupings list from main context to the submodule's context */
3078 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3079 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3080
David Sedlák8985a142019-07-31 16:43:06 +02003081 /* check submodule */
3082 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3083 LY_CHECK_GOTO(ret, cleanup);
3084 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3085 LY_CHECK_GOTO(ret, cleanup);
3086 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3087
3088 if (kw == YANG_MODULE) {
3089 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3090 ret = LY_EINVAL;
3091 goto cleanup;
3092 } else if (kw != YANG_SUBMODULE) {
3093 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
3094 ly_stmt2str(kw));
3095 ret = LY_EVALID;
3096 goto cleanup;
3097 }
3098
3099 mod_p = calloc(1, sizeof *mod_p);
3100 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3101 mod_p->parsing = 1;
3102
3103 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3104 LY_CHECK_GOTO(ret, cleanup);
3105
David Sedlák6d781b62019-08-02 15:22:52 +02003106 name = NULL;
3107 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3108 const char *temp_data = data;
3109 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3110 data = temp_data;
3111 }
3112 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3113 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
3114 15, data, strlen(data) > 15 ? "..." : "");
3115 ret = LY_EVALID;
3116 goto cleanup;
3117 }
3118
David Sedlák8985a142019-07-31 16:43:06 +02003119 mod_p->parsing = 0;
3120 *submod = mod_p;
3121
3122cleanup:
3123 if (ret) {
3124 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003125 yin_parser_ctx_free(*yin_ctx);
3126 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003127 }
3128
3129 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3130 return ret;
3131}
3132
3133LY_ERR
3134yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003135{
David Sedláke4889912018-11-02 09:52:40 +01003136 LY_ERR ret = LY_SUCCESS;
3137 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003138 struct lysp_module *mod_p = NULL;
3139 const char *prefix, *name;
3140 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003141 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003142
David Sedlák8985a142019-07-31 16:43:06 +02003143 /* create context */
3144 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003145 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003146 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3147 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003148
David Sedlák8985a142019-07-31 16:43:06 +02003149 /* check module */
3150 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003151 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003152 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003153 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003154 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003155 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003156 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 +01003157 ret = LY_EINVAL;
3158 goto cleanup;
3159 } else if (kw != YANG_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003160 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +02003161 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003162 ret = LY_EVALID;
3163 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003164 }
3165
David Sedlák3017da42019-02-15 09:48:04 +01003166 /* allocate module */
3167 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003168 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003169 mod_p->mod = mod;
3170 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003171
David Sedlák00250342019-06-21 14:19:39 +02003172 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003173 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003174 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003175
David Sedlák1b623122019-08-05 15:27:49 +02003176 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003177 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3178 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3179 }
3180 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3181 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
3182 15, data, strlen(data) > 15 ? "..." : "");
3183
3184 ret = LY_EVALID;
3185 goto cleanup;
3186 }
3187
David Sedlák3017da42019-02-15 09:48:04 +01003188 mod_p->parsing = 0;
3189 mod->parsed = mod_p;
3190
3191cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003192 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003193 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003194 yin_parser_ctx_free(*yin_ctx);
3195 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003196 }
David Sedlák8985a142019-07-31 16:43:06 +02003197 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003198 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003199}