blob: 7c278a0eef45385a146f4215cb2d1576ea8ddc3e [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/**
513 * @brief Parse enum or bit element.
514 *
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ák07869a52019-07-12 14:28:19 +0200524yin_parse_enum_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
525 enum yang_keyword enum_kw, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200526{
David Sedlák07869a52019-07-12 14:28:19 +0200527 assert(enum_kw == YANG_BIT || enum_kw == YANG_ENUM);
528 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200529 struct lysp_type_enum **enums;
530
531 if (enum_kw == YANG_BIT) {
532 enums = &type->bits;
533 } else {
534 enums = &type->enums;
535 }
536
537 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *enums, en, LY_EMEM);
David Sedlák07869a52019-07-12 14:28:19 +0200538 type->flags |= (enum_kw == YANG_ENUM) ? LYS_SET_ENUM : LYS_SET_BIT;
David Sedlák1e696782019-07-17 15:06:07 +0200539 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, enum_kw));
David Sedlák07869a52019-07-12 14:28:19 +0200540 if (enum_kw == YANG_ENUM) {
541 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
David Sedlákb9b892c2019-07-12 14:44:02 +0200542 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák07869a52019-07-12 14:28:19 +0200543 }
David Sedlák1e696782019-07-17 15:06:07 +0200544 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, *enums, name, ly_stmt2str(enum_kw), en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200545
546 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200547 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
548 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200549 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
550 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák32488102019-07-15 17:44:10 +0200551 {(enum_kw == YANG_ENUM) ? YANG_VALUE : YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200552 {YANG_CUSTOM, NULL, 0}
553 };
David Sedlák07869a52019-07-12 14:28:19 +0200554 return yin_parse_content(ctx, subelems, 6, data, enum_kw, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200555}
556
David Sedlákd3983112019-07-12 11:20:56 +0200557/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200558 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
559 * more instances, such as base or if-feature.
560 *
561 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200562 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200563 * @param[in,out] data Data to read from, always moved to currently handled character.
564 * @param[in] kw Type of current element.
565 * @param[out] values Parsed values to add to.
566 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200567 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200568 * @param[in,out] exts Extension instance to add to.
569 *
570 * @return LY_ERR values.
571 */
572static LY_ERR
573yin_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 +0200574 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 +0200575{
576 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200577 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200578 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200579 struct yin_subelement subelems[1] = {
580 {YANG_CUSTOM, &index, 0}
581 };
582
David Sedlák1f90d252019-07-10 17:09:32 +0200583 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200584
585 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
586}
587
588/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200589 * @brief Parse require instance element.
590 *
591 * @param[in,out] ctx Yin parser context for logging and to store current state.
592 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
593 * @param[in,out] data Data to read from, always moved to currently handled character.
594 * @prama[out] type Type structure to store value, flag and extensions.
595 *
596 * @return LY_ERR values.
597 */
598static LY_ERR
599yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
600 const char **data, struct lysp_type *type)
601{
602 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200603 struct yin_subelement subelems[1] = {
604 {YANG_CUSTOM, NULL, 0}
605 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200606
607 type->flags |= LYS_SET_REQINST;
608 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
609 if (strcmp(temp_val, "true") == 0) {
610 type->require_instance = 1;
611 } else if (strcmp(temp_val, "false") != 0) {
612 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "require-instance");
613 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
614 return LY_EVALID;
615 }
616 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
617
618 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
619}
620
621/**
David Sedlákce77bf52019-07-11 16:59:31 +0200622 * @brief Parse modifier element.
623 *
624 * @param[in,out] ctx Yin parser context for logging and to store current state.
625 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
626 * @param[in,out] data Data to read from, always moved to currently handled character.
627 * @param[in,out] pat Value to write to.
628 * @param[in,out] exts Extension instances to add to.
629 *
630 * @return LY_ERR values.
631 */
632static LY_ERR
633yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
634 const char **pat, struct lysp_ext_instance **exts)
635{
David Sedlákd3983112019-07-12 11:20:56 +0200636 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200637 const char *temp_val;
638 char *modified_val;
639 struct yin_subelement subelems[1] = {
640 {YANG_CUSTOM, NULL, 0}
641 };
642
643 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
644 if (strcmp(temp_val, "invert-match") != 0) {
645 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "modifier");
646 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
647 return LY_EVALID;
648 }
David Sedlákd3983112019-07-12 11:20:56 +0200649 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200650
651 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200652 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200653 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200654 strcpy(modified_val, *pat);
655 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200656
657 /* modify the new value */
658 modified_val[0] = 0x15;
659 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
660
661 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
662}
663
664/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200665 * @brief Parse a restriction element (length, range or one instance of must).
666 *
667 * @param[in,out] ctx Yin parser context for logging and to store current state.
668 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
669 * @param[in,out] data Data to read from, always moved to currently handled character.
670 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
671 * @param[in]
672 */
673static LY_ERR
674yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
675 enum yang_keyword restr_kw, struct lysp_restr *restr)
676{
677 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
678 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200679 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
680 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
681 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
682 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
683 {YANG_CUSTOM, NULL, 0}
684 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200685 /* argument of must is called condition, but argument of length and range is called value */
686 enum YIN_ARGUMENT arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
687 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
688
689 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
690}
691
692/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200693 * @brief Parse must element.
694 *
695 * @param[in,out] ctx YIN parser context for logging and to store current state.
696 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
697 * @param[in,out] data Data to read from, always moved to currently handled character.
698 * @param[in,out] restrs Restrictions to add to.
699 *
700 * @return LY_ERR values.
701 */
702static LY_ERR
703yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
704{
705 struct lysp_restr *restr;
706
707 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
708 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
709}
710
711/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200712 * @brief Parse position or value element.
713 *
714 * @param[in,out] ctx YIN parser context for logging and to store current state.
715 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
716 * @param[in,out] data Data to read from, always moved to currently handled character.
717 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
718 * @param[out] enm Enum structure to save value, flags and extensions.
719 *
720 * @return LY_ERR values.
721 */
722static LY_ERR
723yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
724 enum yang_keyword kw, struct lysp_type_enum *enm)
725{
726 assert(kw == YANG_POSITION || kw == YANG_VALUE);
727 const char *temp_val = NULL;
728 char *ptr;
729 long int num;
730 unsigned long int unum;
731
732 /* set value flag */
733 enm->flags |= LYS_SET_VALUE;
734
735 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200736 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 +0200737 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
738 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200739 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
740 goto error;
741 }
742
743 /* convert value */
744 errno = 0;
745 if (kw == YANG_VALUE) {
746 num = strtol(temp_val, &ptr, 10);
747 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
748 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
749 goto error;
750 }
751 } else {
752 unum = strtoul(temp_val, &ptr, 10);
753 if (unum > UINT64_C(4294967295)) {
754 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
755 goto error;
756 }
757 }
758 /* check if whole argument value was converted */
759 if (*ptr != '\0') {
760 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 +0200761 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200762 }
763 if (errno == ERANGE) {
764 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, ly_stmt2str(kw));
765 goto error;
766 }
767 /* save correctly ternary operator can't be used because num and unum have different signes */
768 if (kw == YANG_VALUE) {
769 enm->value = num;
770 } else {
771 enm->value = unum;
772 }
773 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
774
775 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200776 struct yin_subelement subelems[1] = {
777 {YANG_CUSTOM, NULL, 0}
778 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200779 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
780
781 error:
782 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
783 return LY_EVALID;
784}
785
David Sedlák05404f62019-07-24 14:11:53 +0200786
787/**
788 * @brief Parse belongs-to element.
789 *
790 * @param[in] ctx Yin parser context for logging and to store current state.
791 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
792 * @param[in,out] data Data to read from, always moved to currently handled character.
793 * @param[out] submod Structure of submodule that is being parsed.
794 * @param[in,out] exts Extension instances to add to.
795 *
796 * @return LY_ERR values
797 */
798static LY_ERR
799yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
800 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
801{
802 struct yin_subelement subelems[2] = {
803 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
804 {YANG_CUSTOM, NULL, 0}
805 };
806 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
807
808 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
809}
810
David Sedlák5545f5d2019-07-11 11:55:16 +0200811/**
David Sedlákc1771b12019-07-10 15:55:46 +0200812 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200813 * text element as child
814 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200815 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200816 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200817 * @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 +0200818 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200819 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200820 *
821 * @return LY_ERR values.
822 */
823static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200824yin_parse_meta_element(struct yin_parser_ctx *ctx, const char **data, enum yang_keyword elem_type,
David Sedlákb4e44562019-07-04 15:42:12 +0200825 const char **value, struct lysp_ext_instance **exts)
826{
827 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
828
David Sedlák968ac342019-07-11 15:17:59 +0200829 struct yin_subelement subelems[2] = {
830 {YANG_CUSTOM, NULL, 0},
831 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
832 };
David Sedlákb4e44562019-07-04 15:42:12 +0200833
David Sedlákda8ffa32019-07-08 14:17:10 +0200834 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200835}
836
837/**
David Sedlákc1771b12019-07-10 15:55:46 +0200838 * @brief Parse error-message element.
839 *
840 * @param[in,out] ctx Yin parser context for logging and to store current state.
841 * @param[in,out] data Data to read from.
842 * @param[out] value Where the content of error-message element should be stored.
843 * @param[in,out] exts Extension instance to add to.
844 *
845 * @return LY_ERR values.
846 */
847static LY_ERR
848yin_parse_err_msg_element(struct yin_parser_ctx *ctx, const char **data, const char **value,
849 struct lysp_ext_instance **exts)
850{
David Sedlák968ac342019-07-11 15:17:59 +0200851 struct yin_subelement subelems[2] = {
852 {YANG_CUSTOM, NULL, 0},
853 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
854 };
David Sedlákc1771b12019-07-10 15:55:46 +0200855
856 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
857}
858
859/**
David Sedlák374d2b32019-07-17 15:06:55 +0200860 * @brief parse type element.
861 *
862 * @brief Parse position or value element.
863 *
864 * @param[in,out] ctx YIN parser context for logging and to store current state.
865 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
866 * @param[in,out] data Data to read from, always moved to currently handled character.
867 * @param[in,out] type Type to wrote to.
868 * @param[in,out] exts Extension instance to add to.
869 *
870 * @return LY_ERR values.
871 */
872static LY_ERR
873yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
874{
875 struct yin_subelement subelems[11] = {
876 {YANG_BASE, type, 0},
877 {YANG_BIT, type, 0},
878 {YANG_ENUM, type, 0},
879 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
880 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
881 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
882 {YANG_PATTERN, type, 0},
883 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
884 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
885 {YANG_TYPE, type},
886 {YANG_CUSTOM, NULL, 0},
887 };
888 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
889 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
890}
891
David Sedlák1af868e2019-07-17 17:03:14 +0200892/**
893 * @brief Parse max-elements element.
894 *
895 * @param[in,out] ctx YIN parser context for logging and to store current state.
896 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
897 * @param[in,out] data Data to read from, always moved to currently handled character.
898 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200899 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +0200900 * @param[in,out] exts Extension instances to add to.
901 *
902 * @return LY_ERR values.
903 */
904static LY_ERR
905yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
906 uint16_t *flags, struct lysp_ext_instance **exts)
907{
908 const char *temp_val = NULL;
909 char *ptr;
910 unsigned long int num;
911 struct yin_subelement subelems[1] = {
912 {YANG_CUSTOM, NULL, 0},
913 };
David Sedlák374d2b32019-07-17 15:06:55 +0200914
David Sedlák1af868e2019-07-17 17:03:14 +0200915 *flags |= LYS_SET_MAX;
916 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
917 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
918 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
919 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
920 return LY_EVALID;
921 }
922
923 if (strcmp(temp_val, "unbounded")) {
924 errno = 0;
925 num = strtoul(temp_val, &ptr, 10);
926 if (*ptr != '\0') {
927 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
928 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
929 return LY_EVALID;
930 }
931 if ((errno == ERANGE) || (num > UINT32_MAX)) {
932 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "max-elements");
933 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
934 return LY_EVALID;
935 }
936 *max = num;
937 }
938 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
939 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
940}
David Sedlák374d2b32019-07-17 15:06:55 +0200941
942/**
David Sedlák09e18c92019-07-18 11:17:11 +0200943 * @brief Parse max-elements element.
944 *
945 * @param[in,out] ctx YIN parser context for logging and to store current state.
946 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
947 * @param[in,out] data Data to read from, always moved to currently handled character.
948 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200949 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +0200950 * @param[in,out] exts Extension instances to add to.
951 *
952 * @return LY_ERR values.
953 */
954static LY_ERR
955yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
956 uint16_t *flags, struct lysp_ext_instance **exts)
957{
958 const char *temp_val = NULL;
959 char *ptr;
960 unsigned long int num;
961 struct yin_subelement subelems[1] = {
962 {YANG_CUSTOM, NULL, 0},
963 };
964
965 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +0200966 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 +0200967
968 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
969 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
970 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
971 return LY_EVALID;
972 }
973
974 errno = 0;
975 num = strtoul(temp_val, &ptr, 10);
976 if (ptr[0] != 0) {
977 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
978 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
979 return LY_EVALID;
980 }
981 if (errno == ERANGE || num > UINT32_MAX) {
982 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "min-elements");
983 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
984 return LY_EVALID;
985 }
986 *min = num;
987 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +0200988 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +0200989}
990
David Sedláka2dad212019-07-18 12:45:19 +0200991/**
992 * @brief Parse min-elements or max-elements element.
993 *
994 * @param[in,out] ctx YIN parser context for logging and to store current state.
995 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
996 * @param[in,out] data Data to read from, always moved to currently handled character.
997 * @param[in] parent Identification of parent element.
998 * @param[in] current Identification of current element.
999 * @param[in] dest Where the parsed value and flags should be stored.
1000 *
1001 * @return LY_ERR values.
1002 */
David Sedlák09e18c92019-07-18 11:17:11 +02001003static LY_ERR
1004yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1005 enum yang_keyword parent, enum yang_keyword current, void *dest)
1006{
1007 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001008 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001009 uint32_t *lim;
1010 uint16_t *flags;
1011 struct lysp_ext_instance **exts;
1012
1013 if (parent == YANG_LEAF_LIST) {
1014 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1015 flags = &((struct lysp_node_leaflist *)dest)->flags;
1016 exts = &((struct lysp_node_leaflist *)dest)->exts;
1017 } else if (parent == YANG_REFINE) {
1018 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1019 flags = &((struct lysp_refine *)dest)->flags;
1020 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001021 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001022 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1023 flags = &((struct lysp_node_list *)dest)->flags;
1024 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001025 } else {
1026 lim = ((struct minmax_dev_meta *)dest)->lim;
1027 flags = ((struct minmax_dev_meta *)dest)->flags;
1028 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001029 }
1030
1031 if (current == YANG_MAX_ELEMENTS) {
1032 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1033 } else {
1034 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1035 }
1036
1037 return LY_SUCCESS;
1038}
1039
1040/**
David Sedláka2dad212019-07-18 12:45:19 +02001041 * @brief Parser ordered-by element.
1042 *
1043 * @param[in,out] ctx YIN parser context for logging and to store current state.
1044 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1045 * @param[in,out] data Data to read from, always moved to currently handled character.
1046 * @param[out] flags Flags to write to.
1047 * @param[in,out] exts Extension instance to add to.
1048 *
1049 * @return LY_ERR values.
1050 */
1051static LY_ERR
1052yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1053 uint16_t *flags, struct lysp_ext_instance **exts)
1054{
1055 const char *temp_val;
1056 struct yin_subelement subelems[1] = {
1057 {YANG_CUSTOM, NULL, 0},
1058 };
1059
1060 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1061 if (strcmp(temp_val, "system") == 0) {
1062 *flags |= LYS_ORDBY_SYSTEM;
1063 } else if (strcmp(temp_val, "user") == 0) {
1064 *flags |= LYS_ORDBY_USER;
1065 } else {
1066 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "ordered-by");
1067 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1068 return LY_EVALID;
1069 }
1070 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1071
1072 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1073}
1074
1075/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001076 * @brief parse any-data or any-xml element.
1077 *
1078 * @param[in,out] ctx YIN parser context for logging and to store current state.
1079 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1080 * @param[in,out] data Data to read from, always moved to currently handled character.
1081 * @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 +02001082 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001083 *
1084 * @return LY_ERR values.
1085 */
1086static LY_ERR
1087yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1088 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1089{
1090 struct lysp_node *iter;
1091 struct lysp_node_anydata *any;
1092
1093 /* create structure */
1094 any = calloc(1, sizeof *any);
1095 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1096 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1097 any->parent = node_meta->parent;
1098
1099 /* insert into siblings */
1100 if (!*(node_meta->siblings)) {
1101 *(node_meta->siblings) = (struct lysp_node *)any;
1102 } else {
1103 for (iter = *(node_meta->siblings); iter->next; iter = iter->next);
1104 iter->next = (struct lysp_node *)any;
1105 }
1106
1107 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001108 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 +02001109
1110 struct yin_subelement subelems[9] = {
1111 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1112 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1113 {YANG_IF_FEATURE, &any->iffeatures, 0},
1114 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1115 {YANG_MUST, &any->musts, 0},
1116 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1117 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1118 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1119 {YANG_CUSTOM, NULL, 0},
1120 };
1121 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1122}
1123
1124/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001125 * @brief parse leaf element.
1126 *
1127 * @param[in,out] ctx YIN parser context for logging and to store current state.
1128 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1129 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001130 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák203ca3a2019-07-18 15:26:25 +02001131 *
1132 * @return LY_ERR values.
1133 */
1134static LY_ERR
1135yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1136 struct tree_node_meta *node_meta)
1137{
1138 struct lysp_node *iter;
1139 struct lysp_node_leaf *leaf;
1140
1141 /* create structure */
1142 leaf = calloc(1, sizeof *leaf);
1143 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1144 leaf->nodetype = LYS_LEAF;
1145 leaf->parent = node_meta->parent;
1146
1147 /* insert into siblings */
1148 if (!*(node_meta->siblings)) {
1149 *node_meta->siblings = (struct lysp_node *)leaf;
1150 } else {
1151 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1152 iter->next = (struct lysp_node *)leaf;
1153 }
1154
1155 /* parser argument */
1156 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1157
1158 /* parse content */
1159 struct yin_subelement subelems[12] = {
1160 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1161 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1162 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1163 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1164 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1165 {YANG_MUST, &leaf->musts, 0},
1166 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1167 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1168 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1169 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1170 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1171 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001172 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001173 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1174}
1175
1176/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001177 * @brief Parse leaf-list element.
1178 *
1179 * @param[in,out] ctx YIN parser context for logging and to store current state.
1180 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1181 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001182 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001183 *
1184 * @return LY_ERR values.
1185 */
1186static LY_ERR
1187yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1188 struct tree_node_meta *node_meta)
1189{
1190 struct lysp_node *iter;
1191 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001192
1193 llist = calloc(1, sizeof *llist);
1194 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1195 llist->nodetype = LYS_LEAFLIST;
1196 llist->parent = node_meta->parent;
1197
1198 /* insert into siblings */
1199 if (!*(node_meta->siblings)) {
1200 *node_meta->siblings = (struct lysp_node *)llist;
1201 } else {
1202 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1203 iter->next = (struct lysp_node *)llist;
1204 }
1205
1206 /* parse argument */
1207 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1208
1209 /* parse content */
1210 struct yin_subelement subelems[14] = {
1211 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1212 {YANG_DEFAULT, &llist->dflts, 0},
1213 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1214 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1215 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1216 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1217 {YANG_MUST, &llist->musts, 0},
1218 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1219 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1220 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1221 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1222 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1223 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1224 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001225 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001226 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1227
1228 /* invalid combination of subelements */
1229 if ((llist->min) && (llist->dflts)) {
1230 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
1231 return LY_EVALID;
1232 }
1233 if (llist->max && llist->min > llist->max) {
1234 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1235 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1236 llist->min, llist->max);
1237 return LY_EVALID;
1238 }
1239
1240 return LY_SUCCESS;
1241}
1242
1243/**
David Sedlák04e17b22019-07-19 15:29:48 +02001244 * @brief Parse typedef element.
1245 *
1246 * @param[in,out] ctx YIN parser context for logging and to store current state.
1247 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1248 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001249 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001250 *
1251 * @return LY_ERR values.
1252 */
1253static LY_ERR
1254yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1255 struct typedef_meta *typedef_meta)
1256{
1257 struct lysp_tpdf *tpdf;
1258 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *typedef_meta->typedefs, tpdf, LY_EMEM);
1259
1260 /* parse argument */
1261 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1262
1263 /* parse content */
1264 struct yin_subelement subelems[7] = {
1265 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1266 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1267 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1268 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1269 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1270 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1271 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001272 };
David Sedlák04e17b22019-07-19 15:29:48 +02001273 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1274
1275 /* store data for collision check */
1276 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1277 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1278 }
1279
1280 return LY_SUCCESS;
1281}
1282
1283/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001284 * @brief Parse refine element.
1285 *
1286 * @param[in,out] ctx YIN parser context for logging and to store current state.
1287 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1288 * @param[in,out] data Data to read from, always moved to currently handled character.
1289 * @param[in,out] refines Refines to add to.
1290 *
1291 * @return LY_ERR values.
1292 */
1293static LY_ERR
1294yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1295 struct lysp_refine **refines)
1296{
1297 struct lysp_refine *rf;
1298
1299 /* allocate new refine */
1300 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1301
1302 /* parse attribute */
1303 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1304 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1305
1306 /* parse content */
1307 struct yin_subelement subelems[11] = {
1308 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1309 {YANG_DEFAULT, &rf->dflts, 0},
1310 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1311 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1312 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1313 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1314 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1315 {YANG_MUST, &rf->musts, 0},
1316 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1317 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1318 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001319 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001320 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1321}
1322
1323/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001324 * @brief Parse uses element.
1325 *
1326 * @param[in,out] ctx YIN parser context for logging and to store current state.
1327 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1328 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001329 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001330 *
1331 * @return LY_ERR values.
1332 */
1333static LY_ERR
1334yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1335 struct tree_node_meta *node_meta)
1336{
1337 struct lysp_node *iter;
1338 struct lysp_node_uses *uses;
1339
1340 /* create structure */
1341 uses = calloc(1, sizeof *uses);
1342 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1343 uses->nodetype = LYS_USES;
1344 uses->parent = node_meta->parent;
1345
1346 /* insert into siblings */
1347 if (!*(node_meta->siblings)) {
1348 *node_meta->siblings = (struct lysp_node *)uses;
1349 } else {
1350 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1351 iter->next = (struct lysp_node *)uses;
1352 }
1353
1354 /* parse argument */
1355 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1356
1357 /* parse content */
1358 struct augment_meta augments = {(struct lysp_node *)uses, &uses->augments};
1359 struct yin_subelement subelems[8] = {
1360 {YANG_AUGMENT, &augments, 0},
1361 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1362 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1363 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1364 {YANG_REFINE, &uses->refines, 0},
1365 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1366 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1367 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001368 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001369 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1370 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1371
1372 return LY_SUCCESS;
1373}
1374
1375/**
David Sedlákaa854b02019-07-22 14:17:10 +02001376 * @brief Parse revision element.
1377 *
1378 * @param[in,out] ctx YIN parser context for logging and to store current state.
1379 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1380 * @param[in,out] data Data to read from, always moved to currently handled character.
1381 * @param[in,out] revs Parsed revisions to add to.
1382 *
1383 * @return LY_ERR values.
1384 */
1385static LY_ERR
1386yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1387 struct lysp_revision **revs)
1388{
1389 struct lysp_revision *rev;
1390 const char *temp_date = NULL;
1391
1392 /* allocate new reivison */
1393 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1394
1395 /* parse argument */
1396 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1397 /* check value */
1398 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1399 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1400 return LY_EVALID;
1401 }
1402 strcpy(rev->date, temp_date);
1403 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1404
1405 /* parse content */
1406 struct yin_subelement subelems[3] = {
1407 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1408 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1409 {YANG_CUSTOM, NULL, 0},
1410 };
1411 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1412}
1413
David Sedlák5e13dea2019-07-22 16:06:45 +02001414/**
1415 * @brief Parse include element.
1416 *
1417 * @param[in,out] ctx YIN parser context for logging and to store current state.
1418 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1419 * @param[in,out] data Data to read from, always moved to currently handled character.
1420 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1421 *
1422 * @return LY_ERR values.
1423 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001424static LY_ERR
1425yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1426 struct include_meta *inc_meta)
1427{
1428 struct lysp_include *inc;
1429
1430 /* allocate new include */
1431 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1432
1433 /* parse argument */
1434 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1435
1436 /* submodules share the namespace with the module names, so there must not be
1437 * a module of the same name in the context, no need for revision matching */
1438 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
1439 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG,
1440 "Name collision between module and submodule of name \"%s\".", inc->name);
1441 return LY_EVALID;
1442 }
1443
1444 /* parse content */
1445 struct yin_subelement subelems[4] = {
1446 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1447 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1448 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1449 {YANG_CUSTOM, NULL, 0},
1450 };
1451 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1452}
1453
David Sedlákaa854b02019-07-22 14:17:10 +02001454/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001455 * @brief Parse feature element.
1456 *
1457 * @param[in,out] ctx YIN parser context for logging and to store current state.
1458 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1459 * @param[in,out] data Data to read from, always moved to currently handled character.
1460 * @param[in,out] features Features to add to.
1461 *
1462 * @return LY_ERR values.
1463 */
1464static LY_ERR
1465yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1466 struct lysp_feature **features)
1467{
1468 struct lysp_feature *feat;
1469
1470 /* allocate new feature */
1471 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1472
1473 /* parse argument */
1474 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1475
1476 /* parse content */
1477 struct yin_subelement subelems[5] = {
1478 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1479 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1480 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1481 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1482 {YANG_CUSTOM, NULL, 0},
1483 };
1484 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1485}
1486
1487/**
David Sedlák28794f22019-07-22 16:45:00 +02001488 * @brief Parse identity element.
1489 *
1490 * @param[in,out] ctx YIN parser context for logging and to store current state.
1491 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1492 * @param[in,out] data Data to read from, always moved to currently handled character.
1493 * @param[in,out] identities Identities to add to.
1494 *
1495 * @return LY_ERR values.
1496 */
1497static LY_ERR
1498yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1499 struct lysp_ident **identities)
1500{
1501 struct lysp_ident *ident;
1502
1503 /* allocate new identity */
1504 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1505
1506 /* parse argument */
1507 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1508
1509 /* parse content */
1510 struct yin_subelement subelems[6] = {
1511 {YANG_BASE, &ident->bases, 0},
1512 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1513 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1514 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1515 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1516 {YANG_CUSTOM, NULL, 0},
1517 };
1518 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1519}
1520
1521/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001522 * @brief Parse list element.
1523 *
1524 * @param[in,out] ctx YIN parser context for logging and to store current state.
1525 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1526 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001527 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákaf536aa2019-07-23 13:42:23 +02001528 *
1529 * @return LY_ERR values.
1530 */
1531static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001532yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1533 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001534{
1535 struct lysp_node *iter;
1536 struct lysp_node_list *list;
1537
1538 /* create structure */
1539 list = calloc(1, sizeof *list);
1540 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1541 list->nodetype = LYS_LIST;
1542 list->parent = node_meta->parent;
1543
1544 /* insert into siblings */
1545 if (!*(node_meta->siblings)) {
1546 *node_meta->siblings = (struct lysp_node *)list;
1547 } else {
1548 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1549 iter->next = (struct lysp_node *)list;
1550 }
1551
1552 /* parse argument */
1553 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1554
1555 /* parse list content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001556 struct action_meta act_meta = {(struct lysp_node *)list, &list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001557 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
1558 struct typedef_meta typedef_meta = {(struct lysp_node *)list, &list->typedefs};
David Sedlák031b9e72019-07-23 15:19:37 +02001559 struct notif_meta notif_meta = {(struct lysp_node *)list, &list->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001560 struct grouping_meta gr_meta = {(struct lysp_node *)list, &list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001561 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001562 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001563 {YANG_ANYDATA, &new_node_meta, 0},
1564 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001565 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001566 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001567 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001568 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001569 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001570 {YANG_IF_FEATURE, &list->iffeatures, 0},
1571 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1572 {YANG_LEAF, &new_node_meta, 0},
1573 {YANG_LEAF_LIST, &new_node_meta, 0},
1574 {YANG_LIST, &new_node_meta, 0},
1575 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1576 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1577 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001578 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001579 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1580 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1581 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1582 {YANG_TYPEDEF, &typedef_meta, 0},
1583 {YANG_UNIQUE, &list->uniques, 0},
1584 {YANG_USES, &new_node_meta, 0},
1585 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1586 {YANG_CUSTOM, NULL, 0},
1587 };
1588 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1589
1590 /* finalize parent pointers to the reallocated items */
1591 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1592
1593 if (list->max && list->min > list->max) {
1594 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1595 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1596 list->min, list->max);
1597 return LY_EVALID;
1598 }
1599
1600 return LY_SUCCESS;
1601}
1602
1603/**
David Sedlák031b9e72019-07-23 15:19:37 +02001604 * @brief Parse notification element.
1605 *
1606 * @param[in,out] ctx YIN parser context for logging and to store current state.
1607 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1608 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001609 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001610 *
1611 * @return LY_ERR values.
1612 */
1613static LY_ERR
1614yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1615 struct notif_meta *notif_meta)
1616{
1617 struct lysp_notif *notif;
1618
1619 /* allocate new notification */
1620 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notif_meta->notifs, notif, LY_EMEM);
1621 notif->nodetype = LYS_NOTIF;
1622 notif->parent = notif_meta->parent;
1623
1624 /* parse argument */
1625 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1626
1627 /* parse notification content */
1628 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
1629 struct typedef_meta typedef_meta = {(struct lysp_node *)notif, &notif->typedefs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001630 struct grouping_meta gr_meta = {(struct lysp_node *)notif, &notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001631 struct yin_subelement subelems[16] = {
1632 {YANG_ANYDATA, &node_meta, 0},
1633 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001634 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001635 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001636 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001637 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001638 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1639 {YANG_LEAF, &node_meta, 0},
1640 {YANG_LEAF_LIST, &node_meta, 0},
1641 {YANG_LIST, &node_meta, 0},
1642 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1643 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1644 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1645 {YANG_TYPEDEF, &typedef_meta, 0},
1646 {YANG_USES, &node_meta, 0},
1647 {YANG_CUSTOM, NULL, 0},
1648 };
1649 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1650
1651 /* finalize parent pointers to the reallocated items */
1652 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1653
1654 return LY_SUCCESS;
1655}
1656
1657/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001658 * @brief Parse notification element.
1659 *
1660 * @param[in,out] ctx YIN parser context for logging and to store current state.
1661 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1662 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001663 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001664 *
1665 * @return LY_ERR values.
1666 */
1667static LY_ERR
1668yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1669 struct grouping_meta *gr_meta)
1670{
1671 struct lysp_grp *grp;
1672
1673 /* create new grouping */
1674 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *gr_meta->groupings, grp, LY_EMEM);
1675 grp->nodetype = LYS_GROUPING;
1676 grp->parent = gr_meta->parent;
1677
1678 /* parse argument */
1679 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1680
1681 /* parse grouping content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001682 struct action_meta act_meta = {(struct lysp_node *)grp, &grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001683 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
1684 struct typedef_meta typedef_meta = {(struct lysp_node *)grp, &grp->typedefs};
1685 struct grouping_meta sub_grouping = {(struct lysp_node *)grp, &grp->groupings};
1686 struct notif_meta notif_meta = {(struct lysp_node *)grp, &grp->notifs};
1687 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001688 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001689 {YANG_ANYDATA, &node_meta, 0},
1690 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001691 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001692 {YANG_CONTAINER, &node_meta, 0},
1693 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1694 {YANG_GROUPING, &sub_grouping, 0},
1695 {YANG_LEAF, &node_meta, 0},
1696 {YANG_LEAF_LIST, &node_meta, 0},
1697 {YANG_LIST, &node_meta, 0},
1698 {YANG_NOTIFICATION, &notif_meta, 0},
1699 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
1700 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
1701 {YANG_TYPEDEF, &typedef_meta, 0},
1702 {YANG_USES, &node_meta, 0},
1703 {YANG_CUSTOM, NULL, 0},
1704 };
1705 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
1706 /* finalize parent pointers to the reallocated items */
1707 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
1708
1709 return LY_SUCCESS;
1710}
1711
1712/**
David Sedlákf111bcb2019-07-23 17:15:51 +02001713 * @brief Parse list element.
1714 *
1715 * @param[in,out] ctx YIN parser context for logging and to store current state.
1716 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1717 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001718 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákf111bcb2019-07-23 17:15:51 +02001719 *
1720 * @return LY_ERR values.
1721 */
1722static LY_ERR
1723yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1724 struct tree_node_meta *node_meta)
1725{
1726 struct lysp_node *iter;
1727 struct lysp_node_container *cont;
1728
1729 /* create new container */
1730 cont = calloc(1, sizeof *cont);
1731 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1732 cont->nodetype = LYS_CONTAINER;
1733 cont->parent = node_meta->parent;
1734
1735 /* insert into siblings */
1736 if (!*(node_meta->siblings)) {
1737 *node_meta->siblings = (struct lysp_node *)cont;
1738 } else {
1739 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1740 iter->next = (struct lysp_node *)cont;
1741 }
1742
1743 /* parse aegument */
1744 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
1745
1746 /* parse container content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001747 struct action_meta act_meta = {(struct lysp_node *)cont, &cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02001748 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
1749 struct grouping_meta grp_meta = {(struct lysp_node *)cont, &cont->groupings};
1750 struct typedef_meta typedef_meta = {(struct lysp_node *)cont, &cont->typedefs};
1751 struct notif_meta notif_meta = {(struct lysp_node *)cont, &cont->notifs};
1752 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001753 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02001754 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1755 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001756 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001757 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
1758 {YANG_CONTAINER, &new_node_meta, 0},
1759 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
1760 {YANG_GROUPING, &grp_meta, 0},
1761 {YANG_IF_FEATURE, &cont->iffeatures, 0},
1762 {YANG_LEAF, &new_node_meta, 0},
1763 {YANG_LEAF_LIST, &new_node_meta, 0},
1764 {YANG_LIST, &new_node_meta, 0},
1765 {YANG_MUST, &cont->musts, 0},
1766 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
1767 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
1768 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
1769 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
1770 {YANG_TYPEDEF, &typedef_meta, 0},
1771 {YANG_USES, &new_node_meta, 0},
1772 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
1773 {YANG_CUSTOM, NULL, 0},
1774 };
1775 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
1776 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
1777
1778 return LY_SUCCESS;
1779}
1780
1781/**
David Sedlák5379d392019-07-24 10:42:03 +02001782 * @brief Parse case element.
1783 *
1784 * @param[in,out] ctx YIN parser context for logging and to store current state.
1785 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1786 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001787 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák5379d392019-07-24 10:42:03 +02001788 *
1789 * @return LY_ERR values.
1790 */
1791static LY_ERR
1792yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1793 struct tree_node_meta *node_meta)
1794{
1795 struct lysp_node *iter;
1796 struct lysp_node_case *cas;
1797
1798 /* create new case */
1799 cas = calloc(1, sizeof *cas);
1800 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1801 cas->nodetype = LYS_CASE;
1802 cas->parent = node_meta->parent;
1803
1804 /* insert into siblings */
1805 if (!*(node_meta->siblings)) {
1806 *node_meta->siblings = (struct lysp_node *)cas;
1807 } else {
1808 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1809 iter->next = (struct lysp_node *)cas;
1810 }
1811
1812 /* parse argument */
1813 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
1814
1815 /* parse case content */
1816 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
1817 struct yin_subelement subelems[14] = {
1818 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1819 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001820 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02001821 {YANG_CONTAINER, &new_node_meta, 0},
1822 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
1823 {YANG_IF_FEATURE, &cas->iffeatures, 0},
1824 {YANG_LEAF, &new_node_meta, 0},
1825 {YANG_LEAF_LIST, &new_node_meta, 0},
1826 {YANG_LIST, &new_node_meta, 0},
1827 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
1828 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
1829 {YANG_USES, &new_node_meta, 0},
1830 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
1831 {YANG_CUSTOM, NULL, 0},
1832 };
1833 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
1834}
1835
1836/**
David Sedlák05404f62019-07-24 14:11:53 +02001837 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001838 *
1839 * @param[in,out] ctx YIN parser context for logging and to store current state.
1840 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1841 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001842 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001843 *
1844 * @return LY_ERR values.
1845 */
1846LY_ERR
1847yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1848 struct tree_node_meta *node_meta)
1849{
1850 struct lysp_node *iter;
1851 struct lysp_node_choice *choice;
1852
1853 /* create new choice */
1854 choice = calloc(1, sizeof *choice);
1855 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1856 choice->nodetype = LYS_CHOICE;
1857 choice->parent = node_meta->parent;
1858
1859 /* insert into siblings */
1860 if (!*(node_meta->siblings)) {
1861 *node_meta->siblings = (struct lysp_node *)choice;
1862 } else {
1863 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1864 iter->next = (struct lysp_node *)choice;
1865 }
1866
1867 /* parse argument */
1868 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
1869
1870 /* parse choice content */
1871 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
1872 struct yin_subelement subelems[17] = {
1873 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1874 {YANG_ANYXML, &new_node_meta, 0},
1875 {YANG_CASE, &new_node_meta, 0},
1876 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
1877 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
1878 {YANG_CONTAINER, &new_node_meta, 0},
1879 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
1880 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
1881 {YANG_IF_FEATURE, &choice->iffeatures, 0},
1882 {YANG_LEAF, &new_node_meta, 0},
1883 {YANG_LEAF_LIST, &new_node_meta, 0},
1884 {YANG_LIST, &new_node_meta, 0},
1885 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
1886 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
1887 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
1888 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
1889 {YANG_CUSTOM, NULL, 0},
1890 };
1891 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
1892}
1893
1894/**
David Sedlák05404f62019-07-24 14:11:53 +02001895 * @brief Parse input or output element.
1896 *
1897 * @param[in,out] ctx YIN parser context for logging and to store current state.
1898 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1899 * @param[in,out] data Data to read from, always moved to currently handled character.
1900 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
1901 *
1902 * @return LY_ERR values.
1903 */
1904static LY_ERR
1905yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
1906 struct inout_meta *inout_meta)
1907{
1908 /* initiate structure */
1909 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
1910 inout_meta->inout_p->parent = inout_meta->parent;
1911
1912 /* check attributes */
1913 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
1914
1915 /* parser input/output content */
1916 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
1917 struct grouping_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->groupings};
1918 struct typedef_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->typedefs};
1919 struct yin_subelement subelems[12] = {
1920 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
1921 {YANG_ANYXML, &node_meta, 0},
1922 {YANG_CHOICE, &node_meta, 0},
1923 {YANG_CONTAINER, &node_meta, 0},
1924 {YANG_GROUPING, &grp_meta, 0},
1925 {YANG_LEAF, &node_meta, 0},
1926 {YANG_LEAF_LIST, &node_meta, 0},
1927 {YANG_LIST, &node_meta, 0},
1928 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
1929 {YANG_TYPEDEF, &typedef_meta, 0},
1930 {YANG_USES, &node_meta, 0},
1931 {YANG_CUSTOM, NULL, 0},
1932 };
1933 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
1934
1935 /* finalize parent pointers to the reallocated items */
1936 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
1937 NULL, NULL, NULL));
1938
1939 return LY_SUCCESS;
1940}
1941
David Sedlák992fb7c2019-07-24 16:51:01 +02001942/**
1943 * @brief Parse action element.
1944 *
1945 * @param[in,out] ctx YIN parser context for logging and to store current state.
1946 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1947 * @param[in,out] data Data to read from, always moved to currently handled character.
1948 * @param[in] act_meta Meta information about parent node and actions to add to.
1949 *
1950 * @return LY_ERR values.
1951 */
David Sedlák85d0eca2019-07-24 15:15:21 +02001952static LY_ERR
1953yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1954 struct action_meta *act_meta)
1955{
1956 struct lysp_action *act;
1957
1958 /* create new action */
1959 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *act_meta->actions, act, LY_EMEM);
1960 act->nodetype = LYS_ACTION;
1961 act->parent = act_meta->parent;
1962
1963 /* parse argument */
1964 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
1965
1966 /* parse content */
1967 struct grouping_meta grp_meta = {(struct lysp_node *)act, &act->groupings};
1968 struct typedef_meta typedef_meta = {(struct lysp_node *)act, &act->typedefs};
1969 struct inout_meta input = {(struct lysp_node *)act, &act->input};
1970 struct inout_meta output = {(struct lysp_node *)act, &act->output};
1971 struct yin_subelement subelems[9] = {
1972 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
1973 {YANG_GROUPING, &grp_meta, 0},
1974 {YANG_IF_FEATURE, &act->iffeatures, 0},
1975 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
1976 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
1977 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
1978 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
1979 {YANG_TYPEDEF, &typedef_meta, 0},
1980 {YANG_CUSTOM, NULL, 0},
1981 };
1982 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
1983 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
1984
1985 return LY_SUCCESS;
1986}
1987
David Sedlák05404f62019-07-24 14:11:53 +02001988/**
David Sedlák992fb7c2019-07-24 16:51:01 +02001989 * @brief Parse augment element.
1990 *
1991 * @param[in,out] ctx YIN parser context for logging and to store current state.
1992 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1993 * @param[in,out] data Data to read from, always moved to currently handled character.
1994 * @param[in] aug_meta Meta information about parent node and augments to add to.
1995 *
1996 * @return LY_ERR values.
1997 */
1998static LY_ERR
1999yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2000 struct augment_meta *aug_meta)
2001{
2002 struct lysp_augment *aug;
2003
2004 /* create new augment */
2005 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *aug_meta->augments, aug, LY_EMEM);
2006 aug->nodetype = LYS_AUGMENT;
2007 aug->parent = aug_meta->parent;
2008
2009 /* parse argument */
2010 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2011 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2012
2013 /* parser augment content */
2014 struct action_meta act_meta = {(struct lysp_node *)aug, &aug->actions};
2015 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
2016 struct notif_meta notif_meta = {(struct lysp_node *)aug, &aug->notifs};
2017 struct yin_subelement subelems[17] = {
2018 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
2019 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2020 {YANG_ANYXML, &node_meta, 0},
2021 {YANG_CASE, &node_meta, 0},
2022 {YANG_CHOICE, &node_meta, 0},
2023 {YANG_CONTAINER, &node_meta, 0},
2024 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
2025 {YANG_IF_FEATURE, &aug->iffeatures, 0},
2026 {YANG_LEAF, &node_meta, 0},
2027 {YANG_LEAF_LIST, &node_meta, 0},
2028 {YANG_LIST, &node_meta, 0},
2029 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2030 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
2031 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
2032 {YANG_USES, &node_meta, 0},
2033 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
2034 {YANG_CUSTOM, NULL, 0},
2035 };
2036 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
2037
2038 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2039
2040 return LY_SUCCESS;
2041}
2042
David Sedlák8b754462019-07-25 16:22:13 +02002043/**
2044 * @brief Parse deviate element.
2045 *
2046 * @param[in,out] ctx YIN parser context for logging and to store current state.
2047 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2048 * @param[in,out] data Data to read from, always moved to currently handled character.
2049 * @param[in] deviates Deviates to add to.
2050 *
2051 * @return LY_ERR values.
2052 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002053static LY_ERR
2054yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2055 struct lysp_deviate **deviates)
2056{
2057 LY_ERR ret = LY_SUCCESS;
2058 uint8_t dev_mod;
2059 const char *temp_val;
2060 struct lysp_deviate *iter, *d;
2061 struct lysp_deviate_add *d_add = NULL;
2062 struct lysp_deviate_rpl *d_rpl = NULL;
2063 struct lysp_deviate_del *d_del = NULL;
2064
2065 /* parse argument */
2066 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2067
2068 if (strcmp(temp_val, "not-supported") == 0) {
2069 dev_mod = LYS_DEV_NOT_SUPPORTED;
2070 } else if (strcmp(temp_val, "add") == 0) {
2071 dev_mod = LYS_DEV_ADD;
2072 } else if (strcmp(temp_val, "replace") == 0) {
2073 dev_mod = LYS_DEV_REPLACE;
2074 } else if (strcmp(temp_val, "delete") == 0) {
2075 dev_mod = LYS_DEV_DELETE;
2076 } else {
2077 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "deviate");
2078 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2079 return LY_EVALID;
2080 }
2081 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2082
2083 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2084 d = calloc(1, sizeof *d);
2085 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2086 struct yin_subelement subelems[1] = {
2087 {YANG_CUSTOM, NULL, 0}
2088 };
2089 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2090
2091 } else if (dev_mod == LYS_DEV_ADD) {
2092 d_add = calloc(1, sizeof *d_add);
2093 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2094 d = (struct lysp_deviate *)d_add;
2095 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2096 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2097 struct yin_subelement subelems[9] = {
2098 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2099 {YANG_DEFAULT, &d_add->dflts, 0},
2100 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2101 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2102 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2103 {YANG_MUST, &d_add->musts, 0},
2104 {YANG_UNIQUE, &d_add->uniques, 0},
2105 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2106 {YANG_CUSTOM, NULL, 0},
2107 };
2108 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2109
2110 } else if (dev_mod == LYS_DEV_REPLACE) {
2111 d_rpl = calloc(1, sizeof *d_rpl);
2112 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2113 d = (struct lysp_deviate *)d_rpl;
2114 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2115 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2116 struct yin_subelement subelems[8] = {
2117 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2118 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2119 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2120 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2121 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2122 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2123 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2124 {YANG_CUSTOM, NULL, 0},
2125 };
2126 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2127
2128 } else {
2129 d_del = calloc(1, sizeof *d_del);
2130 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2131 d = (struct lysp_deviate *)d_del;
2132 struct yin_subelement subelems[5] = {
2133 {YANG_DEFAULT, &d_del->dflts, 0},
2134 {YANG_MUST, &d_del->musts, 0},
2135 {YANG_UNIQUE, &d_del->uniques, 0},
2136 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2137 {YANG_CUSTOM, NULL, 0},
2138 };
2139 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2140 }
2141 LY_CHECK_GOTO(ret, cleanup);
2142
2143 d->mod = dev_mod;
2144 /* insert into siblings */
2145 if (!*deviates) {
2146 *deviates = d;
2147 } else {
2148 for (iter = *deviates; iter->next; iter = iter->next);
2149 iter->next = d;
2150 }
2151
2152 return ret;
2153
2154cleanup:
2155 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002156 return ret;
2157}
2158
David Sedlák992fb7c2019-07-24 16:51:01 +02002159/**
David Sedlák8b754462019-07-25 16:22:13 +02002160 * @brief Parse deviation element.
2161 *
2162 * @param[in,out] ctx YIN parser context for logging and to store current state.
2163 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2164 * @param[in,out] data Data to read from, always moved to currently handled character.
2165 * @param[in] deviations Deviations to add to.
2166 *
2167 * @return LY_ERR values.
2168 */
2169static LY_ERR
2170yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2171 struct lysp_deviation **deviations)
2172{
2173 struct lysp_deviation *dev;
2174
2175 /* create new deviation */
2176 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2177
2178 /* parse argument */
2179 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATE));
2180 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2181 struct yin_subelement subelems[4] = {
2182 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2183 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2184 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2185 {YANG_CUSTOM, NULL, 0},
2186 };
2187 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATE, NULL, &dev->exts);
2188}
2189
2190/**
David Sedlákb4e44562019-07-04 15:42:12 +02002191 * @brief Map keyword type to substatement info.
2192 *
2193 * @param[in] kw Keyword type.
2194 *
2195 * @return correct LYEXT_SUBSTMT information.
2196 */
2197static LYEXT_SUBSTMT
2198kw2lyext_substmt(enum yang_keyword kw)
2199{
2200 switch (kw) {
2201 case YANG_ARGUMENT:
2202 return LYEXT_SUBSTMT_ARGUMENT;
2203 case YANG_BASE:
2204 return LYEXT_SUBSTMT_BASE;
2205 case YANG_BELONGS_TO:
2206 return LYEXT_SUBSTMT_BELONGSTO;
2207 case YANG_CONTACT:
2208 return LYEXT_SUBSTMT_CONTACT;
2209 case YANG_DEFAULT:
2210 return LYEXT_SUBSTMT_DEFAULT;
2211 case YANG_DESCRIPTION:
2212 return LYEXT_SUBSTMT_DESCRIPTION;
2213 case YANG_ERROR_APP_TAG:
2214 return LYEXT_SUBSTMT_ERRTAG;
2215 case YANG_ERROR_MESSAGE:
2216 return LYEXT_SUBSTMT_ERRMSG;
2217 case YANG_KEY:
2218 return LYEXT_SUBSTMT_KEY;
2219 case YANG_NAMESPACE:
2220 return LYEXT_SUBSTMT_NAMESPACE;
2221 case YANG_ORGANIZATION:
2222 return LYEXT_SUBSTMT_ORGANIZATION;
2223 case YANG_PATH:
2224 return LYEXT_SUBSTMT_PATH;
2225 case YANG_PREFIX:
2226 return LYEXT_SUBSTMT_PREFIX;
2227 case YANG_PRESENCE:
2228 return LYEXT_SUBSTMT_PRESENCE;
2229 case YANG_REFERENCE:
2230 return LYEXT_SUBSTMT_REFERENCE;
2231 case YANG_REVISION_DATE:
2232 return LYEXT_SUBSTMT_REVISIONDATE;
2233 case YANG_UNITS:
2234 return LYEXT_SUBSTMT_UNITS;
2235 case YANG_VALUE:
2236 return LYEXT_SUBSTMT_VALUE;
2237 case YANG_YANG_VERSION:
2238 return LYEXT_SUBSTMT_VERSION;
2239 case YANG_MODIFIER:
2240 return LYEXT_SUBSTMT_MODIFIER;
2241 case YANG_REQUIRE_INSTANCE:
2242 return LYEXT_SUBSTMT_REQINSTANCE;
2243 case YANG_YIN_ELEMENT:
2244 return LYEXT_SUBSTMT_YINELEM;
2245 case YANG_CONFIG:
2246 return LYEXT_SUBSTMT_CONFIG;
2247 case YANG_MANDATORY:
2248 return LYEXT_SUBSTMT_MANDATORY;
2249 case YANG_ORDERED_BY:
2250 return LYEXT_SUBSTMT_ORDEREDBY;
2251 case YANG_STATUS:
2252 return LYEXT_SUBSTMT_STATUS;
2253 case YANG_FRACTION_DIGITS:
2254 return LYEXT_SUBSTMT_FRACDIGITS;
2255 case YANG_MAX_ELEMENTS:
2256 return LYEXT_SUBSTMT_MAX;
2257 case YANG_MIN_ELEMENTS:
2258 return LYEXT_SUBSTMT_MIN;
2259 case YANG_POSITION:
2260 return LYEXT_SUBSTMT_POSITION;
2261 case YANG_UNIQUE:
2262 return LYEXT_SUBSTMT_UNIQUE;
2263 case YANG_IF_FEATURE:
2264 return LYEXT_SUBSTMT_IFFEATURE;
2265 default:
2266 return LYEXT_SUBSTMT_SELF;
2267 }
2268}
2269
David Sedlákd6e56892019-07-01 15:40:24 +02002270LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002271yin_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 +02002272 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 +02002273{
2274 LY_ERR ret = LY_SUCCESS;
2275 struct sized_string prefix, name;
David Sedlák8e7bda82019-07-16 17:57:50 +02002276 char *out = NULL;
2277 size_t out_len = 0;
2278 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002279 struct yin_arg_record *attrs = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002280 enum yang_keyword kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002281 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002282 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002283
David Sedlákb0faad82019-07-04 14:28:59 +02002284 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002285
David Sedlákda8ffa32019-07-08 14:17:10 +02002286 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2287 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002288 /* current element has subelements as content */
2289 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002290 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2291 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlákd6e56892019-07-01 15:40:24 +02002292 LY_CHECK_GOTO(ret, cleanup);
2293 if (!name.value) {
2294 /* end of current element reached */
2295 break;
2296 }
David Sedlák1af868e2019-07-17 17:03:14 +02002297 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002298 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc1771b12019-07-10 15:55:46 +02002299 kw = yin_match_keyword(ctx, name.value, name.len, prefix.value, prefix.len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002300
2301 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002302 subelem = get_record(kw, subelem_info_size, subelem_info);
2303 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002304 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2305 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2306 } else {
2307 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
2308 }
David Sedlákd6e56892019-07-01 15:40:24 +02002309 ret = LY_EVALID;
2310 goto cleanup;
2311 }
2312
David Sedlák5f8191e2019-07-08 16:35:52 +02002313 /* TODO check relative order */
2314
David Sedlák4ffcec82019-07-25 15:10:21 +02002315 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002316 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002317 /* subelement uniquenes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002318 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 +02002319 return LY_EVALID;
2320 }
David Sedlák1af868e2019-07-17 17:03:14 +02002321 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002322 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002323 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002324 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002325 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002326 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002327 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002328 if (ctx->mod_version < 2) {
2329 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002330 ret = LY_EVALID;
2331 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002332 }
2333 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002334 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002335 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002336
David Sedlákd6e56892019-07-01 15:40:24 +02002337 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002338 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002339 case YANG_CUSTOM:
David Sedlák1af868e2019-07-17 17:03:14 +02002340 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name.value, prefix.len),
David Sedlák3ffbc522019-07-02 17:49:28 +02002341 namelen2fulllen(name.len, prefix.len),
David Sedlák1af868e2019-07-17 17:03:14 +02002342 kw2lyext_substmt(current_element),
2343 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002344 break;
2345 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002346 case YANG_RPC:
David Sedlák85d0eca2019-07-24 15:15:21 +02002347 ret = yin_parse_action(ctx, attrs, data, (struct action_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002348 break;
2349 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002350 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002351 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002352 break;
2353 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002354 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002355 break;
2356 case YANG_AUGMENT:
David Sedlák992fb7c2019-07-24 16:51:01 +02002357 ret = yin_parse_augment(ctx, attrs, data, (struct augment_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002358 break;
2359 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002360 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002361 type = (struct lysp_type *)subelem->dest;
2362 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002363 Y_PREF_IDENTIF_ARG, exts);
2364 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002365 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002366 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002367 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2368 } else {
2369 LOGINT(ctx->xml_ctx.ctx);
2370 ret = LY_EINT;
2371 }
David Sedlákd6e56892019-07-01 15:40:24 +02002372 break;
2373 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002374 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002375 break;
2376 case YANG_BIT:
David Sedlák07869a52019-07-12 14:28:19 +02002377 case YANG_ENUM:
David Sedlák1af868e2019-07-17 17:03:14 +02002378 ret = yin_parse_enum_bit(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002379 break;
2380 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002381 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002382 break;
2383 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002384 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002385 break;
2386 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002387 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002388 break;
2389 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002390 case YANG_DESCRIPTION:
2391 case YANG_ORGANIZATION:
2392 case YANG_REFERENCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002393 ret = yin_parse_meta_element(ctx, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002394 break;
2395 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002396 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002397 break;
2398 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002399 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2400 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2401 YIN_ARG_VALUE, Y_STR_ARG, exts);
2402 } else {
2403 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2404 YIN_ARG_VALUE, Y_STR_ARG, exts);
2405 }
David Sedlákd6e56892019-07-01 15:40:24 +02002406 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002407 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002408 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002409 break;
2410 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002411 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002412 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002413 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002414 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002415 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002416 break;
2417 case YANG_ERROR_MESSAGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002418 ret = yin_parse_err_msg_element(ctx, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002419 break;
2420 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002421 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002422 break;
2423 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002424 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002425 break;
2426 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002427 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002428 break;
2429 case YANG_GROUPING:
David Sedláke3ce9ef2019-07-23 16:34:30 +02002430 ret = yin_parse_grouping(ctx, attrs, data, (struct grouping_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002431 break;
2432 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002433 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002434 break;
2435 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002436 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2437 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002438 break;
2439 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002440 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002441 break;
2442 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002443 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002444 break;
2445 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002446 case YANG_OUTPUT:
2447 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002448 break;
2449 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002450 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2451 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002452 break;
2453 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002454 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002455 break;
2456 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002457 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002458 break;
2459 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002460 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002461 type->length = calloc(1, sizeof *type->length);
2462 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002463 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002464 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002465 break;
2466 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002467 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002468 break;
2469 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002470 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002471 break;
2472 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002473 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002474 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002475 break;
2476 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002477 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002478 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002479 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002480 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002481 break;
2482 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002483 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002484 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002485 break;
2486 case YANG_NOTIFICATION:
David Sedlák031b9e72019-07-23 15:19:37 +02002487 ret = yin_parse_notification(ctx, attrs, data, (struct notif_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002488 break;
2489 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002490 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002491 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002492 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002493 type = (struct lysp_type *)subelem->dest;
2494 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlák58979872019-07-12 11:42:43 +02002495 YIN_ARG_VALUE, Y_STR_ARG, exts);
2496 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002497 break;
2498 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002499 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002500 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002501 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002502 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002503 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2504 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002505 break;
2506 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002507 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2508 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002509 break;
2510 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002511 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2512 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002513 break;
2514 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002515 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002516 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002517 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002518 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002519 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002520 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002521 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002522 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002523 break;
2524 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002525 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002526 break;
2527 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002528 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002529 break;
2530 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002531 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002532 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002533 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002534 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002535 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002536 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002537 if (current_element == YANG_DEVIATE) {
2538 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2539 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2540 type = *((struct lysp_type **)subelem->dest);
2541 } else {
2542 type = (struct lysp_type *)subelem->dest;
2543 }
David Sedlák374d2b32019-07-17 15:06:55 +02002544 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002545 if (current_element == YANG_TYPE) {
2546 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002547 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002548 type = nested_type;
2549 }
David Sedlák1af868e2019-07-17 17:03:14 +02002550 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002551 break;
2552 case YANG_TYPEDEF:
David Sedlák04e17b22019-07-19 15:29:48 +02002553 ret = yin_parse_typedef(ctx, attrs, data, (struct typedef_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002554 break;
2555 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002556 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002557 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002558 break;
2559 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002560 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002561 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002562 break;
2563 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002564 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002565 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002566 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002567 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002568 break;
2569 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002570 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002571 break;
2572 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002573 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002574 break;
2575 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002576 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002577 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002578 break;
2579 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002580 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002581 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002582 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002583 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002584 FREE_ARRAY(ctx, attrs, free_arg_rec);
2585 attrs = NULL;
2586 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002587 }
2588 } else {
2589 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002590 /* save text content, if text_content isn't set, it's just ignored */
David Sedlák4ffcec82019-07-25 15:10:21 +02002591 /* no resources are allocated in this branch so no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002592 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002593 if (text_content) {
2594 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002595 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002596 if (!*text_content) {
2597 free(out);
2598 return LY_EMEM;
2599 }
2600 } else {
2601 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002602 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002603 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002604 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002605 }
2606 }
2607 }
David Sedlákd6e56892019-07-01 15:40:24 +02002608 /* load closing element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002609 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 +02002610 }
2611 }
David Sedlák8b754462019-07-25 16:22:13 +02002612 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2613 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002614
2615cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002616 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002617 return ret;
2618}
2619
David Sedlák619db942019-07-03 14:47:30 +02002620LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002621yin_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 +02002622 struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +02002623{
David Sedlák3ffbc522019-07-02 17:49:28 +02002624 const char *temp_rev;
David Sedlák968ac342019-07-11 15:17:59 +02002625 struct yin_subelement subelems[1] = {
2626 {YANG_CUSTOM, NULL, 0}
2627 };
David Sedlák81e04022019-04-05 15:05:46 +02002628
David Sedlák292763b2019-07-09 11:10:53 +02002629 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 +02002630 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
2631 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
David Sedlákda63c082019-06-04 13:52:23 +02002632
2633 strcpy(rev, temp_rev);
David Sedlákda8ffa32019-07-08 14:17:10 +02002634 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +02002635
David Sedlákda8ffa32019-07-08 14:17:10 +02002636 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002637}
David Sedlák00250342019-06-21 14:19:39 +02002638
David Sedláke1a30302019-07-10 13:49:38 +02002639/**
2640 * @brief Parse config element.
2641 *
2642 * @param[in] ctx Yin parser context for logging and to store current state.
2643 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
2644 * @param[in,out] data Data to read from, always moved to currently handled character.
2645 * @param[in,out] flags Flags to add to.
2646 * @param[in,out] exts Extension instances to add to.
2647 *
2648 * @return LY_ERR values.
2649 */
2650static LY_ERR
2651yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2652 struct lysp_ext_instance **exts)
2653{
2654 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002655 struct yin_subelement subelems[1] = {
2656 {YANG_CUSTOM, NULL, 0}
2657 };
David Sedláke1a30302019-07-10 13:49:38 +02002658
David Sedlák1f90d252019-07-10 17:09:32 +02002659 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 +02002660 if (strcmp(temp_val, "true") == 0) {
2661 *flags |= LYS_CONFIG_W;
2662 } else if (strcmp(temp_val, "false") == 0) {
2663 *flags |= LYS_CONFIG_R;
2664 } else {
2665 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "config");
2666 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2667 return LY_EVALID;
2668 }
2669 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2670
2671 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
2672}
2673
David Sedlák3ffbc522019-07-02 17:49:28 +02002674LY_ERR
David Sedlák92147b02019-07-09 14:01:01 +02002675yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
2676 struct lysp_ext_instance **exts)
2677{
2678 const char *temp_version = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002679 struct yin_subelement subelems[1] = {
2680 {YANG_CUSTOM, NULL, 0}
2681 };
David Sedlák92147b02019-07-09 14:01:01 +02002682
David Sedlák1f90d252019-07-10 17:09:32 +02002683 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 +02002684 if (strcmp(temp_version, "1.0") == 0) {
2685 *version = LYS_VERSION_1_0;
2686 } else if (strcmp(temp_version, "1.1") == 0) {
2687 *version = LYS_VERSION_1_1;
2688 } else {
2689 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "yang-version");
2690 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2691 return LY_EVALID;
2692 }
2693 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2694 ctx->mod_version = *version;
2695
2696 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
2697}
2698
2699LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02002700yin_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 +01002701{
David Sedlák736fd0d2019-02-15 16:06:31 +01002702 struct lysp_import *imp;
David Sedlák00250342019-06-21 14:19:39 +02002703 /* allocate new element in sized array for import */
David Sedlák298ff6d2019-07-26 14:29:03 +02002704 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02002705
David Sedlák968ac342019-07-11 15:17:59 +02002706 struct yin_subelement subelems[5] = {
2707 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2708 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2709 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2710 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2711 {YANG_CUSTOM, NULL, 0}
2712 };
David Sedlák736fd0d2019-02-15 16:06:31 +01002713
David Sedlák92147b02019-07-09 14:01:01 +02002714 /* parse import attributes */
David Sedlák292763b2019-07-09 11:10:53 +02002715 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 +02002716 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
David Sedlák619db942019-07-03 14:47:30 +02002717 /* check prefix validity */
David Sedlák298ff6d2019-07-26 14:29:03 +02002718 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 +02002719
David Sedlák298ff6d2019-07-26 14:29:03 +02002720 return LY_SUCCESS;
David Sedlák736fd0d2019-02-15 16:06:31 +01002721}
2722
David Sedlák11900c82019-06-18 16:29:12 +02002723LY_ERR
David Sedlák1fdb2522019-07-09 16:22:57 +02002724yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2725 struct lysp_ext_instance **exts)
2726{
2727 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002728 struct yin_subelement subelems[1] = {
2729 {YANG_CUSTOM, NULL, 0}
2730 };
David Sedlák1fdb2522019-07-09 16:22:57 +02002731
David Sedlák1f90d252019-07-10 17:09:32 +02002732 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 +02002733 if (strcmp(temp_val, "true") == 0) {
2734 *flags |= LYS_MAND_TRUE;
2735 } else if (strcmp(temp_val, "false") == 0) {
2736 *flags |= LYS_MAND_FALSE;
2737 } else {
2738 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "mandatory");
2739 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2740 return LY_EVALID;
2741 }
2742 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2743
2744 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
2745}
2746
2747LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002748yin_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 +02002749 struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +02002750{
David Sedlák3ffbc522019-07-02 17:49:28 +02002751 const char *value = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002752 struct yin_subelement subelems[1] = {
2753 {YANG_CUSTOM, NULL, 0}
2754 };
David Sedlák3ffbc522019-07-02 17:49:28 +02002755
David Sedlák292763b2019-07-09 11:10:53 +02002756 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 +02002757 if (strcmp(value, "current") == 0) {
2758 *flags |= LYS_STATUS_CURR;
2759 } else if (strcmp(value, "deprecated") == 0) {
2760 *flags |= LYS_STATUS_DEPRC;
2761 } else if (strcmp(value, "obsolete") == 0) {
2762 *flags |= LYS_STATUS_OBSLT;
2763 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002764 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "status");
2765 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002766 return LY_EVALID;
2767 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002768 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002769
David Sedlákda8ffa32019-07-08 14:17:10 +02002770 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
David Sedlák11900c82019-06-18 16:29:12 +02002771}
2772
David Sedlák11900c82019-06-18 16:29:12 +02002773LY_ERR
David Sedlák32eee7b2019-07-09 12:38:44 +02002774yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
2775{
2776 struct lysp_when *when;
2777 when = calloc(1, sizeof *when);
2778 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1f90d252019-07-10 17:09:32 +02002779 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
David Sedlák32eee7b2019-07-09 12:38:44 +02002780 *when_p = when;
David Sedlák968ac342019-07-11 15:17:59 +02002781 struct yin_subelement subelems[3] = {
2782 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2783 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2784 {YANG_CUSTOM, NULL, 0}
2785 };
David Sedlák32eee7b2019-07-09 12:38:44 +02002786
2787 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
2788}
2789
2790LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002791yin_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 +02002792 uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák2721d3d2019-06-21 15:37:41 +02002793{
David Sedlák3ffbc522019-07-02 17:49:28 +02002794 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002795 struct yin_subelement subelems[1] = {
2796 {YANG_CUSTOM, NULL, 0}
2797 };
David Sedlák2721d3d2019-06-21 15:37:41 +02002798
David Sedlák1f90d252019-07-10 17:09:32 +02002799 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 +02002800 if (strcmp(temp_val, "true") == 0) {
2801 *flags |= LYS_YINELEM_TRUE;
2802 } else if (strcmp(temp_val, "false") == 0) {
2803 *flags |= LYS_YINELEM_FALSE;
2804 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002805 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
2806 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002807 return LY_EVALID;
2808 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002809 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002810
David Sedlákda8ffa32019-07-08 14:17:10 +02002811 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
David Sedlák2721d3d2019-06-21 15:37:41 +02002812}
2813
2814LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002815yin_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 +02002816 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002817{
2818 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002819 char *out;
2820 const char *name, *prefix;
2821 size_t out_len, prefix_len, name_len;
2822 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002823 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02002824 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
2825 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002826
David Sedlákda8ffa32019-07-08 14:17:10 +02002827 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002828
2829 e->yin = 0;
2830 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02002831 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02002832 e->insubstmt = subelem;
2833 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002834 e->yin |= LYS_YIN;
2835
David Sedlákb1a78352019-06-28 16:16:29 +02002836 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02002837 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02002838 if (!iter->prefix) {
2839 new_subelem = calloc(1, sizeof(*new_subelem));
2840 if (!e->child) {
2841 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002842 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02002843 last_subelem->next = new_subelem;
2844 }
2845 last_subelem = new_subelem;
2846
2847 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002848 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
2849 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002850 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002851 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
2852 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002853 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002854 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
2855 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002856 }
2857 }
2858 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02002859
David Sedlákf250ecf2019-07-01 11:02:05 +02002860 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002861 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2862 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002863 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002864 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2865 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02002866 if (!name) {
2867 /* end of extension instance reached */
2868 break;
2869 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002870 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02002871 if (!e->child) {
2872 e->child = new_subelem;
2873 } else {
2874 last_subelem->next = new_subelem;
2875 }
2876 last_subelem = new_subelem;
2877 }
David Sedlák555c7202019-07-04 12:14:12 +02002878 } else {
2879 /* save text content */
2880 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002881 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02002882 if (!e->argument) {
2883 free(out);
2884 return LY_EMEM;
2885 }
2886 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002887 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02002888 LY_CHECK_RET(!e->argument, LY_EMEM);
2889 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002890 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02002891 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02002892 }
David Sedlákb1a78352019-06-28 16:16:29 +02002893 }
2894
2895 return LY_SUCCESS;
2896}
2897
2898LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02002899yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
2900 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02002901{
2902 LY_ERR ret = LY_SUCCESS;
2903 const char *temp_prefix, *temp_name;
2904 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02002905 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02002906 int dynamic;
2907 struct yin_arg_record *subelem_args = NULL;
2908 struct lysp_stmt *last = NULL, *new = NULL;
2909
2910 /* allocate new structure for element */
2911 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02002912 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
2913 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002914
2915 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02002916 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002917 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02002918 /* add new element to linked-list */
2919 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02002920 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02002921 if (!(*element)->child) {
2922 /* save first */
2923 (*element)->child = new;
2924 } else {
2925 last->next = new;
2926 }
2927 last = new;
2928
2929 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002930 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 +02002931 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002932 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002933 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002934 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
2935 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002936 /* attributes with prefix are ignored */
2937 if (!temp_prefix) {
2938 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002939 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02002940 if (!last->arg) {
2941 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002942 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02002943 ret = LY_EMEM;
2944 goto err;
2945 }
2946 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002947 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2948 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002949 }
2950 }
2951 }
2952
2953 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002954 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002955 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002956 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02002957 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002958 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 +02002959 LY_CHECK_GOTO(ret, err);
2960 if (!name) {
2961 /* end of element reached */
2962 break;
2963 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002964 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02002965 LY_CHECK_GOTO(ret, err);
2966 last = last->next;
2967 }
2968 } else {
2969 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02002970 if (out_len != 0) {
2971 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002972 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02002973 if (!(*element)->arg) {
2974 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002975 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02002976 ret = LY_EMEM;
2977 goto err;
2978 }
2979 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002980 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2981 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002982 }
David Sedlákb1a78352019-06-28 16:16:29 +02002983 }
2984 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02002985 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 +02002986 LY_CHECK_GOTO(ret, err);
2987 }
2988
David Sedlákda8ffa32019-07-08 14:17:10 +02002989 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02002990 return LY_SUCCESS;
2991
2992err:
David Sedlákda8ffa32019-07-08 14:17:10 +02002993 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002994 return ret;
2995}
2996
2997LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002998yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +02002999 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlák9494eb22019-06-21 16:06:53 +02003000{
David Sedlák968ac342019-07-11 15:17:59 +02003001 struct yin_subelement subelems[2] = {
3002 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
3003 {YANG_CUSTOM, NULL, 0}
3004 };
David Sedlák9494eb22019-06-21 16:06:53 +02003005
David Sedlák292763b2019-07-09 11:10:53 +02003006 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 +02003007
David Sedlákda8ffa32019-07-08 14:17:10 +02003008 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
David Sedlák9494eb22019-06-21 16:06:53 +02003009}
3010
3011LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003012yin_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 +02003013{
David Sedlák11900c82019-06-18 16:29:12 +02003014 struct lysp_ext *ex;
David Sedlákda8ffa32019-07-08 14:17:10 +02003015 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
David Sedlák292763b2019-07-09 11:10:53 +02003016 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 +02003017
David Sedlák3ffbc522019-07-02 17:49:28 +02003018 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
David Sedlák968ac342019-07-11 15:17:59 +02003019 struct yin_subelement subelems[5] = {
3020 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
3021 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
3022 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
3023 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
3024 {YANG_CUSTOM, NULL, 0}
3025 };
David Sedlák11900c82019-06-18 16:29:12 +02003026
David Sedlákda8ffa32019-07-08 14:17:10 +02003027 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
David Sedlák11900c82019-06-18 16:29:12 +02003028}
3029
David Sedlák4f03b932019-07-26 13:01:47 +02003030LY_ERR
3031yin_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 +02003032{
David Sedlák4f03b932019-07-26 13:01:47 +02003033 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3034 struct tree_node_meta node_meta = {NULL, &mod->data};
3035 struct augment_meta aug_meta = {NULL, &mod->augments};
3036 struct grouping_meta grp_meta = {NULL, &mod->groupings};
3037 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
3038 struct notif_meta notif_meta = {NULL, &mod->notifs};
3039 struct action_meta act_meta = {NULL, &mod->rpcs};
3040 struct typedef_meta tpdf_meta = {NULL, &mod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02003041 struct import_meta imp_meta = {mod->mod->prefix, &mod->imports};
David Sedlák4f03b932019-07-26 13:01:47 +02003042 struct yin_subelement subelems[28] = {
3043 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3044 {YANG_ANYXML, &node_meta, 0},
3045 {YANG_AUGMENT, &aug_meta, 0},
3046 {YANG_CHOICE, &node_meta, 0},
3047 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
3048 {YANG_CONTAINER, &node_meta, 0},
3049 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
3050 {YANG_DEVIATION, &mod->deviations, 0},
3051 {YANG_EXTENSION, &mod->extensions, 0},
3052 {YANG_FEATURE, &mod->features, 0},
3053 {YANG_GROUPING, &grp_meta, 0},
3054 {YANG_IDENTITY, &mod->identities, 0},
David Sedlák298ff6d2019-07-26 14:29:03 +02003055 {YANG_IMPORT, &imp_meta, 0},
David Sedlák4f03b932019-07-26 13:01:47 +02003056 {YANG_INCLUDE, &inc_meta, 0},
3057 {YANG_LEAF, &node_meta, 0},
3058 {YANG_LEAF_LIST, &node_meta, 0},
3059 {YANG_LIST, &node_meta, 0},
3060 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3061 {YANG_NOTIFICATION, &notif_meta, 0},
3062 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3063 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3064 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3065 {YANG_REVISION, &mod->revs, 0},
3066 {YANG_RPC, &act_meta, 0},
3067 {YANG_TYPEDEF, &tpdf_meta, 0},
3068 {YANG_USES, &node_meta, 0},
3069 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003070 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003071 };
David Sedlák3b4db242018-10-19 16:11:01 +02003072
David Sedlák4f03b932019-07-26 13:01:47 +02003073 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003074}
3075
3076LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003077yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3078{
3079 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3080 struct tree_node_meta node_meta = {NULL, &submod->data};
3081 struct augment_meta aug_meta = {NULL, &submod->augments};
3082 struct grouping_meta grp_meta = {NULL, &submod->groupings};
3083 struct include_meta inc_meta = {submod->name, &submod->includes};
3084 struct notif_meta notif_meta = {NULL, &submod->notifs};
3085 struct action_meta act_meta = {NULL, &submod->rpcs};
3086 struct typedef_meta tpdf_meta = {NULL, &submod->typedefs};
3087 struct import_meta imp_meta = {submod->prefix, &submod->imports};
3088 struct yin_subelement subelems[27] = {
3089 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3090 {YANG_ANYXML, &node_meta, 0},
3091 {YANG_AUGMENT, &aug_meta, 0},
3092 {YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3093 {YANG_CHOICE, &node_meta, 0},
3094 {YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE},
3095 {YANG_CONTAINER, &node_meta, 0},
3096 {YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE},
3097 {YANG_DEVIATION, &submod->deviations, 0},
3098 {YANG_EXTENSION, &submod->extensions, 0},
3099 {YANG_FEATURE, &submod->features, 0},
3100 {YANG_GROUPING, &grp_meta, 0},
3101 {YANG_IDENTITY, &submod->identities, 0},
3102 {YANG_IMPORT, &imp_meta, 0},
3103 {YANG_INCLUDE, &inc_meta, 0},
3104 {YANG_LEAF, &node_meta, 0},
3105 {YANG_LEAF_LIST, &node_meta, 0},
3106 {YANG_LIST, &node_meta, 0},
3107 {YANG_NOTIFICATION, &notif_meta, 0},
3108 {YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE},
3109 {YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE},
3110 {YANG_REVISION, &submod->revs, 0},
3111 {YANG_RPC, &act_meta, 0},
3112 {YANG_TYPEDEF, &tpdf_meta, 0},
3113 {YANG_USES, &node_meta, 0},
3114 {YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3115 {YANG_CUSTOM, NULL, 0}
3116 };
3117
3118 return yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3119}
3120
3121LY_ERR
David Sedlák8985a142019-07-31 16:43:06 +02003122yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, const char *data, struct lysp_submodule **submod)
3123{
3124 enum yang_keyword kw = YANG_NONE;
3125 LY_ERR ret = LY_SUCCESS;
3126 const char *prefix, *name;
3127 size_t prefix_len, name_len;
3128 struct yin_arg_record *attrs = NULL;
3129 struct lysp_submodule *mod_p = NULL;
3130
3131 /* create context */
3132 *yin_ctx = calloc(1, sizeof **yin_ctx);
3133 LY_CHECK_ERR_RET(!yin_ctx, LOGMEM(ctx), LY_EMEM);
3134 (*yin_ctx)->xml_ctx.ctx = ctx;
3135 (*yin_ctx)->xml_ctx.line = 1;
3136
3137 /* check submodule */
3138 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3139 LY_CHECK_GOTO(ret, cleanup);
3140 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3141 LY_CHECK_GOTO(ret, cleanup);
3142 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3143
3144 if (kw == YANG_MODULE) {
3145 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3146 ret = LY_EINVAL;
3147 goto cleanup;
3148 } else if (kw != YANG_SUBMODULE) {
3149 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
3150 ly_stmt2str(kw));
3151 ret = LY_EVALID;
3152 goto cleanup;
3153 }
3154
3155 mod_p = calloc(1, sizeof *mod_p);
3156 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3157 mod_p->parsing = 1;
3158
3159 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3160 LY_CHECK_GOTO(ret, cleanup);
3161
David Sedlák6d781b62019-08-02 15:22:52 +02003162 name = NULL;
3163 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3164 const char *temp_data = data;
3165 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3166 data = temp_data;
3167 }
3168 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3169 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
3170 15, data, strlen(data) > 15 ? "..." : "");
3171 ret = LY_EVALID;
3172 goto cleanup;
3173 }
3174
David Sedlák8985a142019-07-31 16:43:06 +02003175 mod_p->parsing = 0;
3176 *submod = mod_p;
3177
3178cleanup:
3179 if (ret) {
3180 lysp_submodule_free(ctx, mod_p);
3181 }
3182
3183 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3184 return ret;
3185}
3186
3187LY_ERR
3188yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003189{
David Sedláke4889912018-11-02 09:52:40 +01003190 LY_ERR ret = LY_SUCCESS;
3191 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003192 struct lysp_module *mod_p = NULL;
3193 const char *prefix, *name;
3194 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003195 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003196
David Sedlák8985a142019-07-31 16:43:06 +02003197 /* create context */
3198 *yin_ctx = calloc(1, sizeof **yin_ctx);
3199 LY_CHECK_ERR_RET(!yin_ctx, LOGMEM(mod->ctx), LY_EMEM);
3200 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3201 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003202
David Sedlák8985a142019-07-31 16:43:06 +02003203 /* check module */
3204 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003205 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003206 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003207 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003208 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003209 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003210 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 +01003211 ret = LY_EINVAL;
3212 goto cleanup;
3213 } else if (kw != YANG_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003214 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 +02003215 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003216 ret = LY_EVALID;
3217 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003218 }
3219
David Sedlák3017da42019-02-15 09:48:04 +01003220 /* allocate module */
3221 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003222 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003223 mod_p->mod = mod;
3224 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003225
David Sedlák00250342019-06-21 14:19:39 +02003226 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003227 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003228 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003229
David Sedlák6d781b62019-08-02 15:22:52 +02003230 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3231 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3232 }
3233 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3234 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
3235 15, data, strlen(data) > 15 ? "..." : "");
3236
3237 ret = LY_EVALID;
3238 goto cleanup;
3239 }
3240
David Sedlák3017da42019-02-15 09:48:04 +01003241 mod_p->parsing = 0;
3242 mod->parsed = mod_p;
3243
3244cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003245 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003246 lysp_module_free(mod_p);
3247 }
David Sedlák8985a142019-07-31 16:43:06 +02003248 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003249 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003250}