blob: 44537dd817df205a8a603aa124134f79d7aad085 [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.
35 * @param ns Namespace URI to check.
36 *
37 * @return true if ns equals YIN_NS_URI false otherwise.
38 */
39#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
40
David Sedláke1a30302019-07-10 13:49:38 +020041static LY_ERR
42yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
43 struct lysp_ext_instance **exts);
44
David Sedlákf6251182019-06-06 10:22:13 +020045const char *const yin_attr_list[] = {
46 [YIN_ARG_NAME] = "name",
47 [YIN_ARG_TARGET_NODE] = "target-node",
48 [YIN_ARG_MODULE] = "module",
49 [YIN_ARG_VALUE] = "value",
50 [YIN_ARG_TEXT] = "text",
51 [YIN_ARG_CONDITION] = "condition",
52 [YIN_ARG_URI] = "uri",
53 [YIN_ARG_DATE] = "date",
54 [YIN_ARG_TAG] = "tag",
David Sedlákf6251182019-06-06 10:22:13 +020055};
56
David Sedlák1bccdfa2019-06-17 15:55:27 +020057enum yang_keyword
David Sedlákc1771b12019-07-10 15:55:46 +020058yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
59 const char *prefix, size_t prefix_len, enum yang_keyword parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020060{
David Sedlák8f7a1172019-06-20 14:42:18 +020061 const char *start = NULL;
62 enum yang_keyword kw = YANG_NONE;
63 const struct lyxml_ns *ns = NULL;
64
65 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020066 return YANG_NONE;
67 }
68
David Sedlákda8ffa32019-07-08 14:17:10 +020069 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020070 if (ns) {
71 if (!IS_YIN_NS(ns->uri)) {
72 return YANG_CUSTOM;
73 }
74 } else {
75 /* elements without namespace are automatically unknown */
76 return YANG_NONE;
77 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020078
David Sedlák8f7a1172019-06-20 14:42:18 +020079 start = name;
80 kw = lysp_match_kw(NULL, &name);
81
82 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020083 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
84 if (kw == YANG_VALUE && parrent == YANG_ERROR_MESSAGE) {
85 return YIN_VALUE;
86 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020087 return kw;
88 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020089 if (strncmp(start, "text", name_len) == 0) {
90 return YIN_TEXT;
91 } else if (strncmp(start, "value", name_len) == 0) {
92 return YIN_VALUE;
93 } else {
94 return YANG_NONE;
95 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020096 }
97}
98
David Sedlák872c7b42018-10-26 13:15:20 +020099enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +0200100yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200101{
David Sedláka7406952019-04-05 10:33:07 +0200102 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200103 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200104 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200105
David Sedlák94de2aa2019-02-15 12:42:11 +0100106#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
107#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100108#define IF_ARG_PREFIX_END }
109
David Sedlák1c8b2702019-02-22 11:03:02 +0100110 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100111 case 'c':
112 already_read += 1;
113 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200114 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200115
David Sedlák94de2aa2019-02-15 12:42:11 +0100116 case 'd':
117 already_read += 1;
118 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200119 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200120
David Sedlák94de2aa2019-02-15 12:42:11 +0100121 case 'm':
122 already_read += 1;
123 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200124 break;
125
David Sedlák94de2aa2019-02-15 12:42:11 +0100126 case 'n':
127 already_read += 1;
128 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200129 break;
130
David Sedlák94de2aa2019-02-15 12:42:11 +0100131 case 't':
132 already_read += 1;
133 IF_ARG_PREFIX("a", 1)
134 IF_ARG("g", 1, YIN_ARG_TAG)
135 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
136 IF_ARG_PREFIX_END
137 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200138 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200139
David Sedlák94de2aa2019-02-15 12:42:11 +0100140 case 'u':
141 already_read += 1;
142 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200143 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200144
David Sedlák94de2aa2019-02-15 12:42:11 +0100145 case 'v':
146 already_read += 1;
147 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200148 break;
149 }
150
David Sedlákc10e7902018-12-17 02:17:59 +0100151 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200152 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200153 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200154 }
155
David Sedlák18730132019-03-15 15:51:34 +0100156#undef IF_ARG
157#undef IF_ARG_PREFIX
158#undef IF_ARG_PREFIX_END
159
David Sedlák872c7b42018-10-26 13:15:20 +0200160 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200161}
162
David Sedlák4f03b932019-07-26 13:01:47 +0200163void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200164 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200165 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200166 free(record->content);
167 }
168}
169
David Sedlák8f7a1172019-06-20 14:42:18 +0200170LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200171yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200172{
173 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200174 struct yin_arg_record *argument_record = NULL;
David Sedlák555c7202019-07-04 12:14:12 +0200175 struct sized_string prefix, name;
David Sedláka7406952019-04-05 10:33:07 +0200176
David Sedlák555c7202019-07-04 12:14:12 +0200177 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200178 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
179 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlák00250342019-06-21 14:19:39 +0200180 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200181
David Sedlákda8ffa32019-07-08 14:17:10 +0200182 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
183 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlák555c7202019-07-04 12:14:12 +0200184 argument_record->name = name.value;
185 argument_record->name_len = name.len;
186 argument_record->prefix = prefix.value;
187 argument_record->prefix_len = prefix.len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200188 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200189 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200190 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200191 }
192 }
193
David Sedlák8f7a1172019-06-20 14:42:18 +0200194cleanup:
195 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200196 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200197 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200198 }
199 return ret;
200}
201
David Sedlák4a650532019-07-10 11:55:18 +0200202LY_ERR
203yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
204{
205 int prefix = 0;
206 unsigned int c;
207 size_t utf8_char_len;
208 size_t already_read = 0;
209 while (already_read < len) {
210 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
211 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
212 already_read += utf8_char_len;
213 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
214
215 switch (val_type) {
216 case Y_IDENTIF_ARG:
217 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
218 break;
219 case Y_PREF_IDENTIF_ARG:
220 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
221 break;
222 case Y_STR_ARG:
223 case Y_MAYBE_STR_ARG:
224 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
225 break;
226 }
227 }
228
229 return LY_SUCCESS;
230}
231
David Sedlákb4e44562019-07-04 15:42:12 +0200232/**
233 * @brief Parse yin argument.
234 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200235 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200236 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200237 * @param[in,out] data Data to read from.
David Sedlák4a650532019-07-10 11:55:18 +0200238 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
239 * special argument).
David Sedlákb4e44562019-07-04 15:42:12 +0200240 * @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 +0200241 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200242 * @param[in] current_element Identification of current element, used for logging.
243 *
244 * @return LY_ERR values.
245 */
246static LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +0200247yin_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 +0200248 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200249{
David Sedlák8f7a1172019-06-20 14:42:18 +0200250 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
251 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200252 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200253
David Sedlák1bccdfa2019-06-17 15:55:27 +0200254 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200255 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200256 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
257 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200258 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200259 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200260 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200261 } else if (arg == arg_type) {
David Sedlák292763b2019-07-09 11:10:53 +0200262 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Duplicit definition of %s attribute in %s element",
263 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200264 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200265 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200266 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200267 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200268 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200269 /* string is no longer supposed to be freed when the sized array is freed */
270 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200271 } else {
David Sedlák99295322019-07-17 11:34:18 +0200272 if (iter->content_len == 0) {
273 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
274 } else {
275 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
276 LY_CHECK_RET(!(*arg_val), LY_EMEM);
277 }
David Sedlák57715b12019-06-17 13:05:22 +0200278 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200279 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +0200280 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 +0200281 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200282 }
283 }
284 }
285
David Sedlák292763b2019-07-09 11:10:53 +0200286 /* anything else than Y_MAYBE_STR_ARG is mandatory */
287 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200288 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 +0200289 return LY_EVALID;
290 }
291
292 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200293}
294
David Sedlákd6e56892019-07-01 15:40:24 +0200295/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200296 * @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 +0200297 *
298 * @param[in] type Type of wanted record.
299 * @param[in] array_size Size of array.
300 * @param[in] array Searched array.
301 *
302 * @return Pointer to desired record on success, NULL if element is not in the array.
303 */
David Sedlákb4e44562019-07-04 15:42:12 +0200304static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200305get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200306{
David Sedlákb0faad82019-07-04 14:28:59 +0200307 signed char left = 0, right = array_size - 1, middle;
308
309 while (left <= right) {
310 middle = left + (right - left) / 2;
311
312 if (array[middle].type == type) {
313 return &array[middle];
314 }
315
316 if (array[middle].type < type) {
317 left = middle + 1;
318 } else {
319 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200320 }
321 }
322
323 return NULL;
324}
325
David Sedlákbba38e52019-07-09 15:20:01 +0200326/**
327 * @brief Helper function to check mandatory constraint of subelement.
328 *
329 * @param[in,out] ctx Yin parser context for logging and to store current state.
330 * @param[in] subelem_info Array of information about subelements.
331 * @param[in] subelem_info_size Size of subelem_info array.
332 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
333 *
334 * @return LY_ERR values.
335 */
336static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200337yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200338 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200339{
David Sedlákb0faad82019-07-04 14:28:59 +0200340 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200341 /* 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 +0200342 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200343 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 +0200344 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200345 return LY_EVALID;
346 }
347 }
348
349 return LY_SUCCESS;
350}
351
David Sedlákbba38e52019-07-09 15:20:01 +0200352/**
353 * @brief Helper function to check "first" constraint of subelement.
354 *
355 * @param[in,out] ctx Yin parser context for logging and to store current state.
356 * @param[in] subelem_info Array of information about subelements.
357 * @param[in] subelem_info_size Size of subelem_info array.
358 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
359 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement.
360 *
361 * @return LY_ERR values.
362 */
363static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200364yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200365 signed char subelem_info_size, enum yang_keyword current_element,
366 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200367{
David Sedlákb0faad82019-07-04 14:28:59 +0200368 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200369 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200370 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 +0200371 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200372 return LY_EVALID;
373 }
374 }
375
376 return LY_SUCCESS;
377}
378
David Sedlákbba38e52019-07-09 15:20:01 +0200379/**
380 * @brief Helper function to check if array of information about subelements is in ascending order.
381 *
382 * @param[in] subelem_info Array of information about subelements.
383 * @param[in] subelem_info_size Size of subelem_info array.
384 *
385 * @return True iff subelem_info array is in ascending order, False otherwise.
386 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200387#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200388static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200389is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
390{
David Sedlák292763b2019-07-09 11:10:53 +0200391 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200392
393 for (signed char i = 0; i < subelem_info_size; ++i) {
394 if (subelem_info[i].type <= current) {
395 return false;
396 }
397 current = subelem_info[i].type;
398 }
399
400 return true;
401}
David Sedlák5545f5d2019-07-11 11:55:16 +0200402#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200403
David Sedlákd6e56892019-07-01 15:40:24 +0200404/**
David Sedlákb4e44562019-07-04 15:42:12 +0200405 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
406 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200407 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200408 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200409 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200410 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200411 * @param[in] kw Type of current element.
412 * @param[out] value Where value of attribute should be stored.
413 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200414 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákda8ffa32019-07-08 14:17:10 +0200415 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200416 *
David Sedlákd6e56892019-07-01 15:40:24 +0200417 * @return LY_ERR values.
418 */
David Sedlákb4e44562019-07-04 15:42:12 +0200419static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200420yin_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 +0200421 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 +0200422{
David Sedlák1f90d252019-07-10 17:09:32 +0200423 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200424 struct yin_subelement subelems[1] = {
425 {YANG_CUSTOM, NULL, 0}
426 };
David Sedlákb4e44562019-07-04 15:42:12 +0200427
David Sedlákda8ffa32019-07-08 14:17:10 +0200428 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200429}
430
431/**
David Sedlákd3983112019-07-12 11:20:56 +0200432 * @brief Parse pattern element.
433 *
434 * @param[in,out] ctx Yin parser context for logging and to store current state.
435 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
436 * @param[in,out] data Data to read from, always moved to currently handled character.
437 * @param[in,out] patterns Restrictions to add to.
438 *
439 * @return LY_ERR values.
440 */
441static LY_ERR
442yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
443 struct lysp_type *type)
444{
445 const char *real_value = NULL;
446 char *saved_value = NULL;
447 struct lysp_restr *restr;
448
449 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
450 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
451 size_t len = strlen(real_value);
452
453 saved_value = malloc(len + 2);
454 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
455 memmove(saved_value + 1, real_value, len);
456 FREE_STRING(ctx->xml_ctx.ctx, real_value);
457 saved_value[0] = 0x06;
458 saved_value[len + 1] = '\0';
459 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
460 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
461 type->flags |= LYS_SET_PATTERN;
462
463 struct yin_subelement subelems[6] = {
464 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
465 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
466 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
467 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
468 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
469 {YANG_CUSTOM, NULL, 0}
470 };
471 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
472}
473
David Sedlákf75d55e2019-07-12 16:52:50 +0200474static LY_ERR
475yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
476 struct lysp_type *type)
477{
478 const char *temp_val = NULL;
479 char *ptr;
480 unsigned long int num;
481
482 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
483
484 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
485 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
486 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
487 return LY_EVALID;
488 }
489
490 errno = 0;
491 num = strtoul(temp_val, &ptr, 10);
492 if (*ptr != '\0') {
493 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
494 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
495 return LY_EVALID;
496 }
497 if ((errno == ERANGE) || (num > 18)) {
498 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
499 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
500 return LY_EVALID;
501 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200502 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200503 type->fraction_digits = num;
504 type->flags |= LYS_SET_FRDIGITS;
505 struct yin_subelement subelems[1] = {
506 {YANG_CUSTOM, &index, 0}
507 };
508 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
509}
510
David Sedlák07869a52019-07-12 14:28:19 +0200511/**
512 * @brief Parse enum or bit element.
513 *
514 * @param[in,out] ctx YIN parser context for logging and to store current state.
515 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
516 * @param[in,out] data Data to read from, always moved to currently handled character.
517 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
518 * @param[in,out] enums Enums or bits to add to.
519 *
520 * @return LY_ERR values.
521 */
David Sedlákca36c422019-07-12 12:47:55 +0200522static LY_ERR
David Sedlák07869a52019-07-12 14:28:19 +0200523yin_parse_enum_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
524 enum yang_keyword enum_kw, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200525{
David Sedlák07869a52019-07-12 14:28:19 +0200526 assert(enum_kw == YANG_BIT || enum_kw == YANG_ENUM);
527 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200528 struct lysp_type_enum **enums;
529
530 if (enum_kw == YANG_BIT) {
531 enums = &type->bits;
532 } else {
533 enums = &type->enums;
534 }
535
536 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *enums, en, LY_EMEM);
David Sedlák07869a52019-07-12 14:28:19 +0200537 type->flags |= (enum_kw == YANG_ENUM) ? LYS_SET_ENUM : LYS_SET_BIT;
David Sedlák1e696782019-07-17 15:06:07 +0200538 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 +0200539 if (enum_kw == YANG_ENUM) {
540 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 +0200541 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
David Sedlák07869a52019-07-12 14:28:19 +0200542 }
David Sedlák1e696782019-07-17 15:06:07 +0200543 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, *enums, name, ly_stmt2str(enum_kw), en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200544
545 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200546 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
547 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200548 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
549 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák32488102019-07-15 17:44:10 +0200550 {(enum_kw == YANG_ENUM) ? YANG_VALUE : YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200551 {YANG_CUSTOM, NULL, 0}
552 };
David Sedlák07869a52019-07-12 14:28:19 +0200553 return yin_parse_content(ctx, subelems, 6, data, enum_kw, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200554}
555
David Sedlákd3983112019-07-12 11:20:56 +0200556/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200557 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
558 * more instances, such as base or if-feature.
559 *
560 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200561 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200562 * @param[in,out] data Data to read from, always moved to currently handled character.
563 * @param[in] kw Type of current element.
564 * @param[out] values Parsed values to add to.
565 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200566 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200567 * @param[in,out] exts Extension instance to add to.
568 *
569 * @return LY_ERR values.
570 */
571static LY_ERR
572yin_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 +0200573 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 +0200574{
575 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200576 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200577 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200578 struct yin_subelement subelems[1] = {
579 {YANG_CUSTOM, &index, 0}
580 };
581
David Sedlák1f90d252019-07-10 17:09:32 +0200582 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200583
584 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
585}
586
587/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200588 * @brief Parse require instance element.
589 *
590 * @param[in,out] ctx Yin parser context for logging and to store current state.
591 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
592 * @param[in,out] data Data to read from, always moved to currently handled character.
593 * @prama[out] type Type structure to store value, flag and extensions.
594 *
595 * @return LY_ERR values.
596 */
597static LY_ERR
598yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
599 const char **data, struct lysp_type *type)
600{
601 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200602 struct yin_subelement subelems[1] = {
603 {YANG_CUSTOM, NULL, 0}
604 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200605
606 type->flags |= LYS_SET_REQINST;
607 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
608 if (strcmp(temp_val, "true") == 0) {
609 type->require_instance = 1;
610 } else if (strcmp(temp_val, "false") != 0) {
611 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "require-instance");
612 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
613 return LY_EVALID;
614 }
615 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
616
617 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
618}
619
620/**
David Sedlákce77bf52019-07-11 16:59:31 +0200621 * @brief Parse modifier element.
622 *
623 * @param[in,out] ctx Yin parser context for logging and to store current state.
624 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
625 * @param[in,out] data Data to read from, always moved to currently handled character.
626 * @param[in,out] pat Value to write to.
627 * @param[in,out] exts Extension instances to add to.
628 *
629 * @return LY_ERR values.
630 */
631static LY_ERR
632yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
633 const char **pat, struct lysp_ext_instance **exts)
634{
David Sedlákd3983112019-07-12 11:20:56 +0200635 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200636 const char *temp_val;
637 char *modified_val;
638 struct yin_subelement subelems[1] = {
639 {YANG_CUSTOM, NULL, 0}
640 };
641
642 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
643 if (strcmp(temp_val, "invert-match") != 0) {
644 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "modifier");
645 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
646 return LY_EVALID;
647 }
David Sedlákd3983112019-07-12 11:20:56 +0200648 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200649
650 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200651 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200652 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200653 strcpy(modified_val, *pat);
654 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200655
656 /* modify the new value */
657 modified_val[0] = 0x15;
658 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
659
660 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
661}
662
663/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200664 * @brief Parse a restriction element (length, range or one instance of must).
665 *
666 * @param[in,out] ctx Yin parser context for logging and to store current state.
667 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
668 * @param[in,out] data Data to read from, always moved to currently handled character.
669 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
670 * @param[in]
671 */
672static LY_ERR
673yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
674 enum yang_keyword restr_kw, struct lysp_restr *restr)
675{
676 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
677 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200678 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
679 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
680 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
681 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
682 {YANG_CUSTOM, NULL, 0}
683 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200684 /* argument of must is called condition, but argument of length and range is called value */
685 enum YIN_ARGUMENT arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
686 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
687
688 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
689}
690
691/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200692 * @brief Parse must element.
693 *
694 * @param[in,out] ctx YIN parser context for logging and to store current state.
695 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
696 * @param[in,out] data Data to read from, always moved to currently handled character.
697 * @param[in,out] restrs Restrictions to add to.
698 *
699 * @return LY_ERR values.
700 */
701static LY_ERR
702yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
703{
704 struct lysp_restr *restr;
705
706 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
707 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
708}
709
710/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200711 * @brief Parse position or value element.
712 *
713 * @param[in,out] ctx YIN parser context for logging and to store current state.
714 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
715 * @param[in,out] data Data to read from, always moved to currently handled character.
716 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
717 * @param[out] enm Enum structure to save value, flags and extensions.
718 *
719 * @return LY_ERR values.
720 */
721static LY_ERR
722yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
723 enum yang_keyword kw, struct lysp_type_enum *enm)
724{
725 assert(kw == YANG_POSITION || kw == YANG_VALUE);
726 const char *temp_val = NULL;
727 char *ptr;
728 long int num;
729 unsigned long int unum;
730
731 /* set value flag */
732 enm->flags |= LYS_SET_VALUE;
733
734 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200735 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 +0200736 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
737 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200738 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
739 goto error;
740 }
741
742 /* convert value */
743 errno = 0;
744 if (kw == YANG_VALUE) {
745 num = strtol(temp_val, &ptr, 10);
746 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
747 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
748 goto error;
749 }
750 } else {
751 unum = strtoul(temp_val, &ptr, 10);
752 if (unum > UINT64_C(4294967295)) {
753 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
754 goto error;
755 }
756 }
757 /* check if whole argument value was converted */
758 if (*ptr != '\0') {
759 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 +0200760 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200761 }
762 if (errno == ERANGE) {
763 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, ly_stmt2str(kw));
764 goto error;
765 }
766 /* save correctly ternary operator can't be used because num and unum have different signes */
767 if (kw == YANG_VALUE) {
768 enm->value = num;
769 } else {
770 enm->value = unum;
771 }
772 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
773
774 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200775 struct yin_subelement subelems[1] = {
776 {YANG_CUSTOM, NULL, 0}
777 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200778 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
779
780 error:
781 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
782 return LY_EVALID;
783}
784
David Sedlák05404f62019-07-24 14:11:53 +0200785
786/**
787 * @brief Parse belongs-to element.
788 *
789 * @param[in] ctx Yin parser context for logging and to store current state.
790 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
791 * @param[in,out] data Data to read from, always moved to currently handled character.
792 * @param[out] submod Structure of submodule that is being parsed.
793 * @param[in,out] exts Extension instances to add to.
794 *
795 * @return LY_ERR values
796 */
797static LY_ERR
798yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
799 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
800{
801 struct yin_subelement subelems[2] = {
802 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
803 {YANG_CUSTOM, NULL, 0}
804 };
805 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
806
807 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
808}
809
David Sedlák5545f5d2019-07-11 11:55:16 +0200810/**
David Sedlákc1771b12019-07-10 15:55:46 +0200811 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200812 * text element as child
813 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200814 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákcf5569a2019-07-11 13:31:34 +0200815 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200816 * @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 +0200817 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200818 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200819 *
820 * @return LY_ERR values.
821 */
822static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200823yin_parse_meta_element(struct yin_parser_ctx *ctx, const char **data, enum yang_keyword elem_type,
David Sedlákb4e44562019-07-04 15:42:12 +0200824 const char **value, struct lysp_ext_instance **exts)
825{
826 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
827
David Sedlák968ac342019-07-11 15:17:59 +0200828 struct yin_subelement subelems[2] = {
829 {YANG_CUSTOM, NULL, 0},
830 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
831 };
David Sedlákb4e44562019-07-04 15:42:12 +0200832
David Sedlákda8ffa32019-07-08 14:17:10 +0200833 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200834}
835
836/**
David Sedlákc1771b12019-07-10 15:55:46 +0200837 * @brief Parse error-message element.
838 *
839 * @param[in,out] ctx Yin parser context for logging and to store current state.
840 * @param[in,out] data Data to read from.
841 * @param[out] value Where the content of error-message element should be stored.
842 * @param[in,out] exts Extension instance to add to.
843 *
844 * @return LY_ERR values.
845 */
846static LY_ERR
847yin_parse_err_msg_element(struct yin_parser_ctx *ctx, const char **data, const char **value,
848 struct lysp_ext_instance **exts)
849{
David Sedlák968ac342019-07-11 15:17:59 +0200850 struct yin_subelement subelems[2] = {
851 {YANG_CUSTOM, NULL, 0},
852 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
853 };
David Sedlákc1771b12019-07-10 15:55:46 +0200854
855 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
856}
857
858/**
David Sedlák374d2b32019-07-17 15:06:55 +0200859 * @brief parse type element.
860 *
861 * @brief Parse position or value element.
862 *
863 * @param[in,out] ctx YIN parser context for logging and to store current state.
864 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
865 * @param[in,out] data Data to read from, always moved to currently handled character.
866 * @param[in,out] type Type to wrote to.
867 * @param[in,out] exts Extension instance to add to.
868 *
869 * @return LY_ERR values.
870 */
871static LY_ERR
872yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
873{
874 struct yin_subelement subelems[11] = {
875 {YANG_BASE, type, 0},
876 {YANG_BIT, type, 0},
877 {YANG_ENUM, type, 0},
878 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
879 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
880 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
881 {YANG_PATTERN, type, 0},
882 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
883 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
884 {YANG_TYPE, type},
885 {YANG_CUSTOM, NULL, 0},
886 };
887 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
888 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
889}
890
David Sedlák1af868e2019-07-17 17:03:14 +0200891/**
892 * @brief Parse max-elements element.
893 *
894 * @param[in,out] ctx YIN parser context for logging and to store current state.
895 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
896 * @param[in,out] data Data to read from, always moved to currently handled character.
897 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200898 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +0200899 * @param[in,out] exts Extension instances to add to.
900 *
901 * @return LY_ERR values.
902 */
903static LY_ERR
904yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
905 uint16_t *flags, struct lysp_ext_instance **exts)
906{
907 const char *temp_val = NULL;
908 char *ptr;
909 unsigned long int num;
910 struct yin_subelement subelems[1] = {
911 {YANG_CUSTOM, NULL, 0},
912 };
David Sedlák374d2b32019-07-17 15:06:55 +0200913
David Sedlák1af868e2019-07-17 17:03:14 +0200914 *flags |= LYS_SET_MAX;
915 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
916 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
917 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
918 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
919 return LY_EVALID;
920 }
921
922 if (strcmp(temp_val, "unbounded")) {
923 errno = 0;
924 num = strtoul(temp_val, &ptr, 10);
925 if (*ptr != '\0') {
926 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
927 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
928 return LY_EVALID;
929 }
930 if ((errno == ERANGE) || (num > UINT32_MAX)) {
931 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "max-elements");
932 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
933 return LY_EVALID;
934 }
935 *max = num;
936 }
937 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
938 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
939}
David Sedlák374d2b32019-07-17 15:06:55 +0200940
941/**
David Sedlák09e18c92019-07-18 11:17:11 +0200942 * @brief Parse max-elements element.
943 *
944 * @param[in,out] ctx YIN parser context for logging and to store current state.
945 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
946 * @param[in,out] data Data to read from, always moved to currently handled character.
947 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200948 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +0200949 * @param[in,out] exts Extension instances to add to.
950 *
951 * @return LY_ERR values.
952 */
953static LY_ERR
954yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
955 uint16_t *flags, struct lysp_ext_instance **exts)
956{
957 const char *temp_val = NULL;
958 char *ptr;
959 unsigned long int num;
960 struct yin_subelement subelems[1] = {
961 {YANG_CUSTOM, NULL, 0},
962 };
963
964 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +0200965 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 +0200966
967 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
968 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
969 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
970 return LY_EVALID;
971 }
972
973 errno = 0;
974 num = strtoul(temp_val, &ptr, 10);
975 if (ptr[0] != 0) {
976 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
977 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
978 return LY_EVALID;
979 }
980 if (errno == ERANGE || num > UINT32_MAX) {
981 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "min-elements");
982 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
983 return LY_EVALID;
984 }
985 *min = num;
986 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +0200987 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +0200988}
989
David Sedláka2dad212019-07-18 12:45:19 +0200990/**
991 * @brief Parse min-elements or max-elements element.
992 *
993 * @param[in,out] ctx YIN parser context for logging and to store current state.
994 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
995 * @param[in,out] data Data to read from, always moved to currently handled character.
996 * @param[in] parent Identification of parent element.
997 * @param[in] current Identification of current element.
998 * @param[in] dest Where the parsed value and flags should be stored.
999 *
1000 * @return LY_ERR values.
1001 */
David Sedlák09e18c92019-07-18 11:17:11 +02001002static LY_ERR
1003yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1004 enum yang_keyword parent, enum yang_keyword current, void *dest)
1005{
1006 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001007 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001008 uint32_t *lim;
1009 uint16_t *flags;
1010 struct lysp_ext_instance **exts;
1011
1012 if (parent == YANG_LEAF_LIST) {
1013 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1014 flags = &((struct lysp_node_leaflist *)dest)->flags;
1015 exts = &((struct lysp_node_leaflist *)dest)->exts;
1016 } else if (parent == YANG_REFINE) {
1017 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1018 flags = &((struct lysp_refine *)dest)->flags;
1019 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001020 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001021 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1022 flags = &((struct lysp_node_list *)dest)->flags;
1023 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001024 } else {
1025 lim = ((struct minmax_dev_meta *)dest)->lim;
1026 flags = ((struct minmax_dev_meta *)dest)->flags;
1027 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001028 }
1029
1030 if (current == YANG_MAX_ELEMENTS) {
1031 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1032 } else {
1033 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1034 }
1035
1036 return LY_SUCCESS;
1037}
1038
1039/**
David Sedláka2dad212019-07-18 12:45:19 +02001040 * @brief Parser ordered-by element.
1041 *
1042 * @param[in,out] ctx YIN parser context for logging and to store current state.
1043 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1044 * @param[in,out] data Data to read from, always moved to currently handled character.
1045 * @param[out] flags Flags to write to.
1046 * @param[in,out] exts Extension instance to add to.
1047 *
1048 * @return LY_ERR values.
1049 */
1050static LY_ERR
1051yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1052 uint16_t *flags, struct lysp_ext_instance **exts)
1053{
1054 const char *temp_val;
1055 struct yin_subelement subelems[1] = {
1056 {YANG_CUSTOM, NULL, 0},
1057 };
1058
1059 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1060 if (strcmp(temp_val, "system") == 0) {
1061 *flags |= LYS_ORDBY_SYSTEM;
1062 } else if (strcmp(temp_val, "user") == 0) {
1063 *flags |= LYS_ORDBY_USER;
1064 } else {
1065 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "ordered-by");
1066 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1067 return LY_EVALID;
1068 }
1069 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1070
1071 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1072}
1073
1074/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001075 * @brief parse any-data or any-xml element.
1076 *
1077 * @param[in,out] ctx YIN parser context for logging and to store current state.
1078 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1079 * @param[in,out] data Data to read from, always moved to currently handled character.
1080 * @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 +02001081 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001082 *
1083 * @return LY_ERR values.
1084 */
1085static LY_ERR
1086yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1087 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1088{
1089 struct lysp_node *iter;
1090 struct lysp_node_anydata *any;
1091
1092 /* create structure */
1093 any = calloc(1, sizeof *any);
1094 LY_CHECK_ERR_RET(!any, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1095 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1096 any->parent = node_meta->parent;
1097
1098 /* insert into siblings */
1099 if (!*(node_meta->siblings)) {
1100 *(node_meta->siblings) = (struct lysp_node *)any;
1101 } else {
1102 for (iter = *(node_meta->siblings); iter->next; iter = iter->next);
1103 iter->next = (struct lysp_node *)any;
1104 }
1105
1106 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001107 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 +02001108
1109 struct yin_subelement subelems[9] = {
1110 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1111 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1112 {YANG_IF_FEATURE, &any->iffeatures, 0},
1113 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1114 {YANG_MUST, &any->musts, 0},
1115 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1116 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1117 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1118 {YANG_CUSTOM, NULL, 0},
1119 };
1120 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1121}
1122
1123/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001124 * @brief parse leaf element.
1125 *
1126 * @param[in,out] ctx YIN parser context for logging and to store current state.
1127 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1128 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001129 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák203ca3a2019-07-18 15:26:25 +02001130 *
1131 * @return LY_ERR values.
1132 */
1133static LY_ERR
1134yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1135 struct tree_node_meta *node_meta)
1136{
1137 struct lysp_node *iter;
1138 struct lysp_node_leaf *leaf;
1139
1140 /* create structure */
1141 leaf = calloc(1, sizeof *leaf);
1142 LY_CHECK_ERR_RET(!leaf, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1143 leaf->nodetype = LYS_LEAF;
1144 leaf->parent = node_meta->parent;
1145
1146 /* insert into siblings */
1147 if (!*(node_meta->siblings)) {
1148 *node_meta->siblings = (struct lysp_node *)leaf;
1149 } else {
1150 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1151 iter->next = (struct lysp_node *)leaf;
1152 }
1153
1154 /* parser argument */
1155 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1156
1157 /* parse content */
1158 struct yin_subelement subelems[12] = {
1159 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1160 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1161 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1162 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1163 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1164 {YANG_MUST, &leaf->musts, 0},
1165 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1166 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1167 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1168 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1169 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1170 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001171 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001172 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1173}
1174
1175/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001176 * @brief Parse leaf-list element.
1177 *
1178 * @param[in,out] ctx YIN parser context for logging and to store current state.
1179 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1180 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001181 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001182 *
1183 * @return LY_ERR values.
1184 */
1185static LY_ERR
1186yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1187 struct tree_node_meta *node_meta)
1188{
1189 struct lysp_node *iter;
1190 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001191
1192 llist = calloc(1, sizeof *llist);
1193 LY_CHECK_ERR_RET(!llist, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1194 llist->nodetype = LYS_LEAFLIST;
1195 llist->parent = node_meta->parent;
1196
1197 /* insert into siblings */
1198 if (!*(node_meta->siblings)) {
1199 *node_meta->siblings = (struct lysp_node *)llist;
1200 } else {
1201 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1202 iter->next = (struct lysp_node *)llist;
1203 }
1204
1205 /* parse argument */
1206 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1207
1208 /* parse content */
1209 struct yin_subelement subelems[14] = {
1210 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1211 {YANG_DEFAULT, &llist->dflts, 0},
1212 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1213 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1214 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1215 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1216 {YANG_MUST, &llist->musts, 0},
1217 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1218 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1219 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1220 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1221 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1222 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1223 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001224 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001225 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1226
1227 /* invalid combination of subelements */
1228 if ((llist->min) && (llist->dflts)) {
1229 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
1230 return LY_EVALID;
1231 }
1232 if (llist->max && llist->min > llist->max) {
1233 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1234 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1235 llist->min, llist->max);
1236 return LY_EVALID;
1237 }
1238
1239 return LY_SUCCESS;
1240}
1241
1242/**
David Sedlák04e17b22019-07-19 15:29:48 +02001243 * @brief Parse typedef element.
1244 *
1245 * @param[in,out] ctx YIN parser context for logging and to store current state.
1246 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1247 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001248 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001249 *
1250 * @return LY_ERR values.
1251 */
1252static LY_ERR
1253yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1254 struct typedef_meta *typedef_meta)
1255{
1256 struct lysp_tpdf *tpdf;
1257 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *typedef_meta->typedefs, tpdf, LY_EMEM);
1258
1259 /* parse argument */
1260 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1261
1262 /* parse content */
1263 struct yin_subelement subelems[7] = {
1264 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1265 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1266 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1267 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1268 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1269 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1270 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001271 };
David Sedlák04e17b22019-07-19 15:29:48 +02001272 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1273
1274 /* store data for collision check */
1275 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1276 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1277 }
1278
1279 return LY_SUCCESS;
1280}
1281
1282/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001283 * @brief Parse refine element.
1284 *
1285 * @param[in,out] ctx YIN parser context for logging and to store current state.
1286 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1287 * @param[in,out] data Data to read from, always moved to currently handled character.
1288 * @param[in,out] refines Refines to add to.
1289 *
1290 * @return LY_ERR values.
1291 */
1292static LY_ERR
1293yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1294 struct lysp_refine **refines)
1295{
1296 struct lysp_refine *rf;
1297
1298 /* allocate new refine */
1299 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1300
1301 /* parse attribute */
1302 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1303 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1304
1305 /* parse content */
1306 struct yin_subelement subelems[11] = {
1307 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1308 {YANG_DEFAULT, &rf->dflts, 0},
1309 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1310 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1311 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1312 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1313 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1314 {YANG_MUST, &rf->musts, 0},
1315 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1316 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1317 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001318 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001319 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1320}
1321
1322/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001323 * @brief Parse uses element.
1324 *
1325 * @param[in,out] ctx YIN parser context for logging and to store current state.
1326 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1327 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001328 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001329 *
1330 * @return LY_ERR values.
1331 */
1332static LY_ERR
1333yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1334 struct tree_node_meta *node_meta)
1335{
1336 struct lysp_node *iter;
1337 struct lysp_node_uses *uses;
1338
1339 /* create structure */
1340 uses = calloc(1, sizeof *uses);
1341 LY_CHECK_ERR_RET(!uses, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1342 uses->nodetype = LYS_USES;
1343 uses->parent = node_meta->parent;
1344
1345 /* insert into siblings */
1346 if (!*(node_meta->siblings)) {
1347 *node_meta->siblings = (struct lysp_node *)uses;
1348 } else {
1349 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1350 iter->next = (struct lysp_node *)uses;
1351 }
1352
1353 /* parse argument */
1354 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1355
1356 /* parse content */
1357 struct augment_meta augments = {(struct lysp_node *)uses, &uses->augments};
1358 struct yin_subelement subelems[8] = {
1359 {YANG_AUGMENT, &augments, 0},
1360 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1361 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1362 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1363 {YANG_REFINE, &uses->refines, 0},
1364 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1365 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1366 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001367 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001368 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1369 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1370
1371 return LY_SUCCESS;
1372}
1373
1374/**
David Sedlákaa854b02019-07-22 14:17:10 +02001375 * @brief Parse revision element.
1376 *
1377 * @param[in,out] ctx YIN parser context for logging and to store current state.
1378 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1379 * @param[in,out] data Data to read from, always moved to currently handled character.
1380 * @param[in,out] revs Parsed revisions to add to.
1381 *
1382 * @return LY_ERR values.
1383 */
1384static LY_ERR
1385yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1386 struct lysp_revision **revs)
1387{
1388 struct lysp_revision *rev;
1389 const char *temp_date = NULL;
1390
1391 /* allocate new reivison */
1392 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1393
1394 /* parse argument */
1395 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1396 /* check value */
1397 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1398 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1399 return LY_EVALID;
1400 }
1401 strcpy(rev->date, temp_date);
1402 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1403
1404 /* parse content */
1405 struct yin_subelement subelems[3] = {
1406 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1407 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1408 {YANG_CUSTOM, NULL, 0},
1409 };
1410 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1411}
1412
David Sedlák5e13dea2019-07-22 16:06:45 +02001413/**
1414 * @brief Parse include element.
1415 *
1416 * @param[in,out] ctx YIN parser context for logging and to store current state.
1417 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1418 * @param[in,out] data Data to read from, always moved to currently handled character.
1419 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1420 *
1421 * @return LY_ERR values.
1422 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001423static LY_ERR
1424yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1425 struct include_meta *inc_meta)
1426{
1427 struct lysp_include *inc;
1428
1429 /* allocate new include */
1430 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1431
1432 /* parse argument */
1433 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1434
1435 /* submodules share the namespace with the module names, so there must not be
1436 * a module of the same name in the context, no need for revision matching */
1437 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
1438 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG,
1439 "Name collision between module and submodule of name \"%s\".", inc->name);
1440 return LY_EVALID;
1441 }
1442
1443 /* parse content */
1444 struct yin_subelement subelems[4] = {
1445 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1446 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1447 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1448 {YANG_CUSTOM, NULL, 0},
1449 };
1450 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1451}
1452
David Sedlákaa854b02019-07-22 14:17:10 +02001453/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001454 * @brief Parse feature element.
1455 *
1456 * @param[in,out] ctx YIN parser context for logging and to store current state.
1457 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1458 * @param[in,out] data Data to read from, always moved to currently handled character.
1459 * @param[in,out] features Features to add to.
1460 *
1461 * @return LY_ERR values.
1462 */
1463static LY_ERR
1464yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1465 struct lysp_feature **features)
1466{
1467 struct lysp_feature *feat;
1468
1469 /* allocate new feature */
1470 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1471
1472 /* parse argument */
1473 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1474
1475 /* parse content */
1476 struct yin_subelement subelems[5] = {
1477 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1478 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1479 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1480 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1481 {YANG_CUSTOM, NULL, 0},
1482 };
1483 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1484}
1485
1486/**
David Sedlák28794f22019-07-22 16:45:00 +02001487 * @brief Parse identity element.
1488 *
1489 * @param[in,out] ctx YIN parser context for logging and to store current state.
1490 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1491 * @param[in,out] data Data to read from, always moved to currently handled character.
1492 * @param[in,out] identities Identities to add to.
1493 *
1494 * @return LY_ERR values.
1495 */
1496static LY_ERR
1497yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1498 struct lysp_ident **identities)
1499{
1500 struct lysp_ident *ident;
1501
1502 /* allocate new identity */
1503 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1504
1505 /* parse argument */
1506 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1507
1508 /* parse content */
1509 struct yin_subelement subelems[6] = {
1510 {YANG_BASE, &ident->bases, 0},
1511 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1512 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1513 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1514 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1515 {YANG_CUSTOM, NULL, 0},
1516 };
1517 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1518}
1519
1520/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001521 * @brief Parse list element.
1522 *
1523 * @param[in,out] ctx YIN parser context for logging and to store current state.
1524 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1525 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001526 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákaf536aa2019-07-23 13:42:23 +02001527 *
1528 * @return LY_ERR values.
1529 */
1530static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001531yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1532 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001533{
1534 struct lysp_node *iter;
1535 struct lysp_node_list *list;
1536
1537 /* create structure */
1538 list = calloc(1, sizeof *list);
1539 LY_CHECK_ERR_RET(!list, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1540 list->nodetype = LYS_LIST;
1541 list->parent = node_meta->parent;
1542
1543 /* insert into siblings */
1544 if (!*(node_meta->siblings)) {
1545 *node_meta->siblings = (struct lysp_node *)list;
1546 } else {
1547 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1548 iter->next = (struct lysp_node *)list;
1549 }
1550
1551 /* parse argument */
1552 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1553
1554 /* parse list content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001555 struct action_meta act_meta = {(struct lysp_node *)list, &list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001556 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
1557 struct typedef_meta typedef_meta = {(struct lysp_node *)list, &list->typedefs};
David Sedlák031b9e72019-07-23 15:19:37 +02001558 struct notif_meta notif_meta = {(struct lysp_node *)list, &list->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001559 struct grouping_meta gr_meta = {(struct lysp_node *)list, &list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001560 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001561 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001562 {YANG_ANYDATA, &new_node_meta, 0},
1563 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001564 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001565 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001566 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001567 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001568 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001569 {YANG_IF_FEATURE, &list->iffeatures, 0},
1570 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1571 {YANG_LEAF, &new_node_meta, 0},
1572 {YANG_LEAF_LIST, &new_node_meta, 0},
1573 {YANG_LIST, &new_node_meta, 0},
1574 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1575 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1576 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001577 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001578 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1579 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1580 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1581 {YANG_TYPEDEF, &typedef_meta, 0},
1582 {YANG_UNIQUE, &list->uniques, 0},
1583 {YANG_USES, &new_node_meta, 0},
1584 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1585 {YANG_CUSTOM, NULL, 0},
1586 };
1587 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1588
1589 /* finalize parent pointers to the reallocated items */
1590 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1591
1592 if (list->max && list->min > list->max) {
1593 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1594 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1595 list->min, list->max);
1596 return LY_EVALID;
1597 }
1598
1599 return LY_SUCCESS;
1600}
1601
1602/**
David Sedlák031b9e72019-07-23 15:19:37 +02001603 * @brief Parse notification element.
1604 *
1605 * @param[in,out] ctx YIN parser context for logging and to store current state.
1606 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1607 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001608 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001609 *
1610 * @return LY_ERR values.
1611 */
1612static LY_ERR
1613yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1614 struct notif_meta *notif_meta)
1615{
1616 struct lysp_notif *notif;
1617
1618 /* allocate new notification */
1619 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notif_meta->notifs, notif, LY_EMEM);
1620 notif->nodetype = LYS_NOTIF;
1621 notif->parent = notif_meta->parent;
1622
1623 /* parse argument */
1624 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1625
1626 /* parse notification content */
1627 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
1628 struct typedef_meta typedef_meta = {(struct lysp_node *)notif, &notif->typedefs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001629 struct grouping_meta gr_meta = {(struct lysp_node *)notif, &notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001630 struct yin_subelement subelems[16] = {
1631 {YANG_ANYDATA, &node_meta, 0},
1632 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001633 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001634 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001635 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001636 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001637 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1638 {YANG_LEAF, &node_meta, 0},
1639 {YANG_LEAF_LIST, &node_meta, 0},
1640 {YANG_LIST, &node_meta, 0},
1641 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1642 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1643 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1644 {YANG_TYPEDEF, &typedef_meta, 0},
1645 {YANG_USES, &node_meta, 0},
1646 {YANG_CUSTOM, NULL, 0},
1647 };
1648 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1649
1650 /* finalize parent pointers to the reallocated items */
1651 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1652
1653 return LY_SUCCESS;
1654}
1655
1656/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001657 * @brief Parse notification element.
1658 *
1659 * @param[in,out] ctx YIN parser context for logging and to store current state.
1660 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1661 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001662 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001663 *
1664 * @return LY_ERR values.
1665 */
1666static LY_ERR
1667yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1668 struct grouping_meta *gr_meta)
1669{
1670 struct lysp_grp *grp;
1671
1672 /* create new grouping */
1673 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *gr_meta->groupings, grp, LY_EMEM);
1674 grp->nodetype = LYS_GROUPING;
1675 grp->parent = gr_meta->parent;
1676
1677 /* parse argument */
1678 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1679
1680 /* parse grouping content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001681 struct action_meta act_meta = {(struct lysp_node *)grp, &grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001682 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
1683 struct typedef_meta typedef_meta = {(struct lysp_node *)grp, &grp->typedefs};
1684 struct grouping_meta sub_grouping = {(struct lysp_node *)grp, &grp->groupings};
1685 struct notif_meta notif_meta = {(struct lysp_node *)grp, &grp->notifs};
1686 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001687 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001688 {YANG_ANYDATA, &node_meta, 0},
1689 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001690 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001691 {YANG_CONTAINER, &node_meta, 0},
1692 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1693 {YANG_GROUPING, &sub_grouping, 0},
1694 {YANG_LEAF, &node_meta, 0},
1695 {YANG_LEAF_LIST, &node_meta, 0},
1696 {YANG_LIST, &node_meta, 0},
1697 {YANG_NOTIFICATION, &notif_meta, 0},
1698 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
1699 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
1700 {YANG_TYPEDEF, &typedef_meta, 0},
1701 {YANG_USES, &node_meta, 0},
1702 {YANG_CUSTOM, NULL, 0},
1703 };
1704 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
1705 /* finalize parent pointers to the reallocated items */
1706 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
1707
1708 return LY_SUCCESS;
1709}
1710
1711/**
David Sedlákf111bcb2019-07-23 17:15:51 +02001712 * @brief Parse list element.
1713 *
1714 * @param[in,out] ctx YIN parser context for logging and to store current state.
1715 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1716 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001717 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákf111bcb2019-07-23 17:15:51 +02001718 *
1719 * @return LY_ERR values.
1720 */
1721static LY_ERR
1722yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1723 struct tree_node_meta *node_meta)
1724{
1725 struct lysp_node *iter;
1726 struct lysp_node_container *cont;
1727
1728 /* create new container */
1729 cont = calloc(1, sizeof *cont);
1730 LY_CHECK_ERR_RET(!cont, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1731 cont->nodetype = LYS_CONTAINER;
1732 cont->parent = node_meta->parent;
1733
1734 /* insert into siblings */
1735 if (!*(node_meta->siblings)) {
1736 *node_meta->siblings = (struct lysp_node *)cont;
1737 } else {
1738 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1739 iter->next = (struct lysp_node *)cont;
1740 }
1741
1742 /* parse aegument */
1743 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
1744
1745 /* parse container content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001746 struct action_meta act_meta = {(struct lysp_node *)cont, &cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02001747 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
1748 struct grouping_meta grp_meta = {(struct lysp_node *)cont, &cont->groupings};
1749 struct typedef_meta typedef_meta = {(struct lysp_node *)cont, &cont->typedefs};
1750 struct notif_meta notif_meta = {(struct lysp_node *)cont, &cont->notifs};
1751 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001752 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02001753 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1754 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001755 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001756 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
1757 {YANG_CONTAINER, &new_node_meta, 0},
1758 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
1759 {YANG_GROUPING, &grp_meta, 0},
1760 {YANG_IF_FEATURE, &cont->iffeatures, 0},
1761 {YANG_LEAF, &new_node_meta, 0},
1762 {YANG_LEAF_LIST, &new_node_meta, 0},
1763 {YANG_LIST, &new_node_meta, 0},
1764 {YANG_MUST, &cont->musts, 0},
1765 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
1766 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
1767 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
1768 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
1769 {YANG_TYPEDEF, &typedef_meta, 0},
1770 {YANG_USES, &new_node_meta, 0},
1771 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
1772 {YANG_CUSTOM, NULL, 0},
1773 };
1774 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
1775 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
1776
1777 return LY_SUCCESS;
1778}
1779
1780/**
David Sedlák5379d392019-07-24 10:42:03 +02001781 * @brief Parse case element.
1782 *
1783 * @param[in,out] ctx YIN parser context for logging and to store current state.
1784 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1785 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001786 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák5379d392019-07-24 10:42:03 +02001787 *
1788 * @return LY_ERR values.
1789 */
1790static LY_ERR
1791yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1792 struct tree_node_meta *node_meta)
1793{
1794 struct lysp_node *iter;
1795 struct lysp_node_case *cas;
1796
1797 /* create new case */
1798 cas = calloc(1, sizeof *cas);
1799 LY_CHECK_ERR_RET(!cas, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1800 cas->nodetype = LYS_CASE;
1801 cas->parent = node_meta->parent;
1802
1803 /* insert into siblings */
1804 if (!*(node_meta->siblings)) {
1805 *node_meta->siblings = (struct lysp_node *)cas;
1806 } else {
1807 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1808 iter->next = (struct lysp_node *)cas;
1809 }
1810
1811 /* parse argument */
1812 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
1813
1814 /* parse case content */
1815 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
1816 struct yin_subelement subelems[14] = {
1817 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1818 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001819 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02001820 {YANG_CONTAINER, &new_node_meta, 0},
1821 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
1822 {YANG_IF_FEATURE, &cas->iffeatures, 0},
1823 {YANG_LEAF, &new_node_meta, 0},
1824 {YANG_LEAF_LIST, &new_node_meta, 0},
1825 {YANG_LIST, &new_node_meta, 0},
1826 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
1827 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
1828 {YANG_USES, &new_node_meta, 0},
1829 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
1830 {YANG_CUSTOM, NULL, 0},
1831 };
1832 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
1833}
1834
1835/**
David Sedlák05404f62019-07-24 14:11:53 +02001836 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001837 *
1838 * @param[in,out] ctx YIN parser context for logging and to store current state.
1839 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1840 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001841 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákb7abcfa2019-07-24 12:33:35 +02001842 *
1843 * @return LY_ERR values.
1844 */
1845LY_ERR
1846yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1847 struct tree_node_meta *node_meta)
1848{
1849 struct lysp_node *iter;
1850 struct lysp_node_choice *choice;
1851
1852 /* create new choice */
1853 choice = calloc(1, sizeof *choice);
1854 LY_CHECK_ERR_RET(!choice, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1855 choice->nodetype = LYS_CHOICE;
1856 choice->parent = node_meta->parent;
1857
1858 /* insert into siblings */
1859 if (!*(node_meta->siblings)) {
1860 *node_meta->siblings = (struct lysp_node *)choice;
1861 } else {
1862 for (iter = *node_meta->siblings; iter->next; iter = iter->next);
1863 iter->next = (struct lysp_node *)choice;
1864 }
1865
1866 /* parse argument */
1867 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
1868
1869 /* parse choice content */
1870 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
1871 struct yin_subelement subelems[17] = {
1872 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
1873 {YANG_ANYXML, &new_node_meta, 0},
1874 {YANG_CASE, &new_node_meta, 0},
1875 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
1876 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
1877 {YANG_CONTAINER, &new_node_meta, 0},
1878 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
1879 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
1880 {YANG_IF_FEATURE, &choice->iffeatures, 0},
1881 {YANG_LEAF, &new_node_meta, 0},
1882 {YANG_LEAF_LIST, &new_node_meta, 0},
1883 {YANG_LIST, &new_node_meta, 0},
1884 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
1885 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
1886 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
1887 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
1888 {YANG_CUSTOM, NULL, 0},
1889 };
1890 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
1891}
1892
1893/**
David Sedlák05404f62019-07-24 14:11:53 +02001894 * @brief Parse input or output element.
1895 *
1896 * @param[in,out] ctx YIN parser context for logging and to store current state.
1897 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1898 * @param[in,out] data Data to read from, always moved to currently handled character.
1899 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
1900 *
1901 * @return LY_ERR values.
1902 */
1903static LY_ERR
1904yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
1905 struct inout_meta *inout_meta)
1906{
1907 /* initiate structure */
1908 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
1909 inout_meta->inout_p->parent = inout_meta->parent;
1910
1911 /* check attributes */
1912 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
1913
1914 /* parser input/output content */
1915 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
1916 struct grouping_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->groupings};
1917 struct typedef_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->typedefs};
1918 struct yin_subelement subelems[12] = {
1919 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
1920 {YANG_ANYXML, &node_meta, 0},
1921 {YANG_CHOICE, &node_meta, 0},
1922 {YANG_CONTAINER, &node_meta, 0},
1923 {YANG_GROUPING, &grp_meta, 0},
1924 {YANG_LEAF, &node_meta, 0},
1925 {YANG_LEAF_LIST, &node_meta, 0},
1926 {YANG_LIST, &node_meta, 0},
1927 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
1928 {YANG_TYPEDEF, &typedef_meta, 0},
1929 {YANG_USES, &node_meta, 0},
1930 {YANG_CUSTOM, NULL, 0},
1931 };
1932 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
1933
1934 /* finalize parent pointers to the reallocated items */
1935 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
1936 NULL, NULL, NULL));
1937
1938 return LY_SUCCESS;
1939}
1940
David Sedlák992fb7c2019-07-24 16:51:01 +02001941/**
1942 * @brief Parse action element.
1943 *
1944 * @param[in,out] ctx YIN parser context for logging and to store current state.
1945 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1946 * @param[in,out] data Data to read from, always moved to currently handled character.
1947 * @param[in] act_meta Meta information about parent node and actions to add to.
1948 *
1949 * @return LY_ERR values.
1950 */
David Sedlák85d0eca2019-07-24 15:15:21 +02001951static LY_ERR
1952yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1953 struct action_meta *act_meta)
1954{
1955 struct lysp_action *act;
1956
1957 /* create new action */
1958 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *act_meta->actions, act, LY_EMEM);
1959 act->nodetype = LYS_ACTION;
1960 act->parent = act_meta->parent;
1961
1962 /* parse argument */
1963 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
1964
1965 /* parse content */
1966 struct grouping_meta grp_meta = {(struct lysp_node *)act, &act->groupings};
1967 struct typedef_meta typedef_meta = {(struct lysp_node *)act, &act->typedefs};
1968 struct inout_meta input = {(struct lysp_node *)act, &act->input};
1969 struct inout_meta output = {(struct lysp_node *)act, &act->output};
1970 struct yin_subelement subelems[9] = {
1971 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
1972 {YANG_GROUPING, &grp_meta, 0},
1973 {YANG_IF_FEATURE, &act->iffeatures, 0},
1974 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
1975 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
1976 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
1977 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
1978 {YANG_TYPEDEF, &typedef_meta, 0},
1979 {YANG_CUSTOM, NULL, 0},
1980 };
1981 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
1982 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
1983
1984 return LY_SUCCESS;
1985}
1986
David Sedlák05404f62019-07-24 14:11:53 +02001987/**
David Sedlák992fb7c2019-07-24 16:51:01 +02001988 * @brief Parse augment element.
1989 *
1990 * @param[in,out] ctx YIN parser context for logging and to store current state.
1991 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1992 * @param[in,out] data Data to read from, always moved to currently handled character.
1993 * @param[in] aug_meta Meta information about parent node and augments to add to.
1994 *
1995 * @return LY_ERR values.
1996 */
1997static LY_ERR
1998yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1999 struct augment_meta *aug_meta)
2000{
2001 struct lysp_augment *aug;
2002
2003 /* create new augment */
2004 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *aug_meta->augments, aug, LY_EMEM);
2005 aug->nodetype = LYS_AUGMENT;
2006 aug->parent = aug_meta->parent;
2007
2008 /* parse argument */
2009 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2010 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2011
2012 /* parser augment content */
2013 struct action_meta act_meta = {(struct lysp_node *)aug, &aug->actions};
2014 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
2015 struct notif_meta notif_meta = {(struct lysp_node *)aug, &aug->notifs};
2016 struct yin_subelement subelems[17] = {
2017 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
2018 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2019 {YANG_ANYXML, &node_meta, 0},
2020 {YANG_CASE, &node_meta, 0},
2021 {YANG_CHOICE, &node_meta, 0},
2022 {YANG_CONTAINER, &node_meta, 0},
2023 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
2024 {YANG_IF_FEATURE, &aug->iffeatures, 0},
2025 {YANG_LEAF, &node_meta, 0},
2026 {YANG_LEAF_LIST, &node_meta, 0},
2027 {YANG_LIST, &node_meta, 0},
2028 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2029 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
2030 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
2031 {YANG_USES, &node_meta, 0},
2032 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
2033 {YANG_CUSTOM, NULL, 0},
2034 };
2035 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
2036
2037 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2038
2039 return LY_SUCCESS;
2040}
2041
David Sedlák8b754462019-07-25 16:22:13 +02002042/**
2043 * @brief Parse deviate element.
2044 *
2045 * @param[in,out] ctx YIN parser context for logging and to store current state.
2046 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2047 * @param[in,out] data Data to read from, always moved to currently handled character.
2048 * @param[in] deviates Deviates to add to.
2049 *
2050 * @return LY_ERR values.
2051 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002052static LY_ERR
2053yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2054 struct lysp_deviate **deviates)
2055{
2056 LY_ERR ret = LY_SUCCESS;
2057 uint8_t dev_mod;
2058 const char *temp_val;
2059 struct lysp_deviate *iter, *d;
2060 struct lysp_deviate_add *d_add = NULL;
2061 struct lysp_deviate_rpl *d_rpl = NULL;
2062 struct lysp_deviate_del *d_del = NULL;
2063
2064 /* parse argument */
2065 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2066
2067 if (strcmp(temp_val, "not-supported") == 0) {
2068 dev_mod = LYS_DEV_NOT_SUPPORTED;
2069 } else if (strcmp(temp_val, "add") == 0) {
2070 dev_mod = LYS_DEV_ADD;
2071 } else if (strcmp(temp_val, "replace") == 0) {
2072 dev_mod = LYS_DEV_REPLACE;
2073 } else if (strcmp(temp_val, "delete") == 0) {
2074 dev_mod = LYS_DEV_DELETE;
2075 } else {
2076 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "deviate");
2077 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2078 return LY_EVALID;
2079 }
2080 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2081
2082 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2083 d = calloc(1, sizeof *d);
2084 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2085 struct yin_subelement subelems[1] = {
2086 {YANG_CUSTOM, NULL, 0}
2087 };
2088 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2089
2090 } else if (dev_mod == LYS_DEV_ADD) {
2091 d_add = calloc(1, sizeof *d_add);
2092 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2093 d = (struct lysp_deviate *)d_add;
2094 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2095 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2096 struct yin_subelement subelems[9] = {
2097 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2098 {YANG_DEFAULT, &d_add->dflts, 0},
2099 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2100 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2101 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2102 {YANG_MUST, &d_add->musts, 0},
2103 {YANG_UNIQUE, &d_add->uniques, 0},
2104 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2105 {YANG_CUSTOM, NULL, 0},
2106 };
2107 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2108
2109 } else if (dev_mod == LYS_DEV_REPLACE) {
2110 d_rpl = calloc(1, sizeof *d_rpl);
2111 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2112 d = (struct lysp_deviate *)d_rpl;
2113 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2114 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2115 struct yin_subelement subelems[8] = {
2116 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2117 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2118 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2119 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2120 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2121 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2122 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2123 {YANG_CUSTOM, NULL, 0},
2124 };
2125 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2126
2127 } else {
2128 d_del = calloc(1, sizeof *d_del);
2129 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2130 d = (struct lysp_deviate *)d_del;
2131 struct yin_subelement subelems[5] = {
2132 {YANG_DEFAULT, &d_del->dflts, 0},
2133 {YANG_MUST, &d_del->musts, 0},
2134 {YANG_UNIQUE, &d_del->uniques, 0},
2135 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2136 {YANG_CUSTOM, NULL, 0},
2137 };
2138 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2139 }
2140 LY_CHECK_GOTO(ret, cleanup);
2141
2142 d->mod = dev_mod;
2143 /* insert into siblings */
2144 if (!*deviates) {
2145 *deviates = d;
2146 } else {
2147 for (iter = *deviates; iter->next; iter = iter->next);
2148 iter->next = d;
2149 }
2150
2151 return ret;
2152
2153cleanup:
2154 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002155 return ret;
2156}
2157
David Sedlák992fb7c2019-07-24 16:51:01 +02002158/**
David Sedlák8b754462019-07-25 16:22:13 +02002159 * @brief Parse deviation element.
2160 *
2161 * @param[in,out] ctx YIN parser context for logging and to store current state.
2162 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2163 * @param[in,out] data Data to read from, always moved to currently handled character.
2164 * @param[in] deviations Deviations to add to.
2165 *
2166 * @return LY_ERR values.
2167 */
2168static LY_ERR
2169yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2170 struct lysp_deviation **deviations)
2171{
2172 struct lysp_deviation *dev;
2173
2174 /* create new deviation */
2175 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2176
2177 /* parse argument */
2178 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATE));
2179 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2180 struct yin_subelement subelems[4] = {
2181 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2182 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2183 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2184 {YANG_CUSTOM, NULL, 0},
2185 };
2186 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATE, NULL, &dev->exts);
2187}
2188
2189/**
David Sedlákb4e44562019-07-04 15:42:12 +02002190 * @brief Map keyword type to substatement info.
2191 *
2192 * @param[in] kw Keyword type.
2193 *
2194 * @return correct LYEXT_SUBSTMT information.
2195 */
2196static LYEXT_SUBSTMT
2197kw2lyext_substmt(enum yang_keyword kw)
2198{
2199 switch (kw) {
2200 case YANG_ARGUMENT:
2201 return LYEXT_SUBSTMT_ARGUMENT;
2202 case YANG_BASE:
2203 return LYEXT_SUBSTMT_BASE;
2204 case YANG_BELONGS_TO:
2205 return LYEXT_SUBSTMT_BELONGSTO;
2206 case YANG_CONTACT:
2207 return LYEXT_SUBSTMT_CONTACT;
2208 case YANG_DEFAULT:
2209 return LYEXT_SUBSTMT_DEFAULT;
2210 case YANG_DESCRIPTION:
2211 return LYEXT_SUBSTMT_DESCRIPTION;
2212 case YANG_ERROR_APP_TAG:
2213 return LYEXT_SUBSTMT_ERRTAG;
2214 case YANG_ERROR_MESSAGE:
2215 return LYEXT_SUBSTMT_ERRMSG;
2216 case YANG_KEY:
2217 return LYEXT_SUBSTMT_KEY;
2218 case YANG_NAMESPACE:
2219 return LYEXT_SUBSTMT_NAMESPACE;
2220 case YANG_ORGANIZATION:
2221 return LYEXT_SUBSTMT_ORGANIZATION;
2222 case YANG_PATH:
2223 return LYEXT_SUBSTMT_PATH;
2224 case YANG_PREFIX:
2225 return LYEXT_SUBSTMT_PREFIX;
2226 case YANG_PRESENCE:
2227 return LYEXT_SUBSTMT_PRESENCE;
2228 case YANG_REFERENCE:
2229 return LYEXT_SUBSTMT_REFERENCE;
2230 case YANG_REVISION_DATE:
2231 return LYEXT_SUBSTMT_REVISIONDATE;
2232 case YANG_UNITS:
2233 return LYEXT_SUBSTMT_UNITS;
2234 case YANG_VALUE:
2235 return LYEXT_SUBSTMT_VALUE;
2236 case YANG_YANG_VERSION:
2237 return LYEXT_SUBSTMT_VERSION;
2238 case YANG_MODIFIER:
2239 return LYEXT_SUBSTMT_MODIFIER;
2240 case YANG_REQUIRE_INSTANCE:
2241 return LYEXT_SUBSTMT_REQINSTANCE;
2242 case YANG_YIN_ELEMENT:
2243 return LYEXT_SUBSTMT_YINELEM;
2244 case YANG_CONFIG:
2245 return LYEXT_SUBSTMT_CONFIG;
2246 case YANG_MANDATORY:
2247 return LYEXT_SUBSTMT_MANDATORY;
2248 case YANG_ORDERED_BY:
2249 return LYEXT_SUBSTMT_ORDEREDBY;
2250 case YANG_STATUS:
2251 return LYEXT_SUBSTMT_STATUS;
2252 case YANG_FRACTION_DIGITS:
2253 return LYEXT_SUBSTMT_FRACDIGITS;
2254 case YANG_MAX_ELEMENTS:
2255 return LYEXT_SUBSTMT_MAX;
2256 case YANG_MIN_ELEMENTS:
2257 return LYEXT_SUBSTMT_MIN;
2258 case YANG_POSITION:
2259 return LYEXT_SUBSTMT_POSITION;
2260 case YANG_UNIQUE:
2261 return LYEXT_SUBSTMT_UNIQUE;
2262 case YANG_IF_FEATURE:
2263 return LYEXT_SUBSTMT_IFFEATURE;
2264 default:
2265 return LYEXT_SUBSTMT_SELF;
2266 }
2267}
2268
David Sedlákd6e56892019-07-01 15:40:24 +02002269LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002270yin_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 +02002271 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 +02002272{
2273 LY_ERR ret = LY_SUCCESS;
2274 struct sized_string prefix, name;
David Sedlák8e7bda82019-07-16 17:57:50 +02002275 char *out = NULL;
2276 size_t out_len = 0;
2277 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002278 struct yin_arg_record *attrs = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002279 enum yang_keyword kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002280 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002281 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002282
David Sedlákb0faad82019-07-04 14:28:59 +02002283 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002284
David Sedlákda8ffa32019-07-08 14:17:10 +02002285 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2286 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002287 /* current element has subelements as content */
2288 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002289 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2290 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlákd6e56892019-07-01 15:40:24 +02002291 LY_CHECK_GOTO(ret, cleanup);
2292 if (!name.value) {
2293 /* end of current element reached */
2294 break;
2295 }
David Sedlák1af868e2019-07-17 17:03:14 +02002296 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002297 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc1771b12019-07-10 15:55:46 +02002298 kw = yin_match_keyword(ctx, name.value, name.len, prefix.value, prefix.len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002299
2300 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002301 subelem = get_record(kw, subelem_info_size, subelem_info);
2302 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002303 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2304 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2305 } else {
2306 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
2307 }
David Sedlákd6e56892019-07-01 15:40:24 +02002308 ret = LY_EVALID;
2309 goto cleanup;
2310 }
2311
David Sedlák5f8191e2019-07-08 16:35:52 +02002312 /* TODO check relative order */
2313
David Sedlák4ffcec82019-07-25 15:10:21 +02002314 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002315 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002316 /* subelement uniquenes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002317 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 +02002318 return LY_EVALID;
2319 }
David Sedlák1af868e2019-07-17 17:03:14 +02002320 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002321 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002322 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002323 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002324 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002325 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002326 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002327 if (ctx->mod_version < 2) {
2328 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002329 ret = LY_EVALID;
2330 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002331 }
2332 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002333 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002334 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002335
David Sedlákd6e56892019-07-01 15:40:24 +02002336 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002337 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002338 case YANG_CUSTOM:
David Sedlák1af868e2019-07-17 17:03:14 +02002339 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name.value, prefix.len),
David Sedlák3ffbc522019-07-02 17:49:28 +02002340 namelen2fulllen(name.len, prefix.len),
David Sedlák1af868e2019-07-17 17:03:14 +02002341 kw2lyext_substmt(current_element),
2342 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002343 break;
2344 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002345 case YANG_RPC:
David Sedlák85d0eca2019-07-24 15:15:21 +02002346 ret = yin_parse_action(ctx, attrs, data, (struct action_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002347 break;
2348 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002349 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002350 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002351 break;
2352 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002353 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002354 break;
2355 case YANG_AUGMENT:
David Sedlák992fb7c2019-07-24 16:51:01 +02002356 ret = yin_parse_augment(ctx, attrs, data, (struct augment_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002357 break;
2358 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002359 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002360 type = (struct lysp_type *)subelem->dest;
2361 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002362 Y_PREF_IDENTIF_ARG, exts);
2363 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002364 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002365 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002366 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2367 } else {
2368 LOGINT(ctx->xml_ctx.ctx);
2369 ret = LY_EINT;
2370 }
David Sedlákd6e56892019-07-01 15:40:24 +02002371 break;
2372 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002373 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002374 break;
2375 case YANG_BIT:
David Sedlák07869a52019-07-12 14:28:19 +02002376 case YANG_ENUM:
David Sedlák1af868e2019-07-17 17:03:14 +02002377 ret = yin_parse_enum_bit(ctx, attrs, data, kw, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002378 break;
2379 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002380 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002381 break;
2382 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002383 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002384 break;
2385 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002386 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002387 break;
2388 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002389 case YANG_DESCRIPTION:
2390 case YANG_ORGANIZATION:
2391 case YANG_REFERENCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002392 ret = yin_parse_meta_element(ctx, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002393 break;
2394 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002395 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002396 break;
2397 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002398 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2399 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2400 YIN_ARG_VALUE, Y_STR_ARG, exts);
2401 } else {
2402 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2403 YIN_ARG_VALUE, Y_STR_ARG, exts);
2404 }
David Sedlákd6e56892019-07-01 15:40:24 +02002405 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002406 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002407 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002408 break;
2409 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002410 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002411 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002412 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002413 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002414 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002415 break;
2416 case YANG_ERROR_MESSAGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002417 ret = yin_parse_err_msg_element(ctx, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002418 break;
2419 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002420 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002421 break;
2422 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002423 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002424 break;
2425 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002426 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002427 break;
2428 case YANG_GROUPING:
David Sedláke3ce9ef2019-07-23 16:34:30 +02002429 ret = yin_parse_grouping(ctx, attrs, data, (struct grouping_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002430 break;
2431 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002432 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002433 break;
2434 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002435 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2436 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002437 break;
2438 case YANG_IMPORT:
David Sedlák1af868e2019-07-17 17:03:14 +02002439 ret = yin_parse_import(ctx, attrs, data, (struct lysp_module *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002440 break;
2441 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002442 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002443 break;
2444 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002445 case YANG_OUTPUT:
2446 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002447 break;
2448 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002449 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2450 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002451 break;
2452 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002453 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002454 break;
2455 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002456 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002457 break;
2458 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002459 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002460 type->length = calloc(1, sizeof *type->length);
2461 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002462 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002463 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002464 break;
2465 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002466 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002467 break;
2468 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002469 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002470 break;
2471 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002472 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002473 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002474 break;
2475 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002476 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002477 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002478 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002479 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002480 break;
2481 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002482 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002483 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002484 break;
2485 case YANG_NOTIFICATION:
David Sedlák031b9e72019-07-23 15:19:37 +02002486 ret = yin_parse_notification(ctx, attrs, data, (struct notif_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002487 break;
2488 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002489 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002490 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002491 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002492 type = (struct lysp_type *)subelem->dest;
2493 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlák58979872019-07-12 11:42:43 +02002494 YIN_ARG_VALUE, Y_STR_ARG, exts);
2495 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002496 break;
2497 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002498 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002499 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002500 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002501 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002502 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2503 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002504 break;
2505 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002506 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2507 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002508 break;
2509 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002510 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2511 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002512 break;
2513 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002514 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002515 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002516 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002517 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002518 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002519 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002520 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002521 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002522 break;
2523 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002524 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002525 break;
2526 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002527 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002528 break;
2529 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002530 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002531 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002532 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002533 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002534 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002535 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002536 if (current_element == YANG_DEVIATE) {
2537 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2538 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2539 type = *((struct lysp_type **)subelem->dest);
2540 } else {
2541 type = (struct lysp_type *)subelem->dest;
2542 }
David Sedlák374d2b32019-07-17 15:06:55 +02002543 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002544 if (current_element == YANG_TYPE) {
2545 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002546 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002547 type = nested_type;
2548 }
David Sedlák1af868e2019-07-17 17:03:14 +02002549 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002550 break;
2551 case YANG_TYPEDEF:
David Sedlák04e17b22019-07-19 15:29:48 +02002552 ret = yin_parse_typedef(ctx, attrs, data, (struct typedef_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002553 break;
2554 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002555 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002556 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002557 break;
2558 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002559 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002560 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002561 break;
2562 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002563 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002564 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002565 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002566 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002567 break;
2568 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002569 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002570 break;
2571 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002572 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002573 break;
2574 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002575 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002576 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002577 break;
2578 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002579 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002580 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002581 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002582 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002583 FREE_ARRAY(ctx, attrs, free_arg_rec);
2584 attrs = NULL;
2585 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002586 }
2587 } else {
2588 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002589 /* save text content, if text_content isn't set, it's just ignored */
David Sedlák4ffcec82019-07-25 15:10:21 +02002590 /* no resources are allocated in this branch so no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002591 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002592 if (text_content) {
2593 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002594 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002595 if (!*text_content) {
2596 free(out);
2597 return LY_EMEM;
2598 }
2599 } else {
2600 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002601 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002602 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002603 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002604 }
2605 }
2606 }
David Sedlákd6e56892019-07-01 15:40:24 +02002607 /* load closing element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002608 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 +02002609 }
2610 }
David Sedlák8b754462019-07-25 16:22:13 +02002611 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2612 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002613
2614cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002615 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002616 return ret;
2617}
2618
David Sedlák619db942019-07-03 14:47:30 +02002619LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002620yin_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 +02002621 struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +02002622{
David Sedlák3ffbc522019-07-02 17:49:28 +02002623 const char *temp_rev;
David Sedlák968ac342019-07-11 15:17:59 +02002624 struct yin_subelement subelems[1] = {
2625 {YANG_CUSTOM, NULL, 0}
2626 };
David Sedlák81e04022019-04-05 15:05:46 +02002627
David Sedlák292763b2019-07-09 11:10:53 +02002628 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 +02002629 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
2630 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
David Sedlákda63c082019-06-04 13:52:23 +02002631
2632 strcpy(rev, temp_rev);
David Sedlákda8ffa32019-07-08 14:17:10 +02002633 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
David Sedlák81e04022019-04-05 15:05:46 +02002634
David Sedlákda8ffa32019-07-08 14:17:10 +02002635 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002636}
David Sedlák00250342019-06-21 14:19:39 +02002637
David Sedláke1a30302019-07-10 13:49:38 +02002638/**
2639 * @brief Parse config element.
2640 *
2641 * @param[in] ctx Yin parser context for logging and to store current state.
2642 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
2643 * @param[in,out] data Data to read from, always moved to currently handled character.
2644 * @param[in,out] flags Flags to add to.
2645 * @param[in,out] exts Extension instances to add to.
2646 *
2647 * @return LY_ERR values.
2648 */
2649static LY_ERR
2650yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2651 struct lysp_ext_instance **exts)
2652{
2653 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002654 struct yin_subelement subelems[1] = {
2655 {YANG_CUSTOM, NULL, 0}
2656 };
David Sedláke1a30302019-07-10 13:49:38 +02002657
David Sedlák1f90d252019-07-10 17:09:32 +02002658 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 +02002659 if (strcmp(temp_val, "true") == 0) {
2660 *flags |= LYS_CONFIG_W;
2661 } else if (strcmp(temp_val, "false") == 0) {
2662 *flags |= LYS_CONFIG_R;
2663 } else {
2664 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "config");
2665 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2666 return LY_EVALID;
2667 }
2668 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2669
2670 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
2671}
2672
David Sedlák3ffbc522019-07-02 17:49:28 +02002673LY_ERR
David Sedlák92147b02019-07-09 14:01:01 +02002674yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
2675 struct lysp_ext_instance **exts)
2676{
2677 const char *temp_version = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002678 struct yin_subelement subelems[1] = {
2679 {YANG_CUSTOM, NULL, 0}
2680 };
David Sedlák92147b02019-07-09 14:01:01 +02002681
David Sedlák1f90d252019-07-10 17:09:32 +02002682 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 +02002683 if (strcmp(temp_version, "1.0") == 0) {
2684 *version = LYS_VERSION_1_0;
2685 } else if (strcmp(temp_version, "1.1") == 0) {
2686 *version = LYS_VERSION_1_1;
2687 } else {
2688 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "yang-version");
2689 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2690 return LY_EVALID;
2691 }
2692 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
2693 ctx->mod_version = *version;
2694
2695 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
2696}
2697
2698LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002699yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_module *mod)
David Sedlák736fd0d2019-02-15 16:06:31 +01002700{
David Sedlák736fd0d2019-02-15 16:06:31 +01002701 struct lysp_import *imp;
David Sedlák00250342019-06-21 14:19:39 +02002702 /* allocate new element in sized array for import */
David Sedlákda8ffa32019-07-08 14:17:10 +02002703 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, mod->imports, imp, LY_EMEM);
David Sedlák3ffbc522019-07-02 17:49:28 +02002704
David Sedlák968ac342019-07-11 15:17:59 +02002705 struct yin_subelement subelems[5] = {
2706 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2707 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2708 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2709 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2710 {YANG_CUSTOM, NULL, 0}
2711 };
David Sedlák736fd0d2019-02-15 16:06:31 +01002712
David Sedlák92147b02019-07-09 14:01:01 +02002713 /* parse import attributes */
David Sedlák292763b2019-07-09 11:10:53 +02002714 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 +02002715 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
David Sedlák619db942019-07-03 14:47:30 +02002716 /* check prefix validity */
David Sedlákda8ffa32019-07-08 14:17:10 +02002717 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, mod->imports, mod->mod->prefix, &imp->prefix), LY_EVALID);
David Sedlák00250342019-06-21 14:19:39 +02002718
David Sedlákda8ffa32019-07-08 14:17:10 +02002719 return yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts);
David Sedlák736fd0d2019-02-15 16:06:31 +01002720}
2721
David Sedlák11900c82019-06-18 16:29:12 +02002722LY_ERR
David Sedlák1fdb2522019-07-09 16:22:57 +02002723yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
2724 struct lysp_ext_instance **exts)
2725{
2726 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002727 struct yin_subelement subelems[1] = {
2728 {YANG_CUSTOM, NULL, 0}
2729 };
David Sedlák1fdb2522019-07-09 16:22:57 +02002730
David Sedlák1f90d252019-07-10 17:09:32 +02002731 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 +02002732 if (strcmp(temp_val, "true") == 0) {
2733 *flags |= LYS_MAND_TRUE;
2734 } else if (strcmp(temp_val, "false") == 0) {
2735 *flags |= LYS_MAND_FALSE;
2736 } else {
2737 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "mandatory");
2738 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2739 return LY_EVALID;
2740 }
2741 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2742
2743 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
2744}
2745
2746LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002747yin_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 +02002748 struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +02002749{
David Sedlák3ffbc522019-07-02 17:49:28 +02002750 const char *value = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002751 struct yin_subelement subelems[1] = {
2752 {YANG_CUSTOM, NULL, 0}
2753 };
David Sedlák3ffbc522019-07-02 17:49:28 +02002754
David Sedlák292763b2019-07-09 11:10:53 +02002755 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 +02002756 if (strcmp(value, "current") == 0) {
2757 *flags |= LYS_STATUS_CURR;
2758 } else if (strcmp(value, "deprecated") == 0) {
2759 *flags |= LYS_STATUS_DEPRC;
2760 } else if (strcmp(value, "obsolete") == 0) {
2761 *flags |= LYS_STATUS_OBSLT;
2762 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002763 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "status");
2764 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002765 return LY_EVALID;
2766 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002767 FREE_STRING(ctx->xml_ctx.ctx, value);
David Sedlák11900c82019-06-18 16:29:12 +02002768
David Sedlákda8ffa32019-07-08 14:17:10 +02002769 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
David Sedlák11900c82019-06-18 16:29:12 +02002770}
2771
David Sedlák11900c82019-06-18 16:29:12 +02002772LY_ERR
David Sedlák32eee7b2019-07-09 12:38:44 +02002773yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
2774{
2775 struct lysp_when *when;
2776 when = calloc(1, sizeof *when);
2777 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1f90d252019-07-10 17:09:32 +02002778 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
David Sedlák32eee7b2019-07-09 12:38:44 +02002779 *when_p = when;
David Sedlák968ac342019-07-11 15:17:59 +02002780 struct yin_subelement subelems[3] = {
2781 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2782 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2783 {YANG_CUSTOM, NULL, 0}
2784 };
David Sedlák32eee7b2019-07-09 12:38:44 +02002785
2786 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
2787}
2788
2789LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002790yin_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 +02002791 uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák2721d3d2019-06-21 15:37:41 +02002792{
David Sedlák3ffbc522019-07-02 17:49:28 +02002793 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +02002794 struct yin_subelement subelems[1] = {
2795 {YANG_CUSTOM, NULL, 0}
2796 };
David Sedlák2721d3d2019-06-21 15:37:41 +02002797
David Sedlák1f90d252019-07-10 17:09:32 +02002798 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 +02002799 if (strcmp(temp_val, "true") == 0) {
2800 *flags |= LYS_YINELEM_TRUE;
2801 } else if (strcmp(temp_val, "false") == 0) {
2802 *flags |= LYS_YINELEM_FALSE;
2803 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002804 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
2805 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002806 return LY_EVALID;
2807 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002808 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlák2721d3d2019-06-21 15:37:41 +02002809
David Sedlákda8ffa32019-07-08 14:17:10 +02002810 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
David Sedlák2721d3d2019-06-21 15:37:41 +02002811}
2812
2813LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002814yin_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 +02002815 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002816{
2817 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002818 char *out;
2819 const char *name, *prefix;
2820 size_t out_len, prefix_len, name_len;
2821 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002822 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02002823 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
2824 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002825
David Sedlákda8ffa32019-07-08 14:17:10 +02002826 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002827
2828 e->yin = 0;
2829 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02002830 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02002831 e->insubstmt = subelem;
2832 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002833 e->yin |= LYS_YIN;
2834
David Sedlákb1a78352019-06-28 16:16:29 +02002835 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02002836 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02002837 if (!iter->prefix) {
2838 new_subelem = calloc(1, sizeof(*new_subelem));
2839 if (!e->child) {
2840 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002841 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02002842 last_subelem->next = new_subelem;
2843 }
2844 last_subelem = new_subelem;
2845
2846 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002847 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
2848 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002849 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002850 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
2851 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002852 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002853 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
2854 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002855 }
2856 }
2857 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02002858
David Sedlákf250ecf2019-07-01 11:02:05 +02002859 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002860 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2861 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002862 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002863 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2864 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02002865 if (!name) {
2866 /* end of extension instance reached */
2867 break;
2868 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002869 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02002870 if (!e->child) {
2871 e->child = new_subelem;
2872 } else {
2873 last_subelem->next = new_subelem;
2874 }
2875 last_subelem = new_subelem;
2876 }
David Sedlák555c7202019-07-04 12:14:12 +02002877 } else {
2878 /* save text content */
2879 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002880 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02002881 if (!e->argument) {
2882 free(out);
2883 return LY_EMEM;
2884 }
2885 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002886 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02002887 LY_CHECK_RET(!e->argument, LY_EMEM);
2888 }
David Sedlákda8ffa32019-07-08 14:17:10 +02002889 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02002890 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02002891 }
David Sedlákb1a78352019-06-28 16:16:29 +02002892 }
2893
2894 return LY_SUCCESS;
2895}
2896
2897LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02002898yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
2899 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02002900{
2901 LY_ERR ret = LY_SUCCESS;
2902 const char *temp_prefix, *temp_name;
2903 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02002904 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02002905 int dynamic;
2906 struct yin_arg_record *subelem_args = NULL;
2907 struct lysp_stmt *last = NULL, *new = NULL;
2908
2909 /* allocate new structure for element */
2910 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02002911 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
2912 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002913
2914 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02002915 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002916 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02002917 /* add new element to linked-list */
2918 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02002919 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02002920 if (!(*element)->child) {
2921 /* save first */
2922 (*element)->child = new;
2923 } else {
2924 last->next = new;
2925 }
2926 last = new;
2927
2928 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002929 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 +02002930 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002931 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002932 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02002933 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
2934 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002935 /* attributes with prefix are ignored */
2936 if (!temp_prefix) {
2937 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002938 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02002939 if (!last->arg) {
2940 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002941 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02002942 ret = LY_EMEM;
2943 goto err;
2944 }
2945 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002946 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2947 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002948 }
2949 }
2950 }
2951
2952 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002953 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02002954 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002955 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02002956 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02002957 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 +02002958 LY_CHECK_GOTO(ret, err);
2959 if (!name) {
2960 /* end of element reached */
2961 break;
2962 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002963 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02002964 LY_CHECK_GOTO(ret, err);
2965 last = last->next;
2966 }
2967 } else {
2968 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02002969 if (out_len != 0) {
2970 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002971 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02002972 if (!(*element)->arg) {
2973 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02002974 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02002975 ret = LY_EMEM;
2976 goto err;
2977 }
2978 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002979 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
2980 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02002981 }
David Sedlákb1a78352019-06-28 16:16:29 +02002982 }
2983 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02002984 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 +02002985 LY_CHECK_GOTO(ret, err);
2986 }
2987
David Sedlákda8ffa32019-07-08 14:17:10 +02002988 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02002989 return LY_SUCCESS;
2990
2991err:
David Sedlákda8ffa32019-07-08 14:17:10 +02002992 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002993 return ret;
2994}
2995
2996LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002997yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák3ffbc522019-07-02 17:49:28 +02002998 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
David Sedlák9494eb22019-06-21 16:06:53 +02002999{
David Sedlák968ac342019-07-11 15:17:59 +02003000 struct yin_subelement subelems[2] = {
3001 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
3002 {YANG_CUSTOM, NULL, 0}
3003 };
David Sedlák9494eb22019-06-21 16:06:53 +02003004
David Sedlák292763b2019-07-09 11:10:53 +02003005 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 +02003006
David Sedlákda8ffa32019-07-08 14:17:10 +02003007 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
David Sedlák9494eb22019-06-21 16:06:53 +02003008}
3009
3010LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02003011yin_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 +02003012{
David Sedlák11900c82019-06-18 16:29:12 +02003013 struct lysp_ext *ex;
David Sedlákda8ffa32019-07-08 14:17:10 +02003014 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
David Sedlák292763b2019-07-09 11:10:53 +02003015 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 +02003016
David Sedlák3ffbc522019-07-02 17:49:28 +02003017 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
David Sedlák968ac342019-07-11 15:17:59 +02003018 struct yin_subelement subelems[5] = {
3019 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
3020 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
3021 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
3022 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
3023 {YANG_CUSTOM, NULL, 0}
3024 };
David Sedlák11900c82019-06-18 16:29:12 +02003025
David Sedlákda8ffa32019-07-08 14:17:10 +02003026 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
David Sedlák11900c82019-06-18 16:29:12 +02003027}
3028
David Sedlák4f03b932019-07-26 13:01:47 +02003029LY_ERR
3030yin_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 +02003031{
David Sedlák4f03b932019-07-26 13:01:47 +02003032 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3033 struct tree_node_meta node_meta = {NULL, &mod->data};
3034 struct augment_meta aug_meta = {NULL, &mod->augments};
3035 struct grouping_meta grp_meta = {NULL, &mod->groupings};
3036 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
3037 struct notif_meta notif_meta = {NULL, &mod->notifs};
3038 struct action_meta act_meta = {NULL, &mod->rpcs};
3039 struct typedef_meta tpdf_meta = {NULL, &mod->typedefs};
3040 struct yin_subelement subelems[28] = {
3041 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3042 {YANG_ANYXML, &node_meta, 0},
3043 {YANG_AUGMENT, &aug_meta, 0},
3044 {YANG_CHOICE, &node_meta, 0},
3045 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
3046 {YANG_CONTAINER, &node_meta, 0},
3047 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
3048 {YANG_DEVIATION, &mod->deviations, 0},
3049 {YANG_EXTENSION, &mod->extensions, 0},
3050 {YANG_FEATURE, &mod->features, 0},
3051 {YANG_GROUPING, &grp_meta, 0},
3052 {YANG_IDENTITY, &mod->identities, 0},
3053 {YANG_IMPORT, mod, 0},
3054 {YANG_INCLUDE, &inc_meta, 0},
3055 {YANG_LEAF, &node_meta, 0},
3056 {YANG_LEAF_LIST, &node_meta, 0},
3057 {YANG_LIST, &node_meta, 0},
3058 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3059 {YANG_NOTIFICATION, &notif_meta, 0},
3060 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3061 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3062 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3063 {YANG_REVISION, &mod->revs, 0},
3064 {YANG_RPC, &act_meta, 0},
3065 {YANG_TYPEDEF, &tpdf_meta, 0},
3066 {YANG_USES, &node_meta, 0},
3067 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003068 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003069 };
David Sedlák3b4db242018-10-19 16:11:01 +02003070
David Sedlák4f03b932019-07-26 13:01:47 +02003071 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003072}
3073
3074LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +01003075yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003076{
David Sedláke4889912018-11-02 09:52:40 +01003077 LY_ERR ret = LY_SUCCESS;
3078 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003079 struct lysp_module *mod_p = NULL;
3080 const char *prefix, *name;
3081 size_t prefix_len, name_len;
David Sedlákda8ffa32019-07-08 14:17:10 +02003082
David Sedlák1f90d252019-07-10 17:09:32 +02003083 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003084
David Sedlákda8ffa32019-07-08 14:17:10 +02003085 struct yin_parser_ctx yin_ctx;
3086
3087 /* initialize context */
3088 memset(&yin_ctx, 0, sizeof yin_ctx);
3089 yin_ctx.xml_ctx.ctx = ctx;
3090 yin_ctx.xml_ctx.line = 1;
3091
David Sedláke4889912018-11-02 09:52:40 +01003092
David Sedlák3017da42019-02-15 09:48:04 +01003093 /* check submodule */
David Sedlákda8ffa32019-07-08 14:17:10 +02003094 ret = lyxml_get_element(&yin_ctx.xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003095 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1f90d252019-07-10 17:09:32 +02003096 ret = yin_load_attributes(&yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003097 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc1771b12019-07-10 15:55:46 +02003098 kw = yin_match_keyword(&yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003099 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +01003100 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
3101 ret = LY_EINVAL;
3102 goto cleanup;
3103 } else if (kw != YANG_MODULE) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003104 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 +02003105 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003106 ret = LY_EVALID;
3107 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003108 }
3109
David Sedlák3017da42019-02-15 09:48:04 +01003110 /* allocate module */
3111 mod_p = calloc(1, sizeof *mod_p);
3112 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3113 mod_p->mod = mod;
3114 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003115
David Sedlák00250342019-06-21 14:19:39 +02003116 /* parse module substatements */
David Sedlák4f03b932019-07-26 13:01:47 +02003117 ret = yin_parse_mod(&yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003118 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003119
David Sedlák3017da42019-02-15 09:48:04 +01003120 mod_p->parsing = 0;
3121 mod->parsed = mod_p;
3122
3123cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003124 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003125 lysp_module_free(mod_p);
3126 }
David Sedlák1f90d252019-07-10 17:09:32 +02003127 FREE_ARRAY(&yin_ctx, attrs, free_arg_rec);
David Sedlákda8ffa32019-07-08 14:17:10 +02003128 lyxml_context_clear(&yin_ctx.xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +01003129 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003130}