blob: 67f07c72c0fce1520d9a4e45b08fda9e67a5e247 [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] = {
507 {YANG_CUSTOM, &index, 0}
508 };
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{
1112 struct lysp_node *iter;
1113 struct lysp_node_anydata *any;
1114
1115 /* create structure */
1116 any = calloc(1, sizeof *any);
1117 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1118 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1119 any->parent = node_meta->parent;
1120
1121 /* insert into siblings */
1122 if (!*(node_meta->siblings)) {
1123 *(node_meta->siblings) = (struct lysp_node *)any;
1124 } else {
1125 for (iter = *(node_meta->siblings); iter->next; iter = iter->next);
1126 iter->next = (struct lysp_node *)any;
1127 }
1128
1129 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001130 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 +02001131
1132 struct yin_subelement subelems[9] = {
1133 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1134 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1135 {YANG_IF_FEATURE, &any->iffeatures, 0},
1136 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1137 {YANG_MUST, &any->musts, 0},
1138 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1139 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1140 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1141 {YANG_CUSTOM, NULL, 0},
1142 };
1143 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1144}
1145
1146/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001147 * @brief parse leaf element.
1148 *
1149 * @param[in,out] ctx YIN parser context for logging and to store current state.
1150 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1151 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001152 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák203ca3a2019-07-18 15:26:25 +02001153 *
1154 * @return LY_ERR values.
1155 */
1156static LY_ERR
1157yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1158 struct tree_node_meta *node_meta)
1159{
1160 struct lysp_node *iter;
1161 struct lysp_node_leaf *leaf;
1162
1163 /* create structure */
1164 leaf = calloc(1, sizeof *leaf);
1165 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1166 leaf->nodetype = LYS_LEAF;
1167 leaf->parent = node_meta->parent;
1168
1169 /* insert into siblings */
1170 if (!*(node_meta->siblings)) {
1171 *node_meta->siblings = (struct lysp_node *)leaf;
1172 } else {
1173 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1174 iter->next = (struct lysp_node *)leaf;
1175 }
1176
1177 /* parser argument */
1178 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1179
1180 /* parse content */
1181 struct yin_subelement subelems[12] = {
1182 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1183 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1184 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1185 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1186 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1187 {YANG_MUST, &leaf->musts, 0},
1188 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1189 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1190 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1191 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1192 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1193 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001194 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001195 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1196}
1197
1198/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001199 * @brief Parse leaf-list element.
1200 *
1201 * @param[in,out] ctx YIN parser context for logging and to store current state.
1202 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1203 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001204 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001205 *
1206 * @return LY_ERR values.
1207 */
1208static LY_ERR
1209yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1210 struct tree_node_meta *node_meta)
1211{
1212 struct lysp_node *iter;
1213 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001214
1215 llist = calloc(1, sizeof *llist);
1216 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1217 llist->nodetype = LYS_LEAFLIST;
1218 llist->parent = node_meta->parent;
1219
1220 /* insert into siblings */
1221 if (!*(node_meta->siblings)) {
1222 *node_meta->siblings = (struct lysp_node *)llist;
1223 } else {
1224 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1225 iter->next = (struct lysp_node *)llist;
1226 }
1227
1228 /* parse argument */
1229 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1230
1231 /* parse content */
1232 struct yin_subelement subelems[14] = {
1233 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1234 {YANG_DEFAULT, &llist->dflts, 0},
1235 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1236 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1237 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1238 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1239 {YANG_MUST, &llist->musts, 0},
1240 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1241 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1242 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1243 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1244 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1245 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1246 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001247 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001248 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1249
1250 /* invalid combination of subelements */
1251 if ((llist->min) && (llist->dflts)) {
1252 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
1253 return LY_EVALID;
1254 }
1255 if (llist->max && llist->min > llist->max) {
1256 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1257 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1258 llist->min, llist->max);
1259 return LY_EVALID;
1260 }
1261
1262 return LY_SUCCESS;
1263}
1264
1265/**
David Sedlák04e17b22019-07-19 15:29:48 +02001266 * @brief Parse typedef element.
1267 *
1268 * @param[in,out] ctx YIN parser context for logging and to store current state.
1269 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1270 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001271 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001272 *
1273 * @return LY_ERR values.
1274 */
1275static LY_ERR
1276yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1277 struct typedef_meta *typedef_meta)
1278{
1279 struct lysp_tpdf *tpdf;
1280 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *typedef_meta->typedefs, tpdf, LY_EMEM);
1281
1282 /* parse argument */
1283 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1284
1285 /* parse content */
1286 struct yin_subelement subelems[7] = {
1287 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1288 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1289 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1290 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1291 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1292 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1293 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001294 };
David Sedlák04e17b22019-07-19 15:29:48 +02001295 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1296
1297 /* store data for collision check */
1298 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1299 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1300 }
1301
1302 return LY_SUCCESS;
1303}
1304
1305/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001306 * @brief Parse refine element.
1307 *
1308 * @param[in,out] ctx YIN parser context for logging and to store current state.
1309 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1310 * @param[in,out] data Data to read from, always moved to currently handled character.
1311 * @param[in,out] refines Refines to add to.
1312 *
1313 * @return LY_ERR values.
1314 */
1315static LY_ERR
1316yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1317 struct lysp_refine **refines)
1318{
1319 struct lysp_refine *rf;
1320
1321 /* allocate new refine */
1322 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1323
1324 /* parse attribute */
1325 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1326 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1327
1328 /* parse content */
1329 struct yin_subelement subelems[11] = {
1330 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1331 {YANG_DEFAULT, &rf->dflts, 0},
1332 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1333 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1334 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1335 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1336 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1337 {YANG_MUST, &rf->musts, 0},
1338 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1339 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1340 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001341 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001342 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1343}
1344
1345/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001346 * @brief Parse uses element.
1347 *
1348 * @param[in,out] ctx YIN parser context for logging and to store current state.
1349 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1350 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001351 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001352 *
1353 * @return LY_ERR values.
1354 */
1355static LY_ERR
1356yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1357 struct tree_node_meta *node_meta)
1358{
1359 struct lysp_node *iter;
1360 struct lysp_node_uses *uses;
1361
1362 /* create structure */
1363 uses = calloc(1, sizeof *uses);
1364 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1365 uses->nodetype = LYS_USES;
1366 uses->parent = node_meta->parent;
1367
1368 /* insert into siblings */
1369 if (!*(node_meta->siblings)) {
1370 *node_meta->siblings = (struct lysp_node *)uses;
1371 } else {
1372 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1373 iter->next = (struct lysp_node *)uses;
1374 }
1375
1376 /* parse argument */
1377 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1378
1379 /* parse content */
1380 struct augment_meta augments = {(struct lysp_node *)uses, &uses->augments};
1381 struct yin_subelement subelems[8] = {
1382 {YANG_AUGMENT, &augments, 0},
1383 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1384 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1385 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1386 {YANG_REFINE, &uses->refines, 0},
1387 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1388 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1389 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001390 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001391 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1392 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1393
1394 return LY_SUCCESS;
1395}
1396
1397/**
David Sedlákaa854b02019-07-22 14:17:10 +02001398 * @brief Parse revision 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] revs Parsed revisions to add to.
1404 *
1405 * @return LY_ERR values.
1406 */
1407static LY_ERR
1408yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1409 struct lysp_revision **revs)
1410{
1411 struct lysp_revision *rev;
1412 const char *temp_date = NULL;
1413
1414 /* allocate new reivison */
1415 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1416
1417 /* parse argument */
1418 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1419 /* check value */
1420 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1421 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1422 return LY_EVALID;
1423 }
1424 strcpy(rev->date, temp_date);
1425 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1426
1427 /* parse content */
1428 struct yin_subelement subelems[3] = {
1429 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1430 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1431 {YANG_CUSTOM, NULL, 0},
1432 };
1433 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1434}
1435
David Sedlák5e13dea2019-07-22 16:06:45 +02001436/**
1437 * @brief Parse include element.
1438 *
1439 * @param[in,out] ctx YIN parser context for logging and to store current state.
1440 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1441 * @param[in,out] data Data to read from, always moved to currently handled character.
1442 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1443 *
1444 * @return LY_ERR values.
1445 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001446static LY_ERR
1447yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1448 struct include_meta *inc_meta)
1449{
1450 struct lysp_include *inc;
1451
1452 /* allocate new include */
1453 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1454
1455 /* parse argument */
1456 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1457
1458 /* submodules share the namespace with the module names, so there must not be
1459 * a module of the same name in the context, no need for revision matching */
1460 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
1461 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG,
1462 "Name collision between module and submodule of name \"%s\".", inc->name);
1463 return LY_EVALID;
1464 }
1465
1466 /* parse content */
1467 struct yin_subelement subelems[4] = {
1468 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1469 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1470 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1471 {YANG_CUSTOM, NULL, 0},
1472 };
1473 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1474}
1475
David Sedlákaa854b02019-07-22 14:17:10 +02001476/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001477 * @brief Parse feature element.
1478 *
1479 * @param[in,out] ctx YIN parser context for logging and to store current state.
1480 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1481 * @param[in,out] data Data to read from, always moved to currently handled character.
1482 * @param[in,out] features Features to add to.
1483 *
1484 * @return LY_ERR values.
1485 */
1486static LY_ERR
1487yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1488 struct lysp_feature **features)
1489{
1490 struct lysp_feature *feat;
1491
1492 /* allocate new feature */
1493 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1494
1495 /* parse argument */
1496 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1497
1498 /* parse content */
1499 struct yin_subelement subelems[5] = {
1500 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1501 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1502 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1503 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1504 {YANG_CUSTOM, NULL, 0},
1505 };
1506 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1507}
1508
1509/**
David Sedlák28794f22019-07-22 16:45:00 +02001510 * @brief Parse identity element.
1511 *
1512 * @param[in,out] ctx YIN parser context for logging and to store current state.
1513 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1514 * @param[in,out] data Data to read from, always moved to currently handled character.
1515 * @param[in,out] identities Identities to add to.
1516 *
1517 * @return LY_ERR values.
1518 */
1519static LY_ERR
1520yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1521 struct lysp_ident **identities)
1522{
1523 struct lysp_ident *ident;
1524
1525 /* allocate new identity */
1526 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1527
1528 /* parse argument */
1529 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1530
1531 /* parse content */
1532 struct yin_subelement subelems[6] = {
1533 {YANG_BASE, &ident->bases, 0},
1534 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1535 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1536 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1537 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1538 {YANG_CUSTOM, NULL, 0},
1539 };
1540 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1541}
1542
1543/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001544 * @brief Parse list element.
1545 *
1546 * @param[in,out] ctx YIN parser context for logging and to store current state.
1547 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1548 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001549 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákaf536aa2019-07-23 13:42:23 +02001550 *
1551 * @return LY_ERR values.
1552 */
1553static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001554yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1555 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001556{
1557 struct lysp_node *iter;
1558 struct lysp_node_list *list;
1559
1560 /* create structure */
1561 list = calloc(1, sizeof *list);
1562 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1563 list->nodetype = LYS_LIST;
1564 list->parent = node_meta->parent;
1565
1566 /* insert into siblings */
1567 if (!*(node_meta->siblings)) {
1568 *node_meta->siblings = (struct lysp_node *)list;
1569 } else {
1570 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1571 iter->next = (struct lysp_node *)list;
1572 }
1573
1574 /* parse argument */
1575 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1576
1577 /* parse list content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001578 struct action_meta act_meta = {(struct lysp_node *)list, &list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001579 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
1580 struct typedef_meta typedef_meta = {(struct lysp_node *)list, &list->typedefs};
David Sedlák031b9e72019-07-23 15:19:37 +02001581 struct notif_meta notif_meta = {(struct lysp_node *)list, &list->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001582 struct grouping_meta gr_meta = {(struct lysp_node *)list, &list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001583 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001584 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001585 {YANG_ANYDATA, &new_node_meta, 0},
1586 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001587 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001588 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001589 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001590 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001591 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001592 {YANG_IF_FEATURE, &list->iffeatures, 0},
1593 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1594 {YANG_LEAF, &new_node_meta, 0},
1595 {YANG_LEAF_LIST, &new_node_meta, 0},
1596 {YANG_LIST, &new_node_meta, 0},
1597 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1598 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1599 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001600 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001601 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1602 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1603 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1604 {YANG_TYPEDEF, &typedef_meta, 0},
1605 {YANG_UNIQUE, &list->uniques, 0},
1606 {YANG_USES, &new_node_meta, 0},
1607 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1608 {YANG_CUSTOM, NULL, 0},
1609 };
1610 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1611
1612 /* finalize parent pointers to the reallocated items */
1613 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1614
1615 if (list->max && list->min > list->max) {
1616 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1617 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1618 list->min, list->max);
1619 return LY_EVALID;
1620 }
1621
1622 return LY_SUCCESS;
1623}
1624
1625/**
David Sedlák031b9e72019-07-23 15:19:37 +02001626 * @brief Parse notification element.
1627 *
1628 * @param[in,out] ctx YIN parser context for logging and to store current state.
1629 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1630 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001631 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001632 *
1633 * @return LY_ERR values.
1634 */
1635static LY_ERR
1636yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1637 struct notif_meta *notif_meta)
1638{
1639 struct lysp_notif *notif;
1640
1641 /* allocate new notification */
1642 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notif_meta->notifs, notif, LY_EMEM);
1643 notif->nodetype = LYS_NOTIF;
1644 notif->parent = notif_meta->parent;
1645
1646 /* parse argument */
1647 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1648
1649 /* parse notification content */
1650 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
1651 struct typedef_meta typedef_meta = {(struct lysp_node *)notif, &notif->typedefs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001652 struct grouping_meta gr_meta = {(struct lysp_node *)notif, &notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001653 struct yin_subelement subelems[16] = {
1654 {YANG_ANYDATA, &node_meta, 0},
1655 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001656 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001657 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001658 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001659 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001660 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1661 {YANG_LEAF, &node_meta, 0},
1662 {YANG_LEAF_LIST, &node_meta, 0},
1663 {YANG_LIST, &node_meta, 0},
1664 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1665 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1666 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1667 {YANG_TYPEDEF, &typedef_meta, 0},
1668 {YANG_USES, &node_meta, 0},
1669 {YANG_CUSTOM, NULL, 0},
1670 };
1671 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1672
1673 /* finalize parent pointers to the reallocated items */
1674 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1675
1676 return LY_SUCCESS;
1677}
1678
1679/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001680 * @brief Parse notification element.
1681 *
1682 * @param[in,out] ctx YIN parser context for logging and to store current state.
1683 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1684 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001685 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001686 *
1687 * @return LY_ERR values.
1688 */
1689static LY_ERR
1690yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1691 struct grouping_meta *gr_meta)
1692{
1693 struct lysp_grp *grp;
1694
1695 /* create new grouping */
1696 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *gr_meta->groupings, grp, LY_EMEM);
1697 grp->nodetype = LYS_GROUPING;
1698 grp->parent = gr_meta->parent;
1699
1700 /* parse argument */
1701 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1702
1703 /* parse grouping content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001704 struct action_meta act_meta = {(struct lysp_node *)grp, &grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001705 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
1706 struct typedef_meta typedef_meta = {(struct lysp_node *)grp, &grp->typedefs};
1707 struct grouping_meta sub_grouping = {(struct lysp_node *)grp, &grp->groupings};
1708 struct notif_meta notif_meta = {(struct lysp_node *)grp, &grp->notifs};
1709 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001710 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001711 {YANG_ANYDATA, &node_meta, 0},
1712 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001713 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001714 {YANG_CONTAINER, &node_meta, 0},
1715 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1716 {YANG_GROUPING, &sub_grouping, 0},
1717 {YANG_LEAF, &node_meta, 0},
1718 {YANG_LEAF_LIST, &node_meta, 0},
1719 {YANG_LIST, &node_meta, 0},
1720 {YANG_NOTIFICATION, &notif_meta, 0},
1721 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
1722 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
1723 {YANG_TYPEDEF, &typedef_meta, 0},
1724 {YANG_USES, &node_meta, 0},
1725 {YANG_CUSTOM, NULL, 0},
1726 };
1727 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
1728 /* finalize parent pointers to the reallocated items */
1729 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
1730
1731 return LY_SUCCESS;
1732}
1733
1734/**
David Sedlákf111bcb2019-07-23 17:15:51 +02001735 * @brief Parse list element.
1736 *
1737 * @param[in,out] ctx YIN parser context for logging and to store current state.
1738 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1739 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001740 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákf111bcb2019-07-23 17:15:51 +02001741 *
1742 * @return LY_ERR values.
1743 */
1744static LY_ERR
1745yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1746 struct tree_node_meta *node_meta)
1747{
1748 struct lysp_node *iter;
1749 struct lysp_node_container *cont;
1750
1751 /* create new container */
1752 cont = calloc(1, sizeof *cont);
1753 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1754 cont->nodetype = LYS_CONTAINER;
1755 cont->parent = node_meta->parent;
1756
1757 /* insert into siblings */
1758 if (!*(node_meta->siblings)) {
1759 *node_meta->siblings = (struct lysp_node *)cont;
1760 } else {
1761 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1762 iter->next = (struct lysp_node *)cont;
1763 }
1764
1765 /* parse aegument */
1766 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
1767
1768 /* parse container content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001769 struct action_meta act_meta = {(struct lysp_node *)cont, &cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02001770 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
1771 struct grouping_meta grp_meta = {(struct lysp_node *)cont, &cont->groupings};
1772 struct typedef_meta typedef_meta = {(struct lysp_node *)cont, &cont->typedefs};
1773 struct notif_meta notif_meta = {(struct lysp_node *)cont, &cont->notifs};
1774 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001775 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02001776 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1777 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001778 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001779 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
1780 {YANG_CONTAINER, &new_node_meta, 0},
1781 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
1782 {YANG_GROUPING, &grp_meta, 0},
1783 {YANG_IF_FEATURE, &cont->iffeatures, 0},
1784 {YANG_LEAF, &new_node_meta, 0},
1785 {YANG_LEAF_LIST, &new_node_meta, 0},
1786 {YANG_LIST, &new_node_meta, 0},
1787 {YANG_MUST, &cont->musts, 0},
1788 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
1789 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
1790 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
1791 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
1792 {YANG_TYPEDEF, &typedef_meta, 0},
1793 {YANG_USES, &new_node_meta, 0},
1794 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
1795 {YANG_CUSTOM, NULL, 0},
1796 };
1797 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
1798 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
1799
1800 return LY_SUCCESS;
1801}
1802
1803/**
David Sedlák5379d392019-07-24 10:42:03 +02001804 * @brief Parse case element.
1805 *
1806 * @param[in,out] ctx YIN parser context for logging and to store current state.
1807 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1808 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001809 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák5379d392019-07-24 10:42:03 +02001810 *
1811 * @return LY_ERR values.
1812 */
1813static LY_ERR
1814yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1815 struct tree_node_meta *node_meta)
1816{
1817 struct lysp_node *iter;
1818 struct lysp_node_case *cas;
1819
1820 /* create new case */
1821 cas = calloc(1, sizeof *cas);
1822 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1823 cas->nodetype = LYS_CASE;
1824 cas->parent = node_meta->parent;
1825
1826 /* insert into siblings */
1827 if (!*(node_meta->siblings)) {
1828 *node_meta->siblings = (struct lysp_node *)cas;
1829 } else {
1830 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1831 iter->next = (struct lysp_node *)cas;
1832 }
1833
1834 /* parse argument */
1835 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
1836
1837 /* parse case content */
1838 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
1839 struct yin_subelement subelems[14] = {
1840 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1841 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001842 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02001843 {YANG_CONTAINER, &new_node_meta, 0},
1844 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
1845 {YANG_IF_FEATURE, &cas->iffeatures, 0},
1846 {YANG_LEAF, &new_node_meta, 0},
1847 {YANG_LEAF_LIST, &new_node_meta, 0},
1848 {YANG_LIST, &new_node_meta, 0},
1849 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
1850 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
1851 {YANG_USES, &new_node_meta, 0},
1852 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
1853 {YANG_CUSTOM, NULL, 0},
1854 };
1855 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
1856}
1857
1858/**
David Sedlák05404f62019-07-24 14:11:53 +02001859 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001860 *
1861 * @param[in,out] ctx YIN parser context for logging and to store current state.
1862 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1863 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001864 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001865 *
1866 * @return LY_ERR values.
1867 */
1868LY_ERR
1869yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1870 struct tree_node_meta *node_meta)
1871{
1872 struct lysp_node *iter;
1873 struct lysp_node_choice *choice;
1874
1875 /* create new choice */
1876 choice = calloc(1, sizeof *choice);
1877 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1878 choice->nodetype = LYS_CHOICE;
1879 choice->parent = node_meta->parent;
1880
1881 /* insert into siblings */
1882 if (!*(node_meta->siblings)) {
1883 *node_meta->siblings = (struct lysp_node *)choice;
1884 } else {
1885 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1886 iter->next = (struct lysp_node *)choice;
1887 }
1888
1889 /* parse argument */
1890 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
1891
1892 /* parse choice content */
1893 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
1894 struct yin_subelement subelems[17] = {
1895 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1896 {YANG_ANYXML, &new_node_meta, 0},
1897 {YANG_CASE, &new_node_meta, 0},
1898 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
1899 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
1900 {YANG_CONTAINER, &new_node_meta, 0},
1901 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
1902 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
1903 {YANG_IF_FEATURE, &choice->iffeatures, 0},
1904 {YANG_LEAF, &new_node_meta, 0},
1905 {YANG_LEAF_LIST, &new_node_meta, 0},
1906 {YANG_LIST, &new_node_meta, 0},
1907 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
1908 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
1909 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
1910 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
1911 {YANG_CUSTOM, NULL, 0},
1912 };
1913 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
1914}
1915
1916/**
David Sedlák05404f62019-07-24 14:11:53 +02001917 * @brief Parse input or output element.
1918 *
1919 * @param[in,out] ctx YIN parser context for logging and to store current state.
1920 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1921 * @param[in,out] data Data to read from, always moved to currently handled character.
1922 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
1923 *
1924 * @return LY_ERR values.
1925 */
1926static LY_ERR
1927yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
1928 struct inout_meta *inout_meta)
1929{
1930 /* initiate structure */
1931 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
1932 inout_meta->inout_p->parent = inout_meta->parent;
1933
1934 /* check attributes */
1935 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
1936
1937 /* parser input/output content */
1938 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
1939 struct grouping_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->groupings};
1940 struct typedef_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->typedefs};
1941 struct yin_subelement subelems[12] = {
1942 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
1943 {YANG_ANYXML, &node_meta, 0},
1944 {YANG_CHOICE, &node_meta, 0},
1945 {YANG_CONTAINER, &node_meta, 0},
1946 {YANG_GROUPING, &grp_meta, 0},
1947 {YANG_LEAF, &node_meta, 0},
1948 {YANG_LEAF_LIST, &node_meta, 0},
1949 {YANG_LIST, &node_meta, 0},
1950 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
1951 {YANG_TYPEDEF, &typedef_meta, 0},
1952 {YANG_USES, &node_meta, 0},
1953 {YANG_CUSTOM, NULL, 0},
1954 };
1955 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
1956
1957 /* finalize parent pointers to the reallocated items */
1958 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
1959 NULL, NULL, NULL));
1960
1961 return LY_SUCCESS;
1962}
1963
David Sedlák992fb7c2019-07-24 16:51:01 +02001964/**
1965 * @brief Parse action element.
1966 *
1967 * @param[in,out] ctx YIN parser context for logging and to store current state.
1968 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1969 * @param[in,out] data Data to read from, always moved to currently handled character.
1970 * @param[in] act_meta Meta information about parent node and actions to add to.
1971 *
1972 * @return LY_ERR values.
1973 */
David Sedlák85d0eca2019-07-24 15:15:21 +02001974static LY_ERR
1975yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1976 struct action_meta *act_meta)
1977{
1978 struct lysp_action *act;
1979
1980 /* create new action */
1981 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *act_meta->actions, act, LY_EMEM);
1982 act->nodetype = LYS_ACTION;
1983 act->parent = act_meta->parent;
1984
1985 /* parse argument */
1986 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
1987
1988 /* parse content */
1989 struct grouping_meta grp_meta = {(struct lysp_node *)act, &act->groupings};
1990 struct typedef_meta typedef_meta = {(struct lysp_node *)act, &act->typedefs};
1991 struct inout_meta input = {(struct lysp_node *)act, &act->input};
1992 struct inout_meta output = {(struct lysp_node *)act, &act->output};
1993 struct yin_subelement subelems[9] = {
1994 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
1995 {YANG_GROUPING, &grp_meta, 0},
1996 {YANG_IF_FEATURE, &act->iffeatures, 0},
1997 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
1998 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
1999 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
2000 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
2001 {YANG_TYPEDEF, &typedef_meta, 0},
2002 {YANG_CUSTOM, NULL, 0},
2003 };
2004 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2005 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2006
2007 return LY_SUCCESS;
2008}
2009
David Sedlák05404f62019-07-24 14:11:53 +02002010/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002011 * @brief Parse augment element.
2012 *
2013 * @param[in,out] ctx YIN parser context for logging and to store current state.
2014 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2015 * @param[in,out] data Data to read from, always moved to currently handled character.
2016 * @param[in] aug_meta Meta information about parent node and augments to add to.
2017 *
2018 * @return LY_ERR values.
2019 */
2020static LY_ERR
2021yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2022 struct augment_meta *aug_meta)
2023{
2024 struct lysp_augment *aug;
2025
2026 /* create new augment */
2027 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *aug_meta->augments, aug, LY_EMEM);
2028 aug->nodetype = LYS_AUGMENT;
2029 aug->parent = aug_meta->parent;
2030
2031 /* parse argument */
2032 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2033 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2034
2035 /* parser augment content */
2036 struct action_meta act_meta = {(struct lysp_node *)aug, &aug->actions};
2037 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
2038 struct notif_meta notif_meta = {(struct lysp_node *)aug, &aug->notifs};
2039 struct yin_subelement subelems[17] = {
2040 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
2041 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2042 {YANG_ANYXML, &node_meta, 0},
2043 {YANG_CASE, &node_meta, 0},
2044 {YANG_CHOICE, &node_meta, 0},
2045 {YANG_CONTAINER, &node_meta, 0},
2046 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
2047 {YANG_IF_FEATURE, &aug->iffeatures, 0},
2048 {YANG_LEAF, &node_meta, 0},
2049 {YANG_LEAF_LIST, &node_meta, 0},
2050 {YANG_LIST, &node_meta, 0},
2051 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2052 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
2053 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
2054 {YANG_USES, &node_meta, 0},
2055 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
2056 {YANG_CUSTOM, NULL, 0},
2057 };
2058 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
2059
2060 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2061
2062 return LY_SUCCESS;
2063}
2064
David Sedlák8b754462019-07-25 16:22:13 +02002065/**
2066 * @brief Parse deviate element.
2067 *
2068 * @param[in,out] ctx YIN parser context for logging and to store current state.
2069 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2070 * @param[in,out] data Data to read from, always moved to currently handled character.
2071 * @param[in] deviates Deviates to add to.
2072 *
2073 * @return LY_ERR values.
2074 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002075static LY_ERR
2076yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2077 struct lysp_deviate **deviates)
2078{
2079 LY_ERR ret = LY_SUCCESS;
2080 uint8_t dev_mod;
2081 const char *temp_val;
2082 struct lysp_deviate *iter, *d;
2083 struct lysp_deviate_add *d_add = NULL;
2084 struct lysp_deviate_rpl *d_rpl = NULL;
2085 struct lysp_deviate_del *d_del = NULL;
2086
2087 /* parse argument */
2088 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2089
2090 if (strcmp(temp_val, "not-supported") == 0) {
2091 dev_mod = LYS_DEV_NOT_SUPPORTED;
2092 } else if (strcmp(temp_val, "add") == 0) {
2093 dev_mod = LYS_DEV_ADD;
2094 } else if (strcmp(temp_val, "replace") == 0) {
2095 dev_mod = LYS_DEV_REPLACE;
2096 } else if (strcmp(temp_val, "delete") == 0) {
2097 dev_mod = LYS_DEV_DELETE;
2098 } else {
2099 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "deviate");
2100 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2101 return LY_EVALID;
2102 }
2103 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2104
2105 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2106 d = calloc(1, sizeof *d);
2107 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2108 struct yin_subelement subelems[1] = {
2109 {YANG_CUSTOM, NULL, 0}
2110 };
2111 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2112
2113 } else if (dev_mod == LYS_DEV_ADD) {
2114 d_add = calloc(1, sizeof *d_add);
2115 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2116 d = (struct lysp_deviate *)d_add;
2117 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2118 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2119 struct yin_subelement subelems[9] = {
2120 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2121 {YANG_DEFAULT, &d_add->dflts, 0},
2122 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2123 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2124 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2125 {YANG_MUST, &d_add->musts, 0},
2126 {YANG_UNIQUE, &d_add->uniques, 0},
2127 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2128 {YANG_CUSTOM, NULL, 0},
2129 };
2130 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2131
2132 } else if (dev_mod == LYS_DEV_REPLACE) {
2133 d_rpl = calloc(1, sizeof *d_rpl);
2134 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2135 d = (struct lysp_deviate *)d_rpl;
2136 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2137 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2138 struct yin_subelement subelems[8] = {
2139 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2140 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2141 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2142 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2143 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2144 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2145 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2146 {YANG_CUSTOM, NULL, 0},
2147 };
2148 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2149
2150 } else {
2151 d_del = calloc(1, sizeof *d_del);
2152 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2153 d = (struct lysp_deviate *)d_del;
2154 struct yin_subelement subelems[5] = {
2155 {YANG_DEFAULT, &d_del->dflts, 0},
2156 {YANG_MUST, &d_del->musts, 0},
2157 {YANG_UNIQUE, &d_del->uniques, 0},
2158 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2159 {YANG_CUSTOM, NULL, 0},
2160 };
2161 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2162 }
2163 LY_CHECK_GOTO(ret, cleanup);
2164
2165 d->mod = dev_mod;
2166 /* insert into siblings */
2167 if (!*deviates) {
2168 *deviates = d;
2169 } else {
2170 for (iter = *deviates; iter->next; iter = iter->next);
2171 iter->next = d;
2172 }
2173
2174 return ret;
2175
2176cleanup:
2177 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002178 return ret;
2179}
2180
David Sedlák992fb7c2019-07-24 16:51:01 +02002181/**
David Sedlák8b754462019-07-25 16:22:13 +02002182 * @brief Parse deviation element.
2183 *
2184 * @param[in,out] ctx YIN parser context for logging and to store current state.
2185 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2186 * @param[in,out] data Data to read from, always moved to currently handled character.
2187 * @param[in] deviations Deviations to add to.
2188 *
2189 * @return LY_ERR values.
2190 */
2191static LY_ERR
2192yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2193 struct lysp_deviation **deviations)
2194{
2195 struct lysp_deviation *dev;
2196
2197 /* create new deviation */
2198 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2199
2200 /* parse argument */
2201 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATE));
2202 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2203 struct yin_subelement subelems[4] = {
2204 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2205 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2206 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2207 {YANG_CUSTOM, NULL, 0},
2208 };
2209 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATE, NULL, &dev->exts);
2210}
2211
2212/**
David Sedlákb4e44562019-07-04 15:42:12 +02002213 * @brief Map keyword type to substatement info.
2214 *
2215 * @param[in] kw Keyword type.
2216 *
2217 * @return correct LYEXT_SUBSTMT information.
2218 */
2219static LYEXT_SUBSTMT
2220kw2lyext_substmt(enum yang_keyword kw)
2221{
2222 switch (kw) {
2223 case YANG_ARGUMENT:
2224 return LYEXT_SUBSTMT_ARGUMENT;
2225 case YANG_BASE:
2226 return LYEXT_SUBSTMT_BASE;
2227 case YANG_BELONGS_TO:
2228 return LYEXT_SUBSTMT_BELONGSTO;
2229 case YANG_CONTACT:
2230 return LYEXT_SUBSTMT_CONTACT;
2231 case YANG_DEFAULT:
2232 return LYEXT_SUBSTMT_DEFAULT;
2233 case YANG_DESCRIPTION:
2234 return LYEXT_SUBSTMT_DESCRIPTION;
2235 case YANG_ERROR_APP_TAG:
2236 return LYEXT_SUBSTMT_ERRTAG;
2237 case YANG_ERROR_MESSAGE:
2238 return LYEXT_SUBSTMT_ERRMSG;
2239 case YANG_KEY:
2240 return LYEXT_SUBSTMT_KEY;
2241 case YANG_NAMESPACE:
2242 return LYEXT_SUBSTMT_NAMESPACE;
2243 case YANG_ORGANIZATION:
2244 return LYEXT_SUBSTMT_ORGANIZATION;
2245 case YANG_PATH:
2246 return LYEXT_SUBSTMT_PATH;
2247 case YANG_PREFIX:
2248 return LYEXT_SUBSTMT_PREFIX;
2249 case YANG_PRESENCE:
2250 return LYEXT_SUBSTMT_PRESENCE;
2251 case YANG_REFERENCE:
2252 return LYEXT_SUBSTMT_REFERENCE;
2253 case YANG_REVISION_DATE:
2254 return LYEXT_SUBSTMT_REVISIONDATE;
2255 case YANG_UNITS:
2256 return LYEXT_SUBSTMT_UNITS;
2257 case YANG_VALUE:
2258 return LYEXT_SUBSTMT_VALUE;
2259 case YANG_YANG_VERSION:
2260 return LYEXT_SUBSTMT_VERSION;
2261 case YANG_MODIFIER:
2262 return LYEXT_SUBSTMT_MODIFIER;
2263 case YANG_REQUIRE_INSTANCE:
2264 return LYEXT_SUBSTMT_REQINSTANCE;
2265 case YANG_YIN_ELEMENT:
2266 return LYEXT_SUBSTMT_YINELEM;
2267 case YANG_CONFIG:
2268 return LYEXT_SUBSTMT_CONFIG;
2269 case YANG_MANDATORY:
2270 return LYEXT_SUBSTMT_MANDATORY;
2271 case YANG_ORDERED_BY:
2272 return LYEXT_SUBSTMT_ORDEREDBY;
2273 case YANG_STATUS:
2274 return LYEXT_SUBSTMT_STATUS;
2275 case YANG_FRACTION_DIGITS:
2276 return LYEXT_SUBSTMT_FRACDIGITS;
2277 case YANG_MAX_ELEMENTS:
2278 return LYEXT_SUBSTMT_MAX;
2279 case YANG_MIN_ELEMENTS:
2280 return LYEXT_SUBSTMT_MIN;
2281 case YANG_POSITION:
2282 return LYEXT_SUBSTMT_POSITION;
2283 case YANG_UNIQUE:
2284 return LYEXT_SUBSTMT_UNIQUE;
2285 case YANG_IF_FEATURE:
2286 return LYEXT_SUBSTMT_IFFEATURE;
2287 default:
2288 return LYEXT_SUBSTMT_SELF;
2289 }
2290}
2291
David Sedlákd6e56892019-07-01 15:40:24 +02002292LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002293yin_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 +02002294 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 +02002295{
2296 LY_ERR ret = LY_SUCCESS;
2297 struct sized_string prefix, name;
David Sedlák8e7bda82019-07-16 17:57:50 +02002298 char *out = NULL;
2299 size_t out_len = 0;
2300 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002301 struct yin_arg_record *attrs = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002302 enum yang_keyword kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002303 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002304 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002305
David Sedlákb0faad82019-07-04 14:28:59 +02002306 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002307
David Sedlákda8ffa32019-07-08 14:17:10 +02002308 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2309 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002310 /* current element has subelements as content */
2311 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002312 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2313 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlákd6e56892019-07-01 15:40:24 +02002314 LY_CHECK_GOTO(ret, cleanup);
2315 if (!name.value) {
2316 /* end of current element reached */
2317 break;
2318 }
David Sedlák1af868e2019-07-17 17:03:14 +02002319 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002320 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc1771b12019-07-10 15:55:46 +02002321 kw = yin_match_keyword(ctx, name.value, name.len, prefix.value, prefix.len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002322
2323 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002324 subelem = get_record(kw, subelem_info_size, subelem_info);
2325 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002326 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2327 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2328 } else {
2329 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
2330 }
David Sedlákd6e56892019-07-01 15:40:24 +02002331 ret = LY_EVALID;
2332 goto cleanup;
2333 }
2334
David Sedlák5f8191e2019-07-08 16:35:52 +02002335 /* TODO check relative order */
2336
David Sedlák4ffcec82019-07-25 15:10:21 +02002337 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002338 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002339 /* subelement uniquenes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002340 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 +02002341 return LY_EVALID;
2342 }
David Sedlák1af868e2019-07-17 17:03:14 +02002343 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002344 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002345 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002346 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002347 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002348 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002349 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002350 if (ctx->mod_version < 2) {
2351 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002352 ret = LY_EVALID;
2353 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002354 }
2355 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002356 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002357 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002358
David Sedlákd6e56892019-07-01 15:40:24 +02002359 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002360 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002361 case YANG_CUSTOM:
David Sedlák1af868e2019-07-17 17:03:14 +02002362 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name.value, prefix.len),
David Sedlák3ffbc522019-07-02 17:49:28 +02002363 namelen2fulllen(name.len, prefix.len),
David Sedlák1af868e2019-07-17 17:03:14 +02002364 kw2lyext_substmt(current_element),
2365 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002366 break;
2367 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002368 case YANG_RPC:
David Sedlák85d0eca2019-07-24 15:15:21 +02002369 ret = yin_parse_action(ctx, attrs, data, (struct action_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002370 break;
2371 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002372 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002373 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002374 break;
2375 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002376 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002377 break;
2378 case YANG_AUGMENT:
David Sedlák992fb7c2019-07-24 16:51:01 +02002379 ret = yin_parse_augment(ctx, attrs, data, (struct augment_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002380 break;
2381 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002382 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002383 type = (struct lysp_type *)subelem->dest;
2384 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002385 Y_PREF_IDENTIF_ARG, exts);
2386 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002387 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002388 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002389 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2390 } else {
2391 LOGINT(ctx->xml_ctx.ctx);
2392 ret = LY_EINT;
2393 }
David Sedlákd6e56892019-07-01 15:40:24 +02002394 break;
2395 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002396 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002397 break;
2398 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002399 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002400 break;
2401 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002402 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002403 break;
2404 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002405 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002406 break;
2407 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002408 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002409 break;
2410 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002411 case YANG_DESCRIPTION:
2412 case YANG_ORGANIZATION:
2413 case YANG_REFERENCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002414 ret = yin_parse_meta_element(ctx, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002415 break;
2416 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002417 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002418 break;
2419 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002420 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2421 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2422 YIN_ARG_VALUE, Y_STR_ARG, exts);
2423 } else {
2424 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2425 YIN_ARG_VALUE, Y_STR_ARG, exts);
2426 }
David Sedlákd6e56892019-07-01 15:40:24 +02002427 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002428 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002429 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002430 break;
2431 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002432 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002433 break;
David Sedlák43801c92019-08-05 15:58:54 +02002434 case YANG_ENUM:
2435 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2436 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002437 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002438 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002439 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002440 break;
2441 case YANG_ERROR_MESSAGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002442 ret = yin_parse_err_msg_element(ctx, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002443 break;
2444 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002445 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002446 break;
2447 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002448 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002449 break;
2450 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002451 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002452 break;
2453 case YANG_GROUPING:
David Sedláke3ce9ef2019-07-23 16:34:30 +02002454 ret = yin_parse_grouping(ctx, attrs, data, (struct grouping_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002455 break;
2456 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002457 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002458 break;
2459 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002460 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2461 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002462 break;
2463 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002464 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002465 break;
2466 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002467 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002468 break;
2469 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002470 case YANG_OUTPUT:
2471 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002472 break;
2473 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002474 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2475 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002476 break;
2477 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002478 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002479 break;
2480 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002481 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002482 break;
2483 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002484 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002485 type->length = calloc(1, sizeof *type->length);
2486 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002487 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002488 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002489 break;
2490 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002491 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002492 break;
2493 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002494 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002495 break;
2496 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002497 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002498 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002499 break;
2500 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002501 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002502 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002503 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002504 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002505 break;
2506 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002507 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002508 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002509 break;
2510 case YANG_NOTIFICATION:
David Sedlák031b9e72019-07-23 15:19:37 +02002511 ret = yin_parse_notification(ctx, attrs, data, (struct notif_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002512 break;
2513 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002514 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002515 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002516 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002517 type = (struct lysp_type *)subelem->dest;
2518 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlák58979872019-07-12 11:42:43 +02002519 YIN_ARG_VALUE, Y_STR_ARG, exts);
2520 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002521 break;
2522 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002523 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002524 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002525 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002526 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002527 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2528 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002529 break;
2530 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002531 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2532 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002533 break;
2534 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002535 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2536 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002537 break;
2538 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002539 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002540 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002541 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002542 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002543 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002544 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002545 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002546 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002547 break;
2548 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002549 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002550 break;
2551 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002552 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002553 break;
2554 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002555 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002556 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002557 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002558 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002559 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002560 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002561 if (current_element == YANG_DEVIATE) {
2562 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2563 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2564 type = *((struct lysp_type **)subelem->dest);
2565 } else {
2566 type = (struct lysp_type *)subelem->dest;
2567 }
David Sedlák374d2b32019-07-17 15:06:55 +02002568 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002569 if (current_element == YANG_TYPE) {
2570 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002571 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002572 type = nested_type;
2573 }
David Sedlák1af868e2019-07-17 17:03:14 +02002574 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002575 break;
2576 case YANG_TYPEDEF:
David Sedlák04e17b22019-07-19 15:29:48 +02002577 ret = yin_parse_typedef(ctx, attrs, data, (struct typedef_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002578 break;
2579 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002580 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002581 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002582 break;
2583 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002584 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002585 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002586 break;
2587 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002588 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002589 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002590 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002591 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002592 break;
2593 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002594 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002595 break;
2596 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002597 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002598 break;
2599 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002600 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002601 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002602 break;
2603 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002604 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002605 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002606 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002607 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002608 FREE_ARRAY(ctx, attrs, free_arg_rec);
2609 attrs = NULL;
2610 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002611 }
2612 } else {
2613 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002614 /* save text content, if text_content isn't set, it's just ignored */
David Sedlák4ffcec82019-07-25 15:10:21 +02002615 /* no resources are allocated in this branch so no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002616 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002617 if (text_content) {
2618 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002619 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002620 if (!*text_content) {
2621 free(out);
2622 return LY_EMEM;
2623 }
2624 } else {
2625 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002626 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002627 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002628 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002629 }
2630 }
2631 }
David Sedlákd6e56892019-07-01 15:40:24 +02002632 /* load closing element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002633 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 +02002634 }
2635 }
David Sedlák8b754462019-07-25 16:22:13 +02002636 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2637 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002638
2639cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002640 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002641 return ret;
2642}
2643
David Sedlák619db942019-07-03 14:47:30 +02002644LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002645yin_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 +02002646 struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +02002647{
David Sedlák3ffbc522019-07-02 17:49:28 +02002648 const char *temp_rev;
David Sedlák968ac342019-07-11 15:17:59 +02002649 struct yin_subelement subelems[1] = {
2650 {YANG_CUSTOM, NULL, 0}
2651 };
David Sedlák81e04022019-04-05 15:05:46 +02002652
David Sedlák292763b2019-07-09 11:10:53 +02002653 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 +02002654 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
2655 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
David Sedlákda63c082019-06-04 13:52:23 +02002656
2657 strcpy(rev, temp_rev);
David Sedlákda8ffa32019-07-08 14:17:10 +02002658 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +02002659
David Sedlákda8ffa32019-07-08 14:17:10 +02002660 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002661}
David Sedlák00250342019-06-21 14:19:39 +02002662
David Sedláke1a30302019-07-10 13:49:38 +02002663/**
2664 * @brief Parse config element.
2665 *
2666 * @param[in] ctx Yin parser context for logging and to store current state.
2667 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
2668 * @param[in,out] data Data to read from, always moved to currently handled character.
2669 * @param[in,out] flags Flags to add to.
2670 * @param[in,out] exts Extension instances to add to.
2671 *
2672 * @return LY_ERR values.
2673 */
2674static LY_ERR
2675yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2676 struct lysp_ext_instance **exts)
2677{
2678 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002679 struct yin_subelement subelems[1] = {
2680 {YANG_CUSTOM, NULL, 0}
2681 };
David Sedláke1a30302019-07-10 13:49:38 +02002682
David Sedlák1f90d252019-07-10 17:09:32 +02002683 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 +02002684 if (strcmp(temp_val, "true") == 0) {
2685 *flags |= LYS_CONFIG_W;
2686 } else if (strcmp(temp_val, "false") == 0) {
2687 *flags |= LYS_CONFIG_R;
2688 } else {
2689 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "config");
2690 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2691 return LY_EVALID;
2692 }
2693 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2694
2695 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
2696}
2697
David Sedlák3ffbc522019-07-02 17:49:28 +02002698LY_ERR
David Sedlák92147b02019-07-09 14:01:01 +02002699yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
2700 struct lysp_ext_instance **exts)
2701{
2702 const char *temp_version = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002703 struct yin_subelement subelems[1] = {
2704 {YANG_CUSTOM, NULL, 0}
2705 };
David Sedlák92147b02019-07-09 14:01:01 +02002706
David Sedlák1f90d252019-07-10 17:09:32 +02002707 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 +02002708 if (strcmp(temp_version, "1.0") == 0) {
2709 *version = LYS_VERSION_1_0;
2710 } else if (strcmp(temp_version, "1.1") == 0) {
2711 *version = LYS_VERSION_1_1;
2712 } else {
2713 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "yang-version");
2714 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2715 return LY_EVALID;
2716 }
2717 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2718 ctx->mod_version = *version;
2719
2720 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
2721}
2722
2723LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02002724yin_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 +01002725{
David Sedlák736fd0d2019-02-15 16:06:31 +01002726 struct lysp_import *imp;
David Sedlák00250342019-06-21 14:19:39 +02002727 /* allocate new element in sized array for import */
David Sedlák298ff6d2019-07-26 14:29:03 +02002728 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02002729
David Sedlák968ac342019-07-11 15:17:59 +02002730 struct yin_subelement subelems[5] = {
2731 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2732 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2733 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2734 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2735 {YANG_CUSTOM, NULL, 0}
2736 };
David Sedlák736fd0d2019-02-15 16:06:31 +01002737
David Sedlák92147b02019-07-09 14:01:01 +02002738 /* parse import attributes */
David Sedlák292763b2019-07-09 11:10:53 +02002739 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 +02002740 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
David Sedlák619db942019-07-03 14:47:30 +02002741 /* check prefix validity */
David Sedlák298ff6d2019-07-26 14:29:03 +02002742 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 +02002743
David Sedlák298ff6d2019-07-26 14:29:03 +02002744 return LY_SUCCESS;
David Sedlák736fd0d2019-02-15 16:06:31 +01002745}
2746
David Sedlák11900c82019-06-18 16:29:12 +02002747LY_ERR
David Sedlák1fdb2522019-07-09 16:22:57 +02002748yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2749 struct lysp_ext_instance **exts)
2750{
2751 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002752 struct yin_subelement subelems[1] = {
2753 {YANG_CUSTOM, NULL, 0}
2754 };
David Sedlák1fdb2522019-07-09 16:22:57 +02002755
David Sedlák1f90d252019-07-10 17:09:32 +02002756 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 +02002757 if (strcmp(temp_val, "true") == 0) {
2758 *flags |= LYS_MAND_TRUE;
2759 } else if (strcmp(temp_val, "false") == 0) {
2760 *flags |= LYS_MAND_FALSE;
2761 } else {
2762 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "mandatory");
2763 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2764 return LY_EVALID;
2765 }
2766 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2767
2768 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
2769}
2770
2771LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002772yin_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 +02002773 struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +02002774{
David Sedlák3ffbc522019-07-02 17:49:28 +02002775 const char *value = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002776 struct yin_subelement subelems[1] = {
2777 {YANG_CUSTOM, NULL, 0}
2778 };
David Sedlák3ffbc522019-07-02 17:49:28 +02002779
David Sedlák292763b2019-07-09 11:10:53 +02002780 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 +02002781 if (strcmp(value, "current") == 0) {
2782 *flags |= LYS_STATUS_CURR;
2783 } else if (strcmp(value, "deprecated") == 0) {
2784 *flags |= LYS_STATUS_DEPRC;
2785 } else if (strcmp(value, "obsolete") == 0) {
2786 *flags |= LYS_STATUS_OBSLT;
2787 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002788 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "status");
2789 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002790 return LY_EVALID;
2791 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002792 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002793
David Sedlákda8ffa32019-07-08 14:17:10 +02002794 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
David Sedlák11900c82019-06-18 16:29:12 +02002795}
2796
David Sedlák11900c82019-06-18 16:29:12 +02002797LY_ERR
David Sedlák32eee7b2019-07-09 12:38:44 +02002798yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
2799{
2800 struct lysp_when *when;
2801 when = calloc(1, sizeof *when);
2802 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1f90d252019-07-10 17:09:32 +02002803 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
David Sedlák32eee7b2019-07-09 12:38:44 +02002804 *when_p = when;
David Sedlák968ac342019-07-11 15:17:59 +02002805 struct yin_subelement subelems[3] = {
2806 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2807 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2808 {YANG_CUSTOM, NULL, 0}
2809 };
David Sedlák32eee7b2019-07-09 12:38:44 +02002810
2811 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
2812}
2813
2814LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002815yin_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 +02002816 uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák2721d3d2019-06-21 15:37:41 +02002817{
David Sedlák3ffbc522019-07-02 17:49:28 +02002818 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002819 struct yin_subelement subelems[1] = {
2820 {YANG_CUSTOM, NULL, 0}
2821 };
David Sedlák2721d3d2019-06-21 15:37:41 +02002822
David Sedlák1f90d252019-07-10 17:09:32 +02002823 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 +02002824 if (strcmp(temp_val, "true") == 0) {
2825 *flags |= LYS_YINELEM_TRUE;
2826 } else if (strcmp(temp_val, "false") == 0) {
2827 *flags |= LYS_YINELEM_FALSE;
2828 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002829 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
2830 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002831 return LY_EVALID;
2832 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002833 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002834
David Sedlákda8ffa32019-07-08 14:17:10 +02002835 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
David Sedlák2721d3d2019-06-21 15:37:41 +02002836}
2837
2838LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002839yin_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 +02002840 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002841{
2842 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002843 char *out;
2844 const char *name, *prefix;
2845 size_t out_len, prefix_len, name_len;
2846 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002847 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02002848 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
2849 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002850
David Sedlákda8ffa32019-07-08 14:17:10 +02002851 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002852
2853 e->yin = 0;
2854 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02002855 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02002856 e->insubstmt = subelem;
2857 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002858 e->yin |= LYS_YIN;
2859
David Sedlákb1a78352019-06-28 16:16:29 +02002860 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02002861 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02002862 if (!iter->prefix) {
2863 new_subelem = calloc(1, sizeof(*new_subelem));
2864 if (!e->child) {
2865 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002866 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02002867 last_subelem->next = new_subelem;
2868 }
2869 last_subelem = new_subelem;
2870
2871 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002872 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
2873 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002874 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002875 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
2876 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002877 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002878 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
2879 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002880 }
2881 }
2882 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02002883
David Sedlákf250ecf2019-07-01 11:02:05 +02002884 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002885 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2886 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002887 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002888 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2889 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02002890 if (!name) {
2891 /* end of extension instance reached */
2892 break;
2893 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002894 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02002895 if (!e->child) {
2896 e->child = new_subelem;
2897 } else {
2898 last_subelem->next = new_subelem;
2899 }
2900 last_subelem = new_subelem;
2901 }
David Sedlák555c7202019-07-04 12:14:12 +02002902 } else {
2903 /* save text content */
2904 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002905 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02002906 if (!e->argument) {
2907 free(out);
2908 return LY_EMEM;
2909 }
2910 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002911 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02002912 LY_CHECK_RET(!e->argument, LY_EMEM);
2913 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002914 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02002915 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02002916 }
David Sedlákb1a78352019-06-28 16:16:29 +02002917 }
2918
2919 return LY_SUCCESS;
2920}
2921
2922LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02002923yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
2924 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02002925{
2926 LY_ERR ret = LY_SUCCESS;
2927 const char *temp_prefix, *temp_name;
2928 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02002929 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02002930 int dynamic;
2931 struct yin_arg_record *subelem_args = NULL;
2932 struct lysp_stmt *last = NULL, *new = NULL;
2933
2934 /* allocate new structure for element */
2935 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02002936 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
2937 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002938
2939 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02002940 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002941 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02002942 /* add new element to linked-list */
2943 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02002944 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02002945 if (!(*element)->child) {
2946 /* save first */
2947 (*element)->child = new;
2948 } else {
2949 last->next = new;
2950 }
2951 last = new;
2952
2953 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002954 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 +02002955 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002956 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002957 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002958 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
2959 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002960 /* attributes with prefix are ignored */
2961 if (!temp_prefix) {
2962 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002963 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02002964 if (!last->arg) {
2965 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002966 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02002967 ret = LY_EMEM;
2968 goto err;
2969 }
2970 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002971 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2972 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002973 }
2974 }
2975 }
2976
2977 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002978 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002979 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002980 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02002981 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002982 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 +02002983 LY_CHECK_GOTO(ret, err);
2984 if (!name) {
2985 /* end of element reached */
2986 break;
2987 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002988 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02002989 LY_CHECK_GOTO(ret, err);
2990 last = last->next;
2991 }
2992 } else {
2993 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02002994 if (out_len != 0) {
2995 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002996 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02002997 if (!(*element)->arg) {
2998 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002999 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02003000 ret = LY_EMEM;
3001 goto err;
3002 }
3003 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003004 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3005 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003006 }
David Sedlákb1a78352019-06-28 16:16:29 +02003007 }
3008 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003009 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 +02003010 LY_CHECK_GOTO(ret, err);
3011 }
3012
David Sedlákda8ffa32019-07-08 14:17:10 +02003013 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02003014 return LY_SUCCESS;
3015
3016err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003017 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003018 return ret;
3019}
3020
3021LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003022yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +02003023 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlák9494eb22019-06-21 16:06:53 +02003024{
David Sedlák968ac342019-07-11 15:17:59 +02003025 struct yin_subelement subelems[2] = {
3026 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
3027 {YANG_CUSTOM, NULL, 0}
3028 };
David Sedlák9494eb22019-06-21 16:06:53 +02003029
David Sedlák292763b2019-07-09 11:10:53 +02003030 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 +02003031
David Sedlákda8ffa32019-07-08 14:17:10 +02003032 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
David Sedlák9494eb22019-06-21 16:06:53 +02003033}
3034
3035LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003036yin_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 +02003037{
David Sedlák11900c82019-06-18 16:29:12 +02003038 struct lysp_ext *ex;
David Sedlákda8ffa32019-07-08 14:17:10 +02003039 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
David Sedlák292763b2019-07-09 11:10:53 +02003040 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 +02003041
David Sedlák3ffbc522019-07-02 17:49:28 +02003042 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
David Sedlák968ac342019-07-11 15:17:59 +02003043 struct yin_subelement subelems[5] = {
3044 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
3045 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
3046 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
3047 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
3048 {YANG_CUSTOM, NULL, 0}
3049 };
David Sedlák11900c82019-06-18 16:29:12 +02003050
David Sedlákda8ffa32019-07-08 14:17:10 +02003051 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
David Sedlák11900c82019-06-18 16:29:12 +02003052}
3053
David Sedlák4f03b932019-07-26 13:01:47 +02003054LY_ERR
3055yin_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 +02003056{
David Sedlák4f03b932019-07-26 13:01:47 +02003057 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3058 struct tree_node_meta node_meta = {NULL, &mod->data};
3059 struct augment_meta aug_meta = {NULL, &mod->augments};
3060 struct grouping_meta grp_meta = {NULL, &mod->groupings};
3061 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
3062 struct notif_meta notif_meta = {NULL, &mod->notifs};
3063 struct action_meta act_meta = {NULL, &mod->rpcs};
3064 struct typedef_meta tpdf_meta = {NULL, &mod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02003065 struct import_meta imp_meta = {mod->mod->prefix, &mod->imports};
David Sedlák4f03b932019-07-26 13:01:47 +02003066 struct yin_subelement subelems[28] = {
3067 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3068 {YANG_ANYXML, &node_meta, 0},
3069 {YANG_AUGMENT, &aug_meta, 0},
3070 {YANG_CHOICE, &node_meta, 0},
3071 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
3072 {YANG_CONTAINER, &node_meta, 0},
3073 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
3074 {YANG_DEVIATION, &mod->deviations, 0},
3075 {YANG_EXTENSION, &mod->extensions, 0},
3076 {YANG_FEATURE, &mod->features, 0},
3077 {YANG_GROUPING, &grp_meta, 0},
3078 {YANG_IDENTITY, &mod->identities, 0},
David Sedlák298ff6d2019-07-26 14:29:03 +02003079 {YANG_IMPORT, &imp_meta, 0},
David Sedlák4f03b932019-07-26 13:01:47 +02003080 {YANG_INCLUDE, &inc_meta, 0},
3081 {YANG_LEAF, &node_meta, 0},
3082 {YANG_LEAF_LIST, &node_meta, 0},
3083 {YANG_LIST, &node_meta, 0},
3084 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3085 {YANG_NOTIFICATION, &notif_meta, 0},
3086 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3087 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3088 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3089 {YANG_REVISION, &mod->revs, 0},
3090 {YANG_RPC, &act_meta, 0},
3091 {YANG_TYPEDEF, &tpdf_meta, 0},
3092 {YANG_USES, &node_meta, 0},
3093 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003094 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003095 };
David Sedlák3b4db242018-10-19 16:11:01 +02003096
David Sedlák4f03b932019-07-26 13:01:47 +02003097 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003098}
3099
3100LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003101yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3102{
3103 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3104 struct tree_node_meta node_meta = {NULL, &submod->data};
3105 struct augment_meta aug_meta = {NULL, &submod->augments};
3106 struct grouping_meta grp_meta = {NULL, &submod->groupings};
3107 struct include_meta inc_meta = {submod->name, &submod->includes};
3108 struct notif_meta notif_meta = {NULL, &submod->notifs};
3109 struct action_meta act_meta = {NULL, &submod->rpcs};
3110 struct typedef_meta tpdf_meta = {NULL, &submod->typedefs};
3111 struct import_meta imp_meta = {submod->prefix, &submod->imports};
3112 struct yin_subelement subelems[27] = {
3113 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3114 {YANG_ANYXML, &node_meta, 0},
3115 {YANG_AUGMENT, &aug_meta, 0},
3116 {YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3117 {YANG_CHOICE, &node_meta, 0},
3118 {YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE},
3119 {YANG_CONTAINER, &node_meta, 0},
3120 {YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE},
3121 {YANG_DEVIATION, &submod->deviations, 0},
3122 {YANG_EXTENSION, &submod->extensions, 0},
3123 {YANG_FEATURE, &submod->features, 0},
3124 {YANG_GROUPING, &grp_meta, 0},
3125 {YANG_IDENTITY, &submod->identities, 0},
3126 {YANG_IMPORT, &imp_meta, 0},
3127 {YANG_INCLUDE, &inc_meta, 0},
3128 {YANG_LEAF, &node_meta, 0},
3129 {YANG_LEAF_LIST, &node_meta, 0},
3130 {YANG_LIST, &node_meta, 0},
3131 {YANG_NOTIFICATION, &notif_meta, 0},
3132 {YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE},
3133 {YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE},
3134 {YANG_REVISION, &submod->revs, 0},
3135 {YANG_RPC, &act_meta, 0},
3136 {YANG_TYPEDEF, &tpdf_meta, 0},
3137 {YANG_USES, &node_meta, 0},
3138 {YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3139 {YANG_CUSTOM, NULL, 0}
3140 };
3141
3142 return yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3143}
3144
3145LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003146yin_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 +02003147{
3148 enum yang_keyword kw = YANG_NONE;
3149 LY_ERR ret = LY_SUCCESS;
3150 const char *prefix, *name;
3151 size_t prefix_len, name_len;
3152 struct yin_arg_record *attrs = NULL;
3153 struct lysp_submodule *mod_p = NULL;
3154
3155 /* create context */
3156 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003157 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003158 (*yin_ctx)->xml_ctx.ctx = ctx;
3159 (*yin_ctx)->xml_ctx.line = 1;
3160
David Sedlák1b623122019-08-05 15:27:49 +02003161 /* map the typedefs and groupings list from main context to the submodule's context */
3162 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3163 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3164
David Sedlák8985a142019-07-31 16:43:06 +02003165 /* check submodule */
3166 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3167 LY_CHECK_GOTO(ret, cleanup);
3168 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3169 LY_CHECK_GOTO(ret, cleanup);
3170 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3171
3172 if (kw == YANG_MODULE) {
3173 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3174 ret = LY_EINVAL;
3175 goto cleanup;
3176 } else if (kw != YANG_SUBMODULE) {
3177 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
3178 ly_stmt2str(kw));
3179 ret = LY_EVALID;
3180 goto cleanup;
3181 }
3182
3183 mod_p = calloc(1, sizeof *mod_p);
3184 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3185 mod_p->parsing = 1;
3186
3187 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3188 LY_CHECK_GOTO(ret, cleanup);
3189
David Sedlák6d781b62019-08-02 15:22:52 +02003190 name = NULL;
3191 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3192 const char *temp_data = data;
3193 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3194 data = temp_data;
3195 }
3196 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3197 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
3198 15, data, strlen(data) > 15 ? "..." : "");
3199 ret = LY_EVALID;
3200 goto cleanup;
3201 }
3202
David Sedlák8985a142019-07-31 16:43:06 +02003203 mod_p->parsing = 0;
3204 *submod = mod_p;
3205
3206cleanup:
3207 if (ret) {
3208 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003209 yin_parser_ctx_free(*yin_ctx);
3210 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003211 }
3212
3213 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3214 return ret;
3215}
3216
3217LY_ERR
3218yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003219{
David Sedláke4889912018-11-02 09:52:40 +01003220 LY_ERR ret = LY_SUCCESS;
3221 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003222 struct lysp_module *mod_p = NULL;
3223 const char *prefix, *name;
3224 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003225 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003226
David Sedlák8985a142019-07-31 16:43:06 +02003227 /* create context */
3228 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003229 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003230 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3231 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003232
David Sedlák8985a142019-07-31 16:43:06 +02003233 /* check module */
3234 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003235 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003236 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003237 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003238 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003239 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003240 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 +01003241 ret = LY_EINVAL;
3242 goto cleanup;
3243 } else if (kw != YANG_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003244 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 +02003245 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003246 ret = LY_EVALID;
3247 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003248 }
3249
David Sedlák3017da42019-02-15 09:48:04 +01003250 /* allocate module */
3251 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003252 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003253 mod_p->mod = mod;
3254 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003255
David Sedlák00250342019-06-21 14:19:39 +02003256 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003257 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003258 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003259
David Sedlák1b623122019-08-05 15:27:49 +02003260 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003261 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3262 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3263 }
3264 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3265 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
3266 15, data, strlen(data) > 15 ? "..." : "");
3267
3268 ret = LY_EVALID;
3269 goto cleanup;
3270 }
3271
David Sedlák3017da42019-02-15 09:48:04 +01003272 mod_p->parsing = 0;
3273 mod->parsed = mod_p;
3274
3275cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003276 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003277 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003278 yin_parser_ctx_free(*yin_ctx);
3279 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003280 }
David Sedlák8985a142019-07-31 16:43:06 +02003281 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003282 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003283}