blob: 50b8b8eef36694f364f1b3334864ecbfa63253bd [file] [log] [blame]
David Sedlákf824ad52018-10-14 23:58:15 +02001/**
2 * @file parser_yin.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
David Sedlák3b4db242018-10-19 16:11:01 +02004 * @brief YIN parser.
5 *
David Sedlákb1ce3f82019-06-05 14:37:26 +02006 * Copyright (c) 2015 - 2019 CESNET, z.s.p.o.
David Sedlák3b4db242018-10-19 16:11:01 +02007 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
David Sedlákf824ad52018-10-14 23:58:15 +020013 */
David Sedlákecf5eb82019-06-03 14:12:44 +020014#include "common.h"
15
David Sedlák3ffbc522019-07-02 17:49:28 +020016#include <assert.h>
David Sedlák3b4db242018-10-19 16:11:01 +020017#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020020#include <string.h>
David Sedlákd6e56892019-07-01 15:40:24 +020021#include <stdbool.h>
David Sedlák5545f5d2019-07-11 11:55:16 +020022#include <errno.h>
David Sedlákf75d55e2019-07-12 16:52:50 +020023#include <ctype.h>
David Sedlákf824ad52018-10-14 23:58:15 +020024
David Sedlákf824ad52018-10-14 23:58:15 +020025#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020026#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020027#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020028#include "tree.h"
29#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020030#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020031#include "parser_yin.h"
David Sedlák00250342019-06-21 14:19:39 +020032
David Sedlák2b214ac2019-06-06 16:11:03 +020033/**
34 * @brief check if given string is URI of yin namespace.
David Sedlák8985a142019-07-31 16:43:06 +020035 *
David Sedlák2b214ac2019-06-06 16:11:03 +020036 * @param ns Namespace URI to check.
37 *
38 * @return true if ns equals YIN_NS_URI false otherwise.
39 */
40#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
41
David Sedlákf6251182019-06-06 10:22:13 +020042const char *const yin_attr_list[] = {
43 [YIN_ARG_NAME] = "name",
44 [YIN_ARG_TARGET_NODE] = "target-node",
45 [YIN_ARG_MODULE] = "module",
46 [YIN_ARG_VALUE] = "value",
47 [YIN_ARG_TEXT] = "text",
48 [YIN_ARG_CONDITION] = "condition",
49 [YIN_ARG_URI] = "uri",
50 [YIN_ARG_DATE] = "date",
51 [YIN_ARG_TAG] = "tag",
David Sedlákf6251182019-06-06 10:22:13 +020052};
53
David Sedlák1bccdfa2019-06-17 15:55:27 +020054enum yang_keyword
David Sedlákc1771b12019-07-10 15:55:46 +020055yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
56 const char *prefix, size_t prefix_len, enum yang_keyword parrent)
David Sedlák1bccdfa2019-06-17 15:55:27 +020057{
David Sedlák8f7a1172019-06-20 14:42:18 +020058 const char *start = NULL;
59 enum yang_keyword kw = YANG_NONE;
60 const struct lyxml_ns *ns = NULL;
61
62 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020063 return YANG_NONE;
64 }
65
David Sedlákda8ffa32019-07-08 14:17:10 +020066 ns = lyxml_ns_get(&ctx->xml_ctx, prefix, prefix_len);
David Sedlák8f7a1172019-06-20 14:42:18 +020067 if (ns) {
68 if (!IS_YIN_NS(ns->uri)) {
69 return YANG_CUSTOM;
70 }
71 } else {
72 /* elements without namespace are automatically unknown */
73 return YANG_NONE;
74 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020075
David Sedlák8f7a1172019-06-20 14:42:18 +020076 start = name;
77 kw = lysp_match_kw(NULL, &name);
78
79 if (name - start == (long int)name_len) {
David Sedlákc1771b12019-07-10 15:55:46 +020080 /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
81 if (kw == YANG_VALUE && parrent == YANG_ERROR_MESSAGE) {
82 return YIN_VALUE;
83 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020084 return kw;
85 } else {
David Sedlák3ffbc522019-07-02 17:49:28 +020086 if (strncmp(start, "text", name_len) == 0) {
87 return YIN_TEXT;
David Sedlák3ffbc522019-07-02 17:49:28 +020088 } else {
89 return YANG_NONE;
90 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020091 }
92}
93
David Sedlákc5b20842019-08-13 10:18:31 +020094enum yin_argument
David Sedlák060b00e2019-06-19 11:12:06 +020095yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +020096{
David Sedlákc5b20842019-08-13 10:18:31 +020097 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +020098 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +020099 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200100
David Sedlák94de2aa2019-02-15 12:42:11 +0100101#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
102#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100103#define IF_ARG_PREFIX_END }
104
David Sedlák1c8b2702019-02-22 11:03:02 +0100105 switch (*name) {
David Sedlák94de2aa2019-02-15 12:42:11 +0100106 case 'c':
107 already_read += 1;
108 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200109 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200110
David Sedlák94de2aa2019-02-15 12:42:11 +0100111 case 'd':
112 already_read += 1;
113 IF_ARG("ate", 3, YIN_ARG_DATE);
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 'm':
117 already_read += 1;
118 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200119 break;
120
David Sedlák94de2aa2019-02-15 12:42:11 +0100121 case 'n':
122 already_read += 1;
123 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200124 break;
125
David Sedlák94de2aa2019-02-15 12:42:11 +0100126 case 't':
127 already_read += 1;
128 IF_ARG_PREFIX("a", 1)
129 IF_ARG("g", 1, YIN_ARG_TAG)
130 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
131 IF_ARG_PREFIX_END
132 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200133 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200134
David Sedlák94de2aa2019-02-15 12:42:11 +0100135 case 'u':
136 already_read += 1;
137 IF_ARG("ri", 2, YIN_ARG_URI)
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 'v':
141 already_read += 1;
142 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200143 break;
144 }
145
David Sedlákc10e7902018-12-17 02:17:59 +0100146 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200147 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200148 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200149 }
150
David Sedlák18730132019-03-15 15:51:34 +0100151#undef IF_ARG
152#undef IF_ARG_PREFIX
153#undef IF_ARG_PREFIX_END
154
David Sedlák872c7b42018-10-26 13:15:20 +0200155 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200156}
157
David Sedlák4f03b932019-07-26 13:01:47 +0200158void free_arg_rec(struct yin_parser_ctx *ctx, struct yin_arg_record *record) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200159 (void)ctx; /* unused */
David Sedlákd2d676a2019-07-22 11:28:19 +0200160 if (record && record->dynamic_content) {
David Sedlák00250342019-06-21 14:19:39 +0200161 free(record->content);
162 }
163}
164
David Sedlák8f7a1172019-06-20 14:42:18 +0200165LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200166yin_load_attributes(struct yin_parser_ctx *ctx, const char **data, struct yin_arg_record **attrs)
David Sedláka7406952019-04-05 10:33:07 +0200167{
168 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200169 struct yin_arg_record *argument_record = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +0200170 const char *prefix, *name;
171 size_t prefix_len, name_len;
David Sedláka7406952019-04-05 10:33:07 +0200172
David Sedlák555c7202019-07-04 12:14:12 +0200173 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200174 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákc5b20842019-08-13 10:18:31 +0200175 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +0200176 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200177
David Sedlákda8ffa32019-07-08 14:17:10 +0200178 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
179 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +0200180 argument_record->name = name;
181 argument_record->name_len = name_len;
182 argument_record->prefix = prefix;
183 argument_record->prefix_len = prefix_len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200184 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200185 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200186 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200187 }
188 }
189
David Sedlák8f7a1172019-06-20 14:42:18 +0200190cleanup:
191 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200192 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200193 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200194 }
195 return ret;
196}
197
David Sedlák4a650532019-07-10 11:55:18 +0200198LY_ERR
199yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
200{
201 int prefix = 0;
202 unsigned int c;
203 size_t utf8_char_len;
204 size_t already_read = 0;
205 while (already_read < len) {
206 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
207 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
208 already_read += utf8_char_len;
209 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
210
211 switch (val_type) {
212 case Y_IDENTIF_ARG:
213 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
214 break;
215 case Y_PREF_IDENTIF_ARG:
216 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
217 break;
218 case Y_STR_ARG:
219 case Y_MAYBE_STR_ARG:
220 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
221 break;
222 }
223 }
224
225 return LY_SUCCESS;
226}
227
David Sedlákb4e44562019-07-04 15:42:12 +0200228/**
229 * @brief Parse yin argument.
230 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200231 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200232 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200233 * @param[in,out] data Data to read from.
David Sedlák4a650532019-07-10 11:55:18 +0200234 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
235 * special argument).
David Sedlákb4e44562019-07-04 15:42:12 +0200236 * @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 +0200237 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200238 * @param[in] current_element Identification of current element, used for logging.
239 *
240 * @return LY_ERR values.
241 */
242static LY_ERR
David Sedlákc5b20842019-08-13 10:18:31 +0200243yin_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 +0200244 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200245{
David Sedlákc5b20842019-08-13 10:18:31 +0200246 enum yin_argument arg = YIN_ARG_UNKNOWN;
David Sedlák8f7a1172019-06-20 14:42:18 +0200247 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200248 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200249
David Sedlák1bccdfa2019-06-17 15:55:27 +0200250 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200251 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200252 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
253 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200254 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200255 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200256 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200257 } else if (arg == arg_type) {
David Sedlák1538a842019-08-08 15:38:51 +0200258 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_DUP_ATTR,
David Sedlák292763b2019-07-09 11:10:53 +0200259 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200260 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200261 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200262 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200263 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200264 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200265 /* string is no longer supposed to be freed when the sized array is freed */
266 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200267 } else {
David Sedlák99295322019-07-17 11:34:18 +0200268 if (iter->content_len == 0) {
269 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
270 } else {
271 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
272 LY_CHECK_RET(!(*arg_val), LY_EMEM);
273 }
David Sedlák57715b12019-06-17 13:05:22 +0200274 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200275 } else {
David Sedlák1538a842019-08-08 15:38:51 +0200276 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_ATTR, iter->name_len, iter->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200277 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200278 }
279 }
280 }
281
David Sedlák292763b2019-07-09 11:10:53 +0200282 /* anything else than Y_MAYBE_STR_ARG is mandatory */
283 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200284 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 +0200285 return LY_EVALID;
286 }
287
288 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200289}
290
David Sedlákd6e56892019-07-01 15:40:24 +0200291/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200292 * @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 +0200293 *
294 * @param[in] type Type of wanted record.
295 * @param[in] array_size Size of array.
296 * @param[in] array Searched array.
297 *
298 * @return Pointer to desired record on success, NULL if element is not in the array.
299 */
David Sedlákb4e44562019-07-04 15:42:12 +0200300static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200301get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200302{
David Sedlákb0faad82019-07-04 14:28:59 +0200303 signed char left = 0, right = array_size - 1, middle;
304
305 while (left <= right) {
306 middle = left + (right - left) / 2;
307
308 if (array[middle].type == type) {
309 return &array[middle];
310 }
311
312 if (array[middle].type < type) {
313 left = middle + 1;
314 } else {
315 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200316 }
317 }
318
319 return NULL;
320}
321
David Sedlákbba38e52019-07-09 15:20:01 +0200322/**
323 * @brief Helper function to check mandatory constraint of subelement.
324 *
325 * @param[in,out] ctx Yin parser context for logging and to store current state.
326 * @param[in] subelem_info Array of information about subelements.
327 * @param[in] subelem_info_size Size of subelem_info array.
328 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
329 *
330 * @return LY_ERR values.
331 */
332static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200333yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200334 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200335{
David Sedlákb0faad82019-07-04 14:28:59 +0200336 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200337 /* 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 +0200338 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlák1538a842019-08-08 15:38:51 +0200339 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
David Sedlák555c7202019-07-04 12:14:12 +0200340 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200341 return LY_EVALID;
342 }
343 }
344
345 return LY_SUCCESS;
346}
347
David Sedlákbba38e52019-07-09 15:20:01 +0200348/**
349 * @brief Helper function to check "first" constraint of subelement.
350 *
351 * @param[in,out] ctx Yin parser context for logging and to store current state.
352 * @param[in] subelem_info Array of information about subelements.
353 * @param[in] subelem_info_size Size of subelem_info array.
354 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
355 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement.
356 *
357 * @return LY_ERR values.
358 */
359static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200360yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200361 signed char subelem_info_size, enum yang_keyword current_element,
362 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200363{
David Sedlákb0faad82019-07-04 14:28:59 +0200364 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200365 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlák1538a842019-08-08 15:38:51 +0200366 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
367 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200368 return LY_EVALID;
369 }
370 }
371
372 return LY_SUCCESS;
373}
374
David Sedlákbba38e52019-07-09 15:20:01 +0200375/**
376 * @brief Helper function to check if array of information about subelements is in ascending order.
377 *
378 * @param[in] subelem_info Array of information about subelements.
379 * @param[in] subelem_info_size Size of subelem_info array.
380 *
381 * @return True iff subelem_info array is in ascending order, False otherwise.
382 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200383#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200384static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200385is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
386{
David Sedlák292763b2019-07-09 11:10:53 +0200387 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200388
389 for (signed char i = 0; i < subelem_info_size; ++i) {
390 if (subelem_info[i].type <= current) {
391 return false;
392 }
393 current = subelem_info[i].type;
394 }
395
396 return true;
397}
David Sedlák5545f5d2019-07-11 11:55:16 +0200398#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200399
David Sedlákd6e56892019-07-01 15:40:24 +0200400/**
David Sedlákb4e44562019-07-04 15:42:12 +0200401 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
402 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200403 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200404 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200405 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200406 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200407 * @param[in] kw Type of current element.
408 * @param[out] value Where value of attribute should be stored.
409 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200410 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákda8ffa32019-07-08 14:17:10 +0200411 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200412 *
David Sedlákd6e56892019-07-01 15:40:24 +0200413 * @return LY_ERR values.
414 */
David Sedlákb4e44562019-07-04 15:42:12 +0200415static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200416yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200417 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 +0200418{
David Sedlák1f90d252019-07-10 17:09:32 +0200419 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200420 struct yin_subelement subelems[1] = {
421 {YANG_CUSTOM, NULL, 0}
422 };
David Sedlákb4e44562019-07-04 15:42:12 +0200423
David Sedlákda8ffa32019-07-08 14:17:10 +0200424 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200425}
426
427/**
David Sedlákd3983112019-07-12 11:20:56 +0200428 * @brief Parse pattern element.
429 *
430 * @param[in,out] ctx Yin parser context for logging and to store current state.
431 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
432 * @param[in,out] data Data to read from, always moved to currently handled character.
433 * @param[in,out] patterns Restrictions to add to.
434 *
435 * @return LY_ERR values.
436 */
437static LY_ERR
438yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
439 struct lysp_type *type)
440{
441 const char *real_value = NULL;
442 char *saved_value = NULL;
443 struct lysp_restr *restr;
444
445 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
446 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
447 size_t len = strlen(real_value);
448
449 saved_value = malloc(len + 2);
450 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
451 memmove(saved_value + 1, real_value, len);
452 FREE_STRING(ctx->xml_ctx.ctx, real_value);
453 saved_value[0] = 0x06;
454 saved_value[len + 1] = '\0';
455 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
456 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
457 type->flags |= LYS_SET_PATTERN;
458
459 struct yin_subelement subelems[6] = {
460 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
461 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
462 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
463 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
464 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
465 {YANG_CUSTOM, NULL, 0}
466 };
467 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
468}
469
David Sedlákc5b20842019-08-13 10:18:31 +0200470/**
471 * @brief Parse fraction-digits element.
472 *
473 * @param[in,out] ctx Yin parser context for logging and to store current state.
474 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
475 * @param[in,out] data Data to read from, always moved to currently handled character.
476 * @param[in,out] type Type structure to store value, flags and extension instances.
477 *
478 * @return LY_ERR values.
479 */
David Sedlákf75d55e2019-07-12 16:52:50 +0200480static LY_ERR
481yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
482 struct lysp_type *type)
483{
484 const char *temp_val = NULL;
485 char *ptr;
486 unsigned long int num;
487
488 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
489
490 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
David Sedlák1538a842019-08-08 15:38:51 +0200491 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200492 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
493 return LY_EVALID;
494 }
495
496 errno = 0;
497 num = strtoul(temp_val, &ptr, 10);
498 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200499 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200500 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
501 return LY_EVALID;
502 }
503 if ((errno == ERANGE) || (num > 18)) {
David Sedlák1538a842019-08-08 15:38:51 +0200504 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
David Sedlákf75d55e2019-07-12 16:52:50 +0200505 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
506 return LY_EVALID;
507 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200508 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200509 type->fraction_digits = num;
510 type->flags |= LYS_SET_FRDIGITS;
511 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200512 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200513 };
514 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
515}
516
David Sedlák07869a52019-07-12 14:28:19 +0200517/**
David Sedlák43801c92019-08-05 15:58:54 +0200518 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200519 *
520 * @param[in,out] ctx YIN parser context for logging and to store current state.
521 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
522 * @param[in,out] data Data to read from, always moved to currently handled character.
523 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
David Sedlákc5b20842019-08-13 10:18:31 +0200524 * @param[in,out] type Type structure to store enum value, flags and extension instances.
David Sedlák07869a52019-07-12 14:28:19 +0200525 *
526 * @return LY_ERR values.
527 */
David Sedlákca36c422019-07-12 12:47:55 +0200528static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200529yin_parse_enum(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
David Sedlákca36c422019-07-12 12:47:55 +0200530{
David Sedlák07869a52019-07-12 14:28:19 +0200531 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200532
David Sedlák43801c92019-08-05 15:58:54 +0200533 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
534 type->flags |= LYS_SET_ENUM;
535 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
536 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
537 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
538 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200539
540 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200541 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
542 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200543 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
544 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200545 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200546 {YANG_CUSTOM, NULL, 0}
547 };
David Sedlák43801c92019-08-05 15:58:54 +0200548 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
549}
550
551/**
552 * @brief Parse bit element.
553 *
554 * @param[in,out] ctx YIN parser context for logging and to store current state.
555 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
556 * @param[in,out] data Data to read from, always moved to currently handled character.
557 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
David Sedlákc5b20842019-08-13 10:18:31 +0200558 * @param[in,out] type Type structure to store bit value, flags and extension instances.
David Sedlák43801c92019-08-05 15:58:54 +0200559 *
560 * @return LY_ERR values.
561 */
562static LY_ERR
563yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
564 struct lysp_type *type)
565{
566 struct lysp_type_enum *en;
567
568 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
569 type->flags |= LYS_SET_BIT;
570 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
571 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
572
573 struct yin_subelement subelems[6] = {
574 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
575 {YANG_IF_FEATURE, &en->iffeatures, 0},
576 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
577 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
578 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
579 {YANG_CUSTOM, NULL, 0}
580 };
581 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200582}
583
David Sedlákd3983112019-07-12 11:20:56 +0200584/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200585 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
586 * more instances, such as base or if-feature.
587 *
588 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200589 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200590 * @param[in,out] data Data to read from, always moved to currently handled character.
591 * @param[in] kw Type of current element.
592 * @param[out] values Parsed values to add to.
593 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200594 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200595 * @param[in,out] exts Extension instance to add to.
596 *
597 * @return LY_ERR values.
598 */
599static LY_ERR
600yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlákc5b20842019-08-13 10:18:31 +0200601 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 +0200602{
603 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200604 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200605 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200606 struct yin_subelement subelems[1] = {
607 {YANG_CUSTOM, &index, 0}
608 };
609
David Sedlák1f90d252019-07-10 17:09:32 +0200610 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200611
612 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
613}
614
615/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200616 * @brief Parse require instance element.
617 *
618 * @param[in,out] ctx Yin parser context for logging and to store current state.
619 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
620 * @param[in,out] data Data to read from, always moved to currently handled character.
621 * @prama[out] type Type structure to store value, flag and extensions.
622 *
623 * @return LY_ERR values.
624 */
625static LY_ERR
626yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
627 const char **data, struct lysp_type *type)
628{
629 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200630 struct yin_subelement subelems[1] = {
631 {YANG_CUSTOM, NULL, 0}
632 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200633
634 type->flags |= LYS_SET_REQINST;
635 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
636 if (strcmp(temp_val, "true") == 0) {
637 type->require_instance = 1;
638 } else if (strcmp(temp_val, "false") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200639 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "require-instance");
David Sedlákcf5569a2019-07-11 13:31:34 +0200640 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
641 return LY_EVALID;
642 }
643 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
644
645 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
646}
647
648/**
David Sedlákce77bf52019-07-11 16:59:31 +0200649 * @brief Parse modifier element.
650 *
651 * @param[in,out] ctx Yin parser context for logging and to store current state.
652 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
653 * @param[in,out] data Data to read from, always moved to currently handled character.
654 * @param[in,out] pat Value to write to.
655 * @param[in,out] exts Extension instances to add to.
656 *
657 * @return LY_ERR values.
658 */
659static LY_ERR
660yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
661 const char **pat, struct lysp_ext_instance **exts)
662{
David Sedlákd3983112019-07-12 11:20:56 +0200663 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200664 const char *temp_val;
665 char *modified_val;
666 struct yin_subelement subelems[1] = {
667 {YANG_CUSTOM, NULL, 0}
668 };
669
670 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
671 if (strcmp(temp_val, "invert-match") != 0) {
David Sedlák1538a842019-08-08 15:38:51 +0200672 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "modifier");
David Sedlákce77bf52019-07-11 16:59:31 +0200673 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
674 return LY_EVALID;
675 }
David Sedlákd3983112019-07-12 11:20:56 +0200676 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200677
678 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200679 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200680 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200681 strcpy(modified_val, *pat);
682 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200683
684 /* modify the new value */
685 modified_val[0] = 0x15;
686 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
687
688 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
689}
690
691/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200692 * @brief Parse a restriction element (length, range or one instance of must).
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] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
698 * @param[in]
699 */
700static LY_ERR
701yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
702 enum yang_keyword restr_kw, struct lysp_restr *restr)
703{
704 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
705 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200706 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
707 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
708 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
709 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
710 {YANG_CUSTOM, NULL, 0}
711 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200712 /* argument of must is called condition, but argument of length and range is called value */
David Sedlákc5b20842019-08-13 10:18:31 +0200713 enum yin_argument arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
David Sedlákb7296dd2019-07-11 14:58:38 +0200714 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
715
716 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
717}
718
719/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200720 * @brief Parse must element.
721 *
722 * @param[in,out] ctx YIN parser context for logging and to store current state.
723 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
724 * @param[in,out] data Data to read from, always moved to currently handled character.
725 * @param[in,out] restrs Restrictions to add to.
726 *
727 * @return LY_ERR values.
728 */
729static LY_ERR
730yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
731{
732 struct lysp_restr *restr;
733
734 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
735 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
736}
737
738/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200739 * @brief Parse position or value element.
740 *
741 * @param[in,out] ctx YIN parser context for logging and to store current state.
742 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
743 * @param[in,out] data Data to read from, always moved to currently handled character.
744 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
745 * @param[out] enm Enum structure to save value, flags and extensions.
746 *
747 * @return LY_ERR values.
748 */
749static LY_ERR
750yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
751 enum yang_keyword kw, struct lysp_type_enum *enm)
752{
753 assert(kw == YANG_POSITION || kw == YANG_VALUE);
754 const char *temp_val = NULL;
755 char *ptr;
756 long int num;
757 unsigned long int unum;
758
759 /* set value flag */
760 enm->flags |= LYS_SET_VALUE;
761
762 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200763 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 +0200764 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
765 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák1538a842019-08-08 15:38:51 +0200766 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200767 goto error;
768 }
769
770 /* convert value */
771 errno = 0;
772 if (kw == YANG_VALUE) {
773 num = strtol(temp_val, &ptr, 10);
774 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
David Sedlák1538a842019-08-08 15:38:51 +0200775 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200776 goto error;
777 }
778 } else {
779 unum = strtoul(temp_val, &ptr, 10);
780 if (unum > UINT64_C(4294967295)) {
David Sedlák1538a842019-08-08 15:38:51 +0200781 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200782 goto error;
783 }
784 }
785 /* check if whole argument value was converted */
786 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200787 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +0200788 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200789 }
790 if (errno == ERANGE) {
David Sedlák1538a842019-08-08 15:38:51 +0200791 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", ly_stmt2str(kw));
David Sedlák5545f5d2019-07-11 11:55:16 +0200792 goto error;
793 }
794 /* save correctly ternary operator can't be used because num and unum have different signes */
795 if (kw == YANG_VALUE) {
796 enm->value = num;
797 } else {
798 enm->value = unum;
799 }
800 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
801
802 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200803 struct yin_subelement subelems[1] = {
804 {YANG_CUSTOM, NULL, 0}
805 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200806 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
807
808 error:
809 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
810 return LY_EVALID;
811}
812
David Sedlák05404f62019-07-24 14:11:53 +0200813
814/**
815 * @brief Parse belongs-to element.
816 *
817 * @param[in] ctx Yin parser context for logging and to store current state.
818 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
819 * @param[in,out] data Data to read from, always moved to currently handled character.
820 * @param[out] submod Structure of submodule that is being parsed.
821 * @param[in,out] exts Extension instances to add to.
822 *
823 * @return LY_ERR values
824 */
825static LY_ERR
826yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
827 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
828{
829 struct yin_subelement subelems[2] = {
830 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
831 {YANG_CUSTOM, NULL, 0}
832 };
833 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
834
835 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
836}
837
David Sedlák5545f5d2019-07-11 11:55:16 +0200838/**
David Sedlákc1771b12019-07-10 15:55:46 +0200839 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200840 * text element as child
841 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200842 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200843 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200844 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200845 * @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 +0200846 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200847 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200848 *
849 * @return LY_ERR values.
850 */
851static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200852yin_parse_meta_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
853 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200854{
855 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
856
David Sedlák968ac342019-07-11 15:17:59 +0200857 struct yin_subelement subelems[2] = {
858 {YANG_CUSTOM, NULL, 0},
859 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
860 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200861 /* check attributes */
862 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, elem_type));
David Sedlákb4e44562019-07-04 15:42:12 +0200863
David Sedlákdf2a9732019-08-07 13:23:16 +0200864 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +0200865 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200866}
867
868/**
David Sedlákc1771b12019-07-10 15:55:46 +0200869 * @brief Parse error-message element.
870 *
871 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200872 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +0200873 * @param[in,out] data Data to read from.
874 * @param[out] value Where the content of error-message element should be stored.
875 * @param[in,out] exts Extension instance to add to.
876 *
877 * @return LY_ERR values.
878 */
879static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200880yin_parse_err_msg_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
881 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +0200882{
David Sedlák968ac342019-07-11 15:17:59 +0200883 struct yin_subelement subelems[2] = {
884 {YANG_CUSTOM, NULL, 0},
885 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
886 };
David Sedlákc1771b12019-07-10 15:55:46 +0200887
David Sedlákdf2a9732019-08-07 13:23:16 +0200888 /* check attributes */
889 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
890
David Sedlákc1771b12019-07-10 15:55:46 +0200891 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
892}
893
894/**
David Sedlák374d2b32019-07-17 15:06:55 +0200895 * @brief parse type element.
896 *
897 * @brief Parse position or value element.
898 *
899 * @param[in,out] ctx YIN parser context for logging and to store current state.
900 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
901 * @param[in,out] data Data to read from, always moved to currently handled character.
902 * @param[in,out] type Type to wrote to.
903 * @param[in,out] exts Extension instance to add to.
904 *
905 * @return LY_ERR values.
906 */
907static LY_ERR
908yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
909{
910 struct yin_subelement subelems[11] = {
911 {YANG_BASE, type, 0},
912 {YANG_BIT, type, 0},
913 {YANG_ENUM, type, 0},
914 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
915 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
916 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
917 {YANG_PATTERN, type, 0},
918 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
919 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
920 {YANG_TYPE, type},
921 {YANG_CUSTOM, NULL, 0},
922 };
923 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
924 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
925}
926
David Sedlák1af868e2019-07-17 17:03:14 +0200927/**
928 * @brief Parse max-elements element.
929 *
930 * @param[in,out] ctx YIN parser context for logging and to store current state.
931 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
932 * @param[in,out] data Data to read from, always moved to currently handled character.
933 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200934 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +0200935 * @param[in,out] exts Extension instances to add to.
936 *
937 * @return LY_ERR values.
938 */
939static LY_ERR
940yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
941 uint16_t *flags, struct lysp_ext_instance **exts)
942{
943 const char *temp_val = NULL;
944 char *ptr;
945 unsigned long int num;
946 struct yin_subelement subelems[1] = {
947 {YANG_CUSTOM, NULL, 0},
948 };
David Sedlák374d2b32019-07-17 15:06:55 +0200949
David Sedlák1af868e2019-07-17 17:03:14 +0200950 *flags |= LYS_SET_MAX;
951 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
952 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
David Sedlák1538a842019-08-08 15:38:51 +0200953 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +0200954 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
955 return LY_EVALID;
956 }
957
958 if (strcmp(temp_val, "unbounded")) {
959 errno = 0;
960 num = strtoul(temp_val, &ptr, 10);
961 if (*ptr != '\0') {
David Sedlák1538a842019-08-08 15:38:51 +0200962 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +0200963 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
964 return LY_EVALID;
965 }
966 if ((errno == ERANGE) || (num > UINT32_MAX)) {
David Sedlák1538a842019-08-08 15:38:51 +0200967 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
David Sedlák1af868e2019-07-17 17:03:14 +0200968 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
969 return LY_EVALID;
970 }
971 *max = num;
972 }
973 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
974 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
975}
David Sedlák374d2b32019-07-17 15:06:55 +0200976
977/**
David Sedlák09e18c92019-07-18 11:17:11 +0200978 * @brief Parse max-elements element.
979 *
980 * @param[in,out] ctx YIN parser context for logging and to store current state.
981 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
982 * @param[in,out] data Data to read from, always moved to currently handled character.
983 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200984 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +0200985 * @param[in,out] exts Extension instances to add to.
986 *
987 * @return LY_ERR values.
988 */
989static LY_ERR
990yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
991 uint16_t *flags, struct lysp_ext_instance **exts)
992{
993 const char *temp_val = NULL;
994 char *ptr;
995 unsigned long int num;
996 struct yin_subelement subelems[1] = {
997 {YANG_CUSTOM, NULL, 0},
998 };
999
1000 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +02001001 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 +02001002
1003 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
David Sedlák1538a842019-08-08 15:38:51 +02001004 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001005 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1006 return LY_EVALID;
1007 }
1008
1009 errno = 0;
1010 num = strtoul(temp_val, &ptr, 10);
1011 if (ptr[0] != 0) {
David Sedlák1538a842019-08-08 15:38:51 +02001012 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001013 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1014 return LY_EVALID;
1015 }
1016 if (errno == ERANGE || num > UINT32_MAX) {
David Sedlák1538a842019-08-08 15:38:51 +02001017 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
David Sedlák09e18c92019-07-18 11:17:11 +02001018 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1019 return LY_EVALID;
1020 }
1021 *min = num;
1022 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001023 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001024}
1025
David Sedláka2dad212019-07-18 12:45:19 +02001026/**
1027 * @brief Parse min-elements or max-elements element.
1028 *
1029 * @param[in,out] ctx YIN parser context for logging and to store current state.
1030 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1031 * @param[in,out] data Data to read from, always moved to currently handled character.
1032 * @param[in] parent Identification of parent element.
1033 * @param[in] current Identification of current element.
1034 * @param[in] dest Where the parsed value and flags should be stored.
1035 *
1036 * @return LY_ERR values.
1037 */
David Sedlák09e18c92019-07-18 11:17:11 +02001038static LY_ERR
1039yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1040 enum yang_keyword parent, enum yang_keyword current, void *dest)
1041{
1042 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001043 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001044 uint32_t *lim;
1045 uint16_t *flags;
1046 struct lysp_ext_instance **exts;
1047
1048 if (parent == YANG_LEAF_LIST) {
1049 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1050 flags = &((struct lysp_node_leaflist *)dest)->flags;
1051 exts = &((struct lysp_node_leaflist *)dest)->exts;
1052 } else if (parent == YANG_REFINE) {
1053 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1054 flags = &((struct lysp_refine *)dest)->flags;
1055 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001056 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001057 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1058 flags = &((struct lysp_node_list *)dest)->flags;
1059 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001060 } else {
1061 lim = ((struct minmax_dev_meta *)dest)->lim;
1062 flags = ((struct minmax_dev_meta *)dest)->flags;
1063 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001064 }
1065
1066 if (current == YANG_MAX_ELEMENTS) {
1067 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1068 } else {
1069 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1070 }
1071
1072 return LY_SUCCESS;
1073}
1074
1075/**
David Sedláka2dad212019-07-18 12:45:19 +02001076 * @brief Parser ordered-by element.
1077 *
1078 * @param[in,out] ctx YIN parser context for logging and to store current state.
1079 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1080 * @param[in,out] data Data to read from, always moved to currently handled character.
1081 * @param[out] flags Flags to write to.
1082 * @param[in,out] exts Extension instance to add to.
1083 *
1084 * @return LY_ERR values.
1085 */
1086static LY_ERR
1087yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1088 uint16_t *flags, struct lysp_ext_instance **exts)
1089{
1090 const char *temp_val;
1091 struct yin_subelement subelems[1] = {
1092 {YANG_CUSTOM, NULL, 0},
1093 };
1094
1095 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1096 if (strcmp(temp_val, "system") == 0) {
1097 *flags |= LYS_ORDBY_SYSTEM;
1098 } else if (strcmp(temp_val, "user") == 0) {
1099 *flags |= LYS_ORDBY_USER;
1100 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001101 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "ordered-by");
David Sedláka2dad212019-07-18 12:45:19 +02001102 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1103 return LY_EVALID;
1104 }
1105 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1106
1107 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1108}
1109
1110/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001111 * @brief parse any-data or any-xml element.
1112 *
1113 * @param[in,out] ctx YIN parser context for logging and to store current state.
1114 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1115 * @param[in,out] data Data to read from, always moved to currently handled character.
1116 * @param[in] any_kw Identification of current element, can be set to YANG_ANY_DATA or YANG_ANY_XML
David Sedlákad83cf92019-08-13 12:53:53 +02001117 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001118 *
1119 * @return LY_ERR values.
1120 */
1121static LY_ERR
1122yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1123 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1124{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001125 struct lysp_node_anydata *any;
1126
David Sedlák8d552d62019-08-06 15:29:05 +02001127 /* create new sibling */
1128 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001129 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1130 any->parent = node_meta->parent;
1131
David Sedlák8a83bbb2019-07-18 14:46:00 +02001132 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001133 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 +02001134
1135 struct yin_subelement subelems[9] = {
1136 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1137 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1138 {YANG_IF_FEATURE, &any->iffeatures, 0},
1139 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1140 {YANG_MUST, &any->musts, 0},
1141 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1142 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1143 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1144 {YANG_CUSTOM, NULL, 0},
1145 };
1146 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1147}
1148
1149/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001150 * @brief parse leaf element.
1151 *
1152 * @param[in,out] ctx YIN parser context for logging and to store current state.
1153 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1154 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001155 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák203ca3a2019-07-18 15:26:25 +02001156 *
1157 * @return LY_ERR values.
1158 */
1159static LY_ERR
1160yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1161 struct tree_node_meta *node_meta)
1162{
David Sedlák203ca3a2019-07-18 15:26:25 +02001163 struct lysp_node_leaf *leaf;
1164
David Sedlák8d552d62019-08-06 15:29:05 +02001165 /* create structure new leaf */
1166 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001167 leaf->nodetype = LYS_LEAF;
1168 leaf->parent = node_meta->parent;
1169
David Sedlák203ca3a2019-07-18 15:26:25 +02001170 /* parser argument */
1171 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1172
1173 /* parse content */
1174 struct yin_subelement subelems[12] = {
1175 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1176 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1177 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1178 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1179 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1180 {YANG_MUST, &leaf->musts, 0},
1181 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1182 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1183 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1184 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1185 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1186 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001187 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001188 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1189}
1190
1191/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001192 * @brief Parse leaf-list element.
1193 *
1194 * @param[in,out] ctx YIN parser context for logging and to store current state.
1195 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1196 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001197 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001198 *
1199 * @return LY_ERR values.
1200 */
1201static LY_ERR
1202yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1203 struct tree_node_meta *node_meta)
1204{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001205 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001206
David Sedlák8d552d62019-08-06 15:29:05 +02001207 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, llist, next);
1208
David Sedlákc3da3ef2019-07-19 12:56:08 +02001209 llist->nodetype = LYS_LEAFLIST;
1210 llist->parent = node_meta->parent;
1211
David Sedlákc3da3ef2019-07-19 12:56:08 +02001212 /* parse argument */
1213 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1214
1215 /* parse content */
1216 struct yin_subelement subelems[14] = {
1217 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1218 {YANG_DEFAULT, &llist->dflts, 0},
1219 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1220 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1221 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1222 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1223 {YANG_MUST, &llist->musts, 0},
1224 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1225 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1226 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1227 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1228 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1229 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1230 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001231 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001232 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1233
1234 /* invalid combination of subelements */
1235 if ((llist->min) && (llist->dflts)) {
David Sedlák1538a842019-08-08 15:38:51 +02001236 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
David Sedlákc3da3ef2019-07-19 12:56:08 +02001237 return LY_EVALID;
1238 }
1239 if (llist->max && llist->min > llist->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001240 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
David Sedlákc3da3ef2019-07-19 12:56:08 +02001241 return LY_EVALID;
1242 }
1243
1244 return LY_SUCCESS;
1245}
1246
1247/**
David Sedlák04e17b22019-07-19 15:29:48 +02001248 * @brief Parse typedef element.
1249 *
1250 * @param[in,out] ctx YIN parser context for logging and to store current state.
1251 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1252 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001253 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001254 *
1255 * @return LY_ERR values.
1256 */
1257static LY_ERR
1258yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001259 struct tree_node_meta *typedef_meta)
David Sedlák04e17b22019-07-19 15:29:48 +02001260{
1261 struct lysp_tpdf *tpdf;
David Sedlák6881b512019-08-13 12:52:00 +02001262 struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->siblings;
1263 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *tpdfs, tpdf, LY_EMEM);
David Sedlák04e17b22019-07-19 15:29:48 +02001264
1265 /* parse argument */
1266 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1267
1268 /* parse content */
1269 struct yin_subelement subelems[7] = {
1270 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1271 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1272 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1273 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1274 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1275 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1276 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001277 };
David Sedlák04e17b22019-07-19 15:29:48 +02001278 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1279
1280 /* store data for collision check */
1281 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1282 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1283 }
1284
1285 return LY_SUCCESS;
1286}
1287
1288/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001289 * @brief Parse refine element.
1290 *
1291 * @param[in,out] ctx YIN parser context for logging and to store current state.
1292 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1293 * @param[in,out] data Data to read from, always moved to currently handled character.
1294 * @param[in,out] refines Refines to add to.
1295 *
1296 * @return LY_ERR values.
1297 */
1298static LY_ERR
1299yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1300 struct lysp_refine **refines)
1301{
1302 struct lysp_refine *rf;
1303
1304 /* allocate new refine */
1305 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1306
1307 /* parse attribute */
1308 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1309 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1310
1311 /* parse content */
1312 struct yin_subelement subelems[11] = {
1313 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1314 {YANG_DEFAULT, &rf->dflts, 0},
1315 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1316 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1317 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1318 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1319 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1320 {YANG_MUST, &rf->musts, 0},
1321 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1322 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1323 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001324 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001325 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1326}
1327
1328/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001329 * @brief Parse uses element.
1330 *
1331 * @param[in,out] ctx YIN parser context for logging and to store current state.
1332 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1333 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001334 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001335 *
1336 * @return LY_ERR values.
1337 */
1338static LY_ERR
1339yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1340 struct tree_node_meta *node_meta)
1341{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001342 struct lysp_node_uses *uses;
1343
David Sedlák8d552d62019-08-06 15:29:05 +02001344 /* create new uses */
1345 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001346 uses->nodetype = LYS_USES;
1347 uses->parent = node_meta->parent;
1348
David Sedlák0d6de5a2019-07-22 13:25:44 +02001349 /* parse argument */
1350 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1351
1352 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02001353 struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
David Sedlák0d6de5a2019-07-22 13:25:44 +02001354 struct yin_subelement subelems[8] = {
1355 {YANG_AUGMENT, &augments, 0},
1356 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1357 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1358 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1359 {YANG_REFINE, &uses->refines, 0},
1360 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1361 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1362 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001363 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001364 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1365 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1366
1367 return LY_SUCCESS;
1368}
1369
1370/**
David Sedlákaa854b02019-07-22 14:17:10 +02001371 * @brief Parse revision element.
1372 *
1373 * @param[in,out] ctx YIN parser context for logging and to store current state.
1374 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1375 * @param[in,out] data Data to read from, always moved to currently handled character.
1376 * @param[in,out] revs Parsed revisions to add to.
1377 *
1378 * @return LY_ERR values.
1379 */
1380static LY_ERR
1381yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1382 struct lysp_revision **revs)
1383{
1384 struct lysp_revision *rev;
1385 const char *temp_date = NULL;
1386
1387 /* allocate new reivison */
1388 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1389
1390 /* parse argument */
1391 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1392 /* check value */
1393 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1394 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1395 return LY_EVALID;
1396 }
1397 strcpy(rev->date, temp_date);
1398 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1399
1400 /* parse content */
1401 struct yin_subelement subelems[3] = {
1402 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1403 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1404 {YANG_CUSTOM, NULL, 0},
1405 };
1406 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1407}
1408
David Sedlák5e13dea2019-07-22 16:06:45 +02001409/**
1410 * @brief Parse include element.
1411 *
1412 * @param[in,out] ctx YIN parser context for logging and to store current state.
1413 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1414 * @param[in,out] data Data to read from, always moved to currently handled character.
1415 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1416 *
1417 * @return LY_ERR values.
1418 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001419static LY_ERR
1420yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1421 struct include_meta *inc_meta)
1422{
1423 struct lysp_include *inc;
1424
1425 /* allocate new include */
1426 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1427
1428 /* parse argument */
1429 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1430
1431 /* submodules share the namespace with the module names, so there must not be
1432 * a module of the same name in the context, no need for revision matching */
1433 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
David Sedlák1538a842019-08-08 15:38:51 +02001434 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_NAME_COL, inc->name);
David Sedlák0c2bab92019-07-22 15:33:19 +02001435 return LY_EVALID;
1436 }
1437
1438 /* parse content */
1439 struct yin_subelement subelems[4] = {
1440 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1441 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1442 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1443 {YANG_CUSTOM, NULL, 0},
1444 };
1445 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1446}
1447
David Sedlákaa854b02019-07-22 14:17:10 +02001448/**
David Sedlákdfbbb442019-08-06 16:33:21 +02001449 * @brief Parse revision date element.
1450 *
1451 * @param[in,out] ctx Yin parser context for logging and to store current state.
1452 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1453 * @param[in,out] data Data to read from, always moved to currently handled character.
1454 * @param[in,out] rev Array to store the parsed value in.
1455 * @param[in,out] exts Extension instances to add to.
1456 *
1457 * @return LY_ERR values.
1458 */
1459static LY_ERR
1460yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1461 struct lysp_ext_instance **exts)
1462{
1463 const char *temp_rev;
1464 struct yin_subelement subelems[1] = {
1465 {YANG_CUSTOM, NULL, 0}
1466 };
1467
1468 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1469 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1470 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1471
1472 strcpy(rev, temp_rev);
1473 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1474
1475 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1476}
1477
1478/**
1479 * @brief Parse config element.
1480 *
1481 * @param[in] ctx Yin parser context for logging and to store current state.
1482 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1483 * @param[in,out] data Data to read from, always moved to currently handled character.
1484 * @param[in,out] flags Flags to add to.
1485 * @param[in,out] exts Extension instances to add to.
1486 *
1487 * @return LY_ERR values.
1488 */
1489static LY_ERR
1490yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1491 struct lysp_ext_instance **exts)
1492{
1493 const char *temp_val = NULL;
1494 struct yin_subelement subelems[1] = {
1495 {YANG_CUSTOM, NULL, 0}
1496 };
1497
1498 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1499 if (strcmp(temp_val, "true") == 0) {
1500 *flags |= LYS_CONFIG_W;
1501 } else if (strcmp(temp_val, "false") == 0) {
1502 *flags |= LYS_CONFIG_R;
1503 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001504 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "config");
David Sedlákdfbbb442019-08-06 16:33:21 +02001505 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1506 return LY_EVALID;
1507 }
1508 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1509
1510 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1511}
1512
1513/**
1514 * @brief Parse yang-version element.
1515 *
1516 * @param[in,out] ctx Yin parser context for logging and to store current state.
1517 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1518 * @param[in] data Data to read from, always moved to currently handled character.
1519 * @param[out] version Storage for the parsed information.
1520 * @param[in,out] exts Extension instance to add to.
1521 *
1522 * @return LY_ERR values.
1523 */
1524static LY_ERR
1525yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1526 struct lysp_ext_instance **exts)
1527{
1528 const char *temp_version = NULL;
1529 struct yin_subelement subelems[1] = {
1530 {YANG_CUSTOM, NULL, 0}
1531 };
1532
1533 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1534 if (strcmp(temp_version, "1.0") == 0) {
1535 *version = LYS_VERSION_1_0;
1536 } else if (strcmp(temp_version, "1.1") == 0) {
1537 *version = LYS_VERSION_1_1;
1538 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001539 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "value", "yang-version");
David Sedlákdfbbb442019-08-06 16:33:21 +02001540 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1541 return LY_EVALID;
1542 }
1543 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1544 ctx->mod_version = *version;
1545
1546 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1547}
1548
1549/**
1550 * @brief Parse import element.
1551 *
1552 * @param[in,out] ctx Yin parser context for logging and to store current state.
1553 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1554 * @param[in,out] data Data to read from, always moved to currently handled character.
1555 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1556 *
1557 * @return LY_ERR values.
1558 */
1559static LY_ERR
1560yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1561{
1562 struct lysp_import *imp;
1563 /* allocate new element in sized array for import */
1564 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1565
1566 struct yin_subelement subelems[5] = {
1567 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1568 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1569 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1570 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1571 {YANG_CUSTOM, NULL, 0}
1572 };
1573
1574 /* parse import attributes */
1575 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1576 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1577 /* check prefix validity */
1578 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1579
1580 return LY_SUCCESS;
1581}
1582
1583/**
1584 * @brief Parse mandatory element.
1585 *
1586 * @param[in,out] ctx Yin parser context for logging and to store current state.
1587 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1588 * @param[in,out] data Data to read from, always moved to currently handled character.
1589 * @param[in,out] flags Flags to add to.
1590 * @param[in,out] exts Extension instances to add to.
1591 *
1592 * @return LY_ERR values.
1593 */
1594static LY_ERR
1595yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1596 struct lysp_ext_instance **exts)
1597{
1598 const char *temp_val = NULL;
1599 struct yin_subelement subelems[1] = {
1600 {YANG_CUSTOM, NULL, 0}
1601 };
1602
1603 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1604 if (strcmp(temp_val, "true") == 0) {
1605 *flags |= LYS_MAND_TRUE;
1606 } else if (strcmp(temp_val, "false") == 0) {
1607 *flags |= LYS_MAND_FALSE;
1608 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001609 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "mandatory");
David Sedlákdfbbb442019-08-06 16:33:21 +02001610 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1611 return LY_EVALID;
1612 }
1613 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1614
1615 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1616}
1617
1618/**
1619 * @brief Parse status element.
1620 *
1621 * @param[in,out] ctx Yin parser context for logging and to store current state.
1622 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1623 * @param[in,out] data Data to read from, always moved to currently handled character.
1624 * @param[in,out] flags Flags to add to.
1625 * @param[in,out] exts Extension instances to add to.
1626 *
1627 * @return LY_ERR values.
1628 */
1629static LY_ERR
1630yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1631 struct lysp_ext_instance **exts)
1632{
1633 const char *value = NULL;
1634 struct yin_subelement subelems[1] = {
1635 {YANG_CUSTOM, NULL, 0}
1636 };
1637
1638 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1639 if (strcmp(value, "current") == 0) {
1640 *flags |= LYS_STATUS_CURR;
1641 } else if (strcmp(value, "deprecated") == 0) {
1642 *flags |= LYS_STATUS_DEPRC;
1643 } else if (strcmp(value, "obsolete") == 0) {
1644 *flags |= LYS_STATUS_OBSLT;
1645 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001646 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "value", "status");
David Sedlákdfbbb442019-08-06 16:33:21 +02001647 FREE_STRING(ctx->xml_ctx.ctx, value);
1648 return LY_EVALID;
1649 }
1650 FREE_STRING(ctx->xml_ctx.ctx, value);
1651
1652 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1653}
1654
1655/**
1656 * @brief Parse when element.
1657 *
1658 * @param[in,out] ctx Yin parser context for logging and to store current state.
1659 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1660 * @param[in,out] data Data to read from, always moved to currently handled character.
1661 * @param[out] when_p When pointer to parse to.
1662 */
1663static LY_ERR
1664yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1665{
1666 struct lysp_when *when;
1667 when = calloc(1, sizeof *when);
1668 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1669 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1670 *when_p = when;
1671 struct yin_subelement subelems[3] = {
1672 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1673 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1674 {YANG_CUSTOM, NULL, 0}
1675 };
1676
1677 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1678}
1679
1680/**
1681 * @brief Parse yin-elemenet element.
1682 *
1683 * @param[in,out] ctx Yin parser context for logging and to store current state.
1684 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1685 * @param[in,out] data Data to read from, always moved to currently handled position.
1686 * @param[in,out] flags Flags to add to.
1687 * @prama[in,out] exts Extension instance to add to.
1688 *
1689 * @return LY_ERR values.
1690 */
1691static LY_ERR
1692yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1693 uint16_t *flags, struct lysp_ext_instance **exts)
1694{
1695 const char *temp_val = NULL;
1696 struct yin_subelement subelems[1] = {
1697 {YANG_CUSTOM, NULL, 0}
1698 };
1699
1700 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1701 if (strcmp(temp_val, "true") == 0) {
1702 *flags |= LYS_YINELEM_TRUE;
1703 } else if (strcmp(temp_val, "false") == 0) {
1704 *flags |= LYS_YINELEM_FALSE;
1705 } else {
David Sedlák1538a842019-08-08 15:38:51 +02001706 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "yin-element");
David Sedlákdfbbb442019-08-06 16:33:21 +02001707 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1708 return LY_EVALID;
1709 }
1710 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1711
1712 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1713}
1714
1715/**
1716 * @brief Parse argument element.
1717 *
1718 * @param[in,out] xml_ctx Xml context.
1719 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1720 * @param[in,out] data Data to read from, always moved to currently handled character.
1721 * @param[in,out] arg_meta Meta information about destionation af prased data.
1722 * @param[in,out] exts Extension instance to add to.
1723 *
1724 * @return LY_ERR values.
1725 */
1726static LY_ERR
1727yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1728 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1729{
1730 struct yin_subelement subelems[2] = {
1731 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1732 {YANG_CUSTOM, NULL, 0}
1733 };
1734
1735 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1736
1737 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1738}
1739
1740/**
1741 * @brief Parse the extension statement.
1742 *
1743 * @param[in,out] ctx Yin parser context for logging and to store current state.
1744 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1745 * @param[in,out] data Data to read from.
1746 * @param[in,out] extensions Extensions to add to.
1747 *
1748 * @return LY_ERR values.
1749 */
1750static LY_ERR
1751yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1752{
1753 struct lysp_ext *ex;
1754 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
1755 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
1756
1757 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1758 struct yin_subelement subelems[5] = {
1759 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1760 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1761 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1762 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1763 {YANG_CUSTOM, NULL, 0}
1764 };
1765
1766 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
1767}
1768
1769/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001770 * @brief Parse feature element.
1771 *
1772 * @param[in,out] ctx YIN parser context for logging and to store current state.
1773 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1774 * @param[in,out] data Data to read from, always moved to currently handled character.
1775 * @param[in,out] features Features to add to.
1776 *
1777 * @return LY_ERR values.
1778 */
1779static LY_ERR
1780yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1781 struct lysp_feature **features)
1782{
1783 struct lysp_feature *feat;
1784
1785 /* allocate new feature */
1786 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1787
1788 /* parse argument */
1789 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1790
1791 /* parse content */
1792 struct yin_subelement subelems[5] = {
1793 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1794 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1795 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1796 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1797 {YANG_CUSTOM, NULL, 0},
1798 };
1799 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1800}
1801
1802/**
David Sedlák28794f22019-07-22 16:45:00 +02001803 * @brief Parse identity element.
1804 *
1805 * @param[in,out] ctx YIN parser context for logging and to store current state.
1806 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1807 * @param[in,out] data Data to read from, always moved to currently handled character.
1808 * @param[in,out] identities Identities to add to.
1809 *
1810 * @return LY_ERR values.
1811 */
1812static LY_ERR
1813yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1814 struct lysp_ident **identities)
1815{
1816 struct lysp_ident *ident;
1817
1818 /* allocate new identity */
1819 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1820
1821 /* parse argument */
1822 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1823
1824 /* parse content */
1825 struct yin_subelement subelems[6] = {
1826 {YANG_BASE, &ident->bases, 0},
1827 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1828 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1829 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1830 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1831 {YANG_CUSTOM, NULL, 0},
1832 };
1833 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1834}
1835
1836/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001837 * @brief Parse list element.
1838 *
1839 * @param[in,out] ctx YIN parser context for logging and to store current state.
1840 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1841 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02001842 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákaf536aa2019-07-23 13:42:23 +02001843 *
1844 * @return LY_ERR values.
1845 */
1846static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001847yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1848 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001849{
David Sedlákaf536aa2019-07-23 13:42:23 +02001850 struct lysp_node_list *list;
1851
David Sedlák8d552d62019-08-06 15:29:05 +02001852 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02001853 list->nodetype = LYS_LIST;
1854 list->parent = node_meta->parent;
1855
David Sedlákaf536aa2019-07-23 13:42:23 +02001856 /* parse argument */
1857 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1858
1859 /* parse list content */
David Sedlák6881b512019-08-13 12:52:00 +02001860 struct tree_node_meta act_meta = {(struct lysp_node *)list, (struct lysp_node **)&list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001861 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
David Sedlák6881b512019-08-13 12:52:00 +02001862 struct tree_node_meta typedef_meta = {(struct lysp_node *)list, (struct lysp_node **)&list->typedefs};
1863 struct tree_node_meta notif_meta = {(struct lysp_node *)list, (struct lysp_node **)&list->notifs};
1864 struct tree_node_meta gr_meta = {(struct lysp_node *)list, (struct lysp_node **)&list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001865 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001866 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001867 {YANG_ANYDATA, &new_node_meta, 0},
1868 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001869 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001870 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001871 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001872 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001873 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001874 {YANG_IF_FEATURE, &list->iffeatures, 0},
1875 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1876 {YANG_LEAF, &new_node_meta, 0},
1877 {YANG_LEAF_LIST, &new_node_meta, 0},
1878 {YANG_LIST, &new_node_meta, 0},
1879 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1880 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1881 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001882 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001883 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1884 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1885 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1886 {YANG_TYPEDEF, &typedef_meta, 0},
1887 {YANG_UNIQUE, &list->uniques, 0},
1888 {YANG_USES, &new_node_meta, 0},
1889 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1890 {YANG_CUSTOM, NULL, 0},
1891 };
1892 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1893
1894 /* finalize parent pointers to the reallocated items */
1895 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1896
1897 if (list->max && list->min > list->max) {
David Sedlák1538a842019-08-08 15:38:51 +02001898 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
David Sedlákaf536aa2019-07-23 13:42:23 +02001899 return LY_EVALID;
1900 }
1901
1902 return LY_SUCCESS;
1903}
1904
1905/**
David Sedlák031b9e72019-07-23 15:19:37 +02001906 * @brief Parse notification element.
1907 *
1908 * @param[in,out] ctx YIN parser context for logging and to store current state.
1909 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1910 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001911 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001912 *
1913 * @return LY_ERR values.
1914 */
1915static LY_ERR
1916yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001917 struct tree_node_meta *notif_meta)
David Sedlák031b9e72019-07-23 15:19:37 +02001918{
1919 struct lysp_notif *notif;
David Sedlák6881b512019-08-13 12:52:00 +02001920 struct lysp_notif **notifs = (struct lysp_notif **)notif_meta->siblings;
David Sedlák031b9e72019-07-23 15:19:37 +02001921
1922 /* allocate new notification */
David Sedlák6881b512019-08-13 12:52:00 +02001923 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notifs, notif, LY_EMEM);
David Sedlák031b9e72019-07-23 15:19:37 +02001924 notif->nodetype = LYS_NOTIF;
1925 notif->parent = notif_meta->parent;
1926
1927 /* parse argument */
1928 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1929
1930 /* parse notification content */
1931 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
David Sedlák6881b512019-08-13 12:52:00 +02001932 struct tree_node_meta typedef_meta = {(struct lysp_node *)notif, (struct lysp_node **)&notif->typedefs};
1933 struct tree_node_meta gr_meta = {(struct lysp_node *)notif, (struct lysp_node **)&notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001934 struct yin_subelement subelems[16] = {
1935 {YANG_ANYDATA, &node_meta, 0},
1936 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001937 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001938 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001939 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001940 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001941 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1942 {YANG_LEAF, &node_meta, 0},
1943 {YANG_LEAF_LIST, &node_meta, 0},
1944 {YANG_LIST, &node_meta, 0},
1945 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1946 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1947 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1948 {YANG_TYPEDEF, &typedef_meta, 0},
1949 {YANG_USES, &node_meta, 0},
1950 {YANG_CUSTOM, NULL, 0},
1951 };
1952 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1953
1954 /* finalize parent pointers to the reallocated items */
1955 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1956
1957 return LY_SUCCESS;
1958}
1959
1960/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001961 * @brief Parse notification element.
1962 *
1963 * @param[in,out] ctx YIN parser context for logging and to store current state.
1964 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1965 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001966 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001967 *
1968 * @return LY_ERR values.
1969 */
1970static LY_ERR
1971yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02001972 struct tree_node_meta *gr_meta)
David Sedláke3ce9ef2019-07-23 16:34:30 +02001973{
1974 struct lysp_grp *grp;
David Sedlák6881b512019-08-13 12:52:00 +02001975 struct lysp_grp **grps = (struct lysp_grp **)gr_meta->siblings;
David Sedláke3ce9ef2019-07-23 16:34:30 +02001976
1977 /* create new grouping */
David Sedlák6881b512019-08-13 12:52:00 +02001978 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *grps, grp, LY_EMEM);
David Sedláke3ce9ef2019-07-23 16:34:30 +02001979 grp->nodetype = LYS_GROUPING;
1980 grp->parent = gr_meta->parent;
1981
1982 /* parse argument */
1983 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1984
1985 /* parse grouping content */
David Sedlák6881b512019-08-13 12:52:00 +02001986 struct tree_node_meta act_meta = {(struct lysp_node *)grp, (struct lysp_node **)&grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001987 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
David Sedlák6881b512019-08-13 12:52:00 +02001988 struct tree_node_meta typedef_meta = {(struct lysp_node *)grp, (struct lysp_node **)&grp->typedefs};
1989 struct tree_node_meta sub_grouping = {(struct lysp_node *)grp, (struct lysp_node **)&grp->groupings};
1990 struct tree_node_meta notif_meta = {(struct lysp_node *)grp, (struct lysp_node **)&grp->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001991 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001992 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001993 {YANG_ANYDATA, &node_meta, 0},
1994 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001995 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001996 {YANG_CONTAINER, &node_meta, 0},
1997 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1998 {YANG_GROUPING, &sub_grouping, 0},
1999 {YANG_LEAF, &node_meta, 0},
2000 {YANG_LEAF_LIST, &node_meta, 0},
2001 {YANG_LIST, &node_meta, 0},
2002 {YANG_NOTIFICATION, &notif_meta, 0},
2003 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
2004 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
2005 {YANG_TYPEDEF, &typedef_meta, 0},
2006 {YANG_USES, &node_meta, 0},
2007 {YANG_CUSTOM, NULL, 0},
2008 };
2009 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
2010 /* finalize parent pointers to the reallocated items */
2011 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2012
2013 return LY_SUCCESS;
2014}
2015
2016/**
David Sedlákf111bcb2019-07-23 17:15:51 +02002017 * @brief Parse list element.
2018 *
2019 * @param[in,out] ctx YIN parser context for logging and to store current state.
2020 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2021 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002022 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákf111bcb2019-07-23 17:15:51 +02002023 *
2024 * @return LY_ERR values.
2025 */
2026static LY_ERR
2027yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2028 struct tree_node_meta *node_meta)
2029{
David Sedlákf111bcb2019-07-23 17:15:51 +02002030 struct lysp_node_container *cont;
2031
2032 /* create new container */
David Sedlák8d552d62019-08-06 15:29:05 +02002033 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002034 cont->nodetype = LYS_CONTAINER;
2035 cont->parent = node_meta->parent;
2036
David Sedlákf111bcb2019-07-23 17:15:51 +02002037 /* parse aegument */
2038 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2039
2040 /* parse container content */
David Sedlák6881b512019-08-13 12:52:00 +02002041 struct tree_node_meta act_meta = {(struct lysp_node *)cont, (struct lysp_node **)&cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02002042 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
David Sedlák6881b512019-08-13 12:52:00 +02002043 struct tree_node_meta grp_meta = {(struct lysp_node *)cont, (struct lysp_node **)&cont->groupings};
2044 struct tree_node_meta typedef_meta = {(struct lysp_node *)cont, (struct lysp_node **)&cont->typedefs};
2045 struct tree_node_meta notif_meta = {(struct lysp_node *)cont, (struct lysp_node **)&cont->notifs};
David Sedlákf111bcb2019-07-23 17:15:51 +02002046 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02002047 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02002048 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2049 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02002050 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02002051 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
2052 {YANG_CONTAINER, &new_node_meta, 0},
2053 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
2054 {YANG_GROUPING, &grp_meta, 0},
2055 {YANG_IF_FEATURE, &cont->iffeatures, 0},
2056 {YANG_LEAF, &new_node_meta, 0},
2057 {YANG_LEAF_LIST, &new_node_meta, 0},
2058 {YANG_LIST, &new_node_meta, 0},
2059 {YANG_MUST, &cont->musts, 0},
2060 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2061 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
2062 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
2063 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
2064 {YANG_TYPEDEF, &typedef_meta, 0},
2065 {YANG_USES, &new_node_meta, 0},
2066 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
2067 {YANG_CUSTOM, NULL, 0},
2068 };
2069 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
2070 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2071
2072 return LY_SUCCESS;
2073}
2074
2075/**
David Sedlák5379d392019-07-24 10:42:03 +02002076 * @brief Parse case element.
2077 *
2078 * @param[in,out] ctx YIN parser context for logging and to store current state.
2079 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2080 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002081 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlák5379d392019-07-24 10:42:03 +02002082 *
2083 * @return LY_ERR values.
2084 */
2085static LY_ERR
2086yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2087 struct tree_node_meta *node_meta)
2088{
David Sedlák5379d392019-07-24 10:42:03 +02002089 struct lysp_node_case *cas;
2090
2091 /* create new case */
David Sedlák8d552d62019-08-06 15:29:05 +02002092 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002093 cas->nodetype = LYS_CASE;
2094 cas->parent = node_meta->parent;
2095
David Sedlák5379d392019-07-24 10:42:03 +02002096 /* parse argument */
2097 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2098
2099 /* parse case content */
2100 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
2101 struct yin_subelement subelems[14] = {
2102 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2103 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02002104 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02002105 {YANG_CONTAINER, &new_node_meta, 0},
2106 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
2107 {YANG_IF_FEATURE, &cas->iffeatures, 0},
2108 {YANG_LEAF, &new_node_meta, 0},
2109 {YANG_LEAF_LIST, &new_node_meta, 0},
2110 {YANG_LIST, &new_node_meta, 0},
2111 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
2112 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
2113 {YANG_USES, &new_node_meta, 0},
2114 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
2115 {YANG_CUSTOM, NULL, 0},
2116 };
2117 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2118}
2119
2120/**
David Sedlák05404f62019-07-24 14:11:53 +02002121 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002122 *
2123 * @param[in,out] ctx YIN parser context for logging and to store current state.
2124 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2125 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákad83cf92019-08-13 12:53:53 +02002126 * @param[in] node_meta Meta information about parent node and siblings to add to.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002127 *
2128 * @return LY_ERR values.
2129 */
2130LY_ERR
2131yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2132 struct tree_node_meta *node_meta)
2133{
David Sedlákb7abcfa2019-07-24 12:33:35 +02002134 struct lysp_node_choice *choice;
2135
2136 /* create new choice */
David Sedlák8d552d62019-08-06 15:29:05 +02002137 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, choice, next);
2138
David Sedlákb7abcfa2019-07-24 12:33:35 +02002139 choice->nodetype = LYS_CHOICE;
2140 choice->parent = node_meta->parent;
2141
David Sedlákb7abcfa2019-07-24 12:33:35 +02002142 /* parse argument */
2143 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2144
2145 /* parse choice content */
2146 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
2147 struct yin_subelement subelems[17] = {
2148 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2149 {YANG_ANYXML, &new_node_meta, 0},
2150 {YANG_CASE, &new_node_meta, 0},
2151 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
2152 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
2153 {YANG_CONTAINER, &new_node_meta, 0},
2154 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
2155 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
2156 {YANG_IF_FEATURE, &choice->iffeatures, 0},
2157 {YANG_LEAF, &new_node_meta, 0},
2158 {YANG_LEAF_LIST, &new_node_meta, 0},
2159 {YANG_LIST, &new_node_meta, 0},
2160 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
2161 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
2162 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
2163 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
2164 {YANG_CUSTOM, NULL, 0},
2165 };
2166 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2167}
2168
2169/**
David Sedlák05404f62019-07-24 14:11:53 +02002170 * @brief Parse input or output element.
2171 *
2172 * @param[in,out] ctx YIN parser context for logging and to store current state.
2173 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2174 * @param[in,out] data Data to read from, always moved to currently handled character.
2175 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2176 *
2177 * @return LY_ERR values.
2178 */
2179static LY_ERR
2180yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2181 struct inout_meta *inout_meta)
2182{
2183 /* initiate structure */
2184 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2185 inout_meta->inout_p->parent = inout_meta->parent;
2186
2187 /* check attributes */
2188 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2189
2190 /* parser input/output content */
2191 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
David Sedlák6881b512019-08-13 12:52:00 +02002192 struct tree_node_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, (struct lysp_node **)&inout_meta->inout_p->groupings};
2193 struct tree_node_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, (struct lysp_node **)&inout_meta->inout_p->typedefs};
David Sedlák05404f62019-07-24 14:11:53 +02002194 struct yin_subelement subelems[12] = {
2195 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2196 {YANG_ANYXML, &node_meta, 0},
2197 {YANG_CHOICE, &node_meta, 0},
2198 {YANG_CONTAINER, &node_meta, 0},
2199 {YANG_GROUPING, &grp_meta, 0},
2200 {YANG_LEAF, &node_meta, 0},
2201 {YANG_LEAF_LIST, &node_meta, 0},
2202 {YANG_LIST, &node_meta, 0},
2203 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
2204 {YANG_TYPEDEF, &typedef_meta, 0},
2205 {YANG_USES, &node_meta, 0},
2206 {YANG_CUSTOM, NULL, 0},
2207 };
2208 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
2209
2210 /* finalize parent pointers to the reallocated items */
2211 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
2212 NULL, NULL, NULL));
2213
2214 return LY_SUCCESS;
2215}
2216
David Sedlák992fb7c2019-07-24 16:51:01 +02002217/**
2218 * @brief Parse action element.
2219 *
2220 * @param[in,out] ctx YIN parser context for logging and to store current state.
2221 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2222 * @param[in,out] data Data to read from, always moved to currently handled character.
2223 * @param[in] act_meta Meta information about parent node and actions to add to.
2224 *
2225 * @return LY_ERR values.
2226 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002227static LY_ERR
2228yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002229 struct tree_node_meta *act_meta)
David Sedlák85d0eca2019-07-24 15:15:21 +02002230{
2231 struct lysp_action *act;
David Sedlák6881b512019-08-13 12:52:00 +02002232 struct lysp_action **acts = (struct lysp_action **)act_meta->siblings;
David Sedlák85d0eca2019-07-24 15:15:21 +02002233
2234 /* create new action */
David Sedlák6881b512019-08-13 12:52:00 +02002235 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *acts, act, LY_EMEM);
David Sedlák85d0eca2019-07-24 15:15:21 +02002236 act->nodetype = LYS_ACTION;
2237 act->parent = act_meta->parent;
2238
2239 /* parse argument */
2240 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2241
2242 /* parse content */
David Sedlák6881b512019-08-13 12:52:00 +02002243 struct tree_node_meta grp_meta = {(struct lysp_node *)act, (struct lysp_node **)&act->groupings};
2244 struct tree_node_meta typedef_meta = {(struct lysp_node *)act, (struct lysp_node **)&act->typedefs};
David Sedlák85d0eca2019-07-24 15:15:21 +02002245 struct inout_meta input = {(struct lysp_node *)act, &act->input};
2246 struct inout_meta output = {(struct lysp_node *)act, &act->output};
2247 struct yin_subelement subelems[9] = {
2248 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
2249 {YANG_GROUPING, &grp_meta, 0},
2250 {YANG_IF_FEATURE, &act->iffeatures, 0},
2251 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
2252 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
2253 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
2254 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
2255 {YANG_TYPEDEF, &typedef_meta, 0},
2256 {YANG_CUSTOM, NULL, 0},
2257 };
2258 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2259 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2260
2261 return LY_SUCCESS;
2262}
2263
David Sedlák05404f62019-07-24 14:11:53 +02002264/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002265 * @brief Parse augment element.
2266 *
2267 * @param[in,out] ctx YIN parser context for logging and to store current state.
2268 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2269 * @param[in,out] data Data to read from, always moved to currently handled character.
2270 * @param[in] aug_meta Meta information about parent node and augments to add to.
2271 *
2272 * @return LY_ERR values.
2273 */
2274static LY_ERR
2275yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
David Sedlák6881b512019-08-13 12:52:00 +02002276 struct tree_node_meta *aug_meta)
David Sedlák992fb7c2019-07-24 16:51:01 +02002277{
2278 struct lysp_augment *aug;
David Sedlák6881b512019-08-13 12:52:00 +02002279 struct lysp_augment **augs = (struct lysp_augment **)aug_meta->siblings;
David Sedlák992fb7c2019-07-24 16:51:01 +02002280
2281 /* create new augment */
David Sedlák6881b512019-08-13 12:52:00 +02002282 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *augs, aug, LY_EMEM);
David Sedlák992fb7c2019-07-24 16:51:01 +02002283 aug->nodetype = LYS_AUGMENT;
2284 aug->parent = aug_meta->parent;
2285
2286 /* parse argument */
2287 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2288 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2289
2290 /* parser augment content */
David Sedlák6881b512019-08-13 12:52:00 +02002291 struct tree_node_meta act_meta = {(struct lysp_node *)aug, (struct lysp_node **)&aug->actions};
David Sedlák992fb7c2019-07-24 16:51:01 +02002292 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
David Sedlák6881b512019-08-13 12:52:00 +02002293 struct tree_node_meta notif_meta = {(struct lysp_node *)aug, (struct lysp_node **)&aug->notifs};
David Sedlák992fb7c2019-07-24 16:51:01 +02002294 struct yin_subelement subelems[17] = {
2295 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
2296 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2297 {YANG_ANYXML, &node_meta, 0},
2298 {YANG_CASE, &node_meta, 0},
2299 {YANG_CHOICE, &node_meta, 0},
2300 {YANG_CONTAINER, &node_meta, 0},
2301 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
2302 {YANG_IF_FEATURE, &aug->iffeatures, 0},
2303 {YANG_LEAF, &node_meta, 0},
2304 {YANG_LEAF_LIST, &node_meta, 0},
2305 {YANG_LIST, &node_meta, 0},
2306 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2307 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
2308 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
2309 {YANG_USES, &node_meta, 0},
2310 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
2311 {YANG_CUSTOM, NULL, 0},
2312 };
2313 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
2314
2315 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2316
2317 return LY_SUCCESS;
2318}
2319
David Sedlák8b754462019-07-25 16:22:13 +02002320/**
2321 * @brief Parse deviate element.
2322 *
2323 * @param[in,out] ctx YIN parser context for logging and to store current state.
2324 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2325 * @param[in,out] data Data to read from, always moved to currently handled character.
2326 * @param[in] deviates Deviates to add to.
2327 *
2328 * @return LY_ERR values.
2329 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002330static LY_ERR
2331yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2332 struct lysp_deviate **deviates)
2333{
2334 LY_ERR ret = LY_SUCCESS;
2335 uint8_t dev_mod;
2336 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002337 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002338 struct lysp_deviate_add *d_add = NULL;
2339 struct lysp_deviate_rpl *d_rpl = NULL;
2340 struct lysp_deviate_del *d_del = NULL;
2341
2342 /* parse argument */
2343 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2344
2345 if (strcmp(temp_val, "not-supported") == 0) {
2346 dev_mod = LYS_DEV_NOT_SUPPORTED;
2347 } else if (strcmp(temp_val, "add") == 0) {
2348 dev_mod = LYS_DEV_ADD;
2349 } else if (strcmp(temp_val, "replace") == 0) {
2350 dev_mod = LYS_DEV_REPLACE;
2351 } else if (strcmp(temp_val, "delete") == 0) {
2352 dev_mod = LYS_DEV_DELETE;
2353 } else {
David Sedlák1538a842019-08-08 15:38:51 +02002354 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "deviate");
David Sedlák4ffcec82019-07-25 15:10:21 +02002355 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2356 return LY_EVALID;
2357 }
2358 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2359
2360 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2361 d = calloc(1, sizeof *d);
2362 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2363 struct yin_subelement subelems[1] = {
2364 {YANG_CUSTOM, NULL, 0}
2365 };
2366 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2367
2368 } else if (dev_mod == LYS_DEV_ADD) {
2369 d_add = calloc(1, sizeof *d_add);
2370 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2371 d = (struct lysp_deviate *)d_add;
2372 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2373 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2374 struct yin_subelement subelems[9] = {
2375 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2376 {YANG_DEFAULT, &d_add->dflts, 0},
2377 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2378 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2379 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2380 {YANG_MUST, &d_add->musts, 0},
2381 {YANG_UNIQUE, &d_add->uniques, 0},
2382 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2383 {YANG_CUSTOM, NULL, 0},
2384 };
2385 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2386
2387 } else if (dev_mod == LYS_DEV_REPLACE) {
2388 d_rpl = calloc(1, sizeof *d_rpl);
2389 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2390 d = (struct lysp_deviate *)d_rpl;
2391 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2392 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2393 struct yin_subelement subelems[8] = {
2394 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2395 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2396 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2397 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2398 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2399 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2400 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2401 {YANG_CUSTOM, NULL, 0},
2402 };
2403 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2404
2405 } else {
2406 d_del = calloc(1, sizeof *d_del);
2407 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2408 d = (struct lysp_deviate *)d_del;
2409 struct yin_subelement subelems[5] = {
2410 {YANG_DEFAULT, &d_del->dflts, 0},
2411 {YANG_MUST, &d_del->musts, 0},
2412 {YANG_UNIQUE, &d_del->uniques, 0},
2413 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2414 {YANG_CUSTOM, NULL, 0},
2415 };
2416 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2417 }
2418 LY_CHECK_GOTO(ret, cleanup);
2419
2420 d->mod = dev_mod;
2421 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002422 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002423
2424 return ret;
2425
2426cleanup:
2427 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002428 return ret;
2429}
2430
David Sedlák992fb7c2019-07-24 16:51:01 +02002431/**
David Sedlák8b754462019-07-25 16:22:13 +02002432 * @brief Parse deviation element.
2433 *
2434 * @param[in,out] ctx YIN parser context for logging and to store current state.
2435 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2436 * @param[in,out] data Data to read from, always moved to currently handled character.
2437 * @param[in] deviations Deviations to add to.
2438 *
2439 * @return LY_ERR values.
2440 */
2441static LY_ERR
2442yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2443 struct lysp_deviation **deviations)
2444{
2445 struct lysp_deviation *dev;
2446
2447 /* create new deviation */
2448 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2449
2450 /* parse argument */
David Sedlák1538a842019-08-08 15:38:51 +02002451 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATION));
David Sedlák8b754462019-07-25 16:22:13 +02002452 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2453 struct yin_subelement subelems[4] = {
2454 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2455 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2456 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2457 {YANG_CUSTOM, NULL, 0},
2458 };
David Sedlák1538a842019-08-08 15:38:51 +02002459 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATION, NULL, &dev->exts);
David Sedlák8b754462019-07-25 16:22:13 +02002460}
2461
2462/**
David Sedlákb4e44562019-07-04 15:42:12 +02002463 * @brief Map keyword type to substatement info.
2464 *
2465 * @param[in] kw Keyword type.
2466 *
2467 * @return correct LYEXT_SUBSTMT information.
2468 */
2469static LYEXT_SUBSTMT
2470kw2lyext_substmt(enum yang_keyword kw)
2471{
2472 switch (kw) {
2473 case YANG_ARGUMENT:
2474 return LYEXT_SUBSTMT_ARGUMENT;
2475 case YANG_BASE:
2476 return LYEXT_SUBSTMT_BASE;
2477 case YANG_BELONGS_TO:
2478 return LYEXT_SUBSTMT_BELONGSTO;
2479 case YANG_CONTACT:
2480 return LYEXT_SUBSTMT_CONTACT;
2481 case YANG_DEFAULT:
2482 return LYEXT_SUBSTMT_DEFAULT;
2483 case YANG_DESCRIPTION:
2484 return LYEXT_SUBSTMT_DESCRIPTION;
2485 case YANG_ERROR_APP_TAG:
2486 return LYEXT_SUBSTMT_ERRTAG;
2487 case YANG_ERROR_MESSAGE:
2488 return LYEXT_SUBSTMT_ERRMSG;
2489 case YANG_KEY:
2490 return LYEXT_SUBSTMT_KEY;
2491 case YANG_NAMESPACE:
2492 return LYEXT_SUBSTMT_NAMESPACE;
2493 case YANG_ORGANIZATION:
2494 return LYEXT_SUBSTMT_ORGANIZATION;
2495 case YANG_PATH:
2496 return LYEXT_SUBSTMT_PATH;
2497 case YANG_PREFIX:
2498 return LYEXT_SUBSTMT_PREFIX;
2499 case YANG_PRESENCE:
2500 return LYEXT_SUBSTMT_PRESENCE;
2501 case YANG_REFERENCE:
2502 return LYEXT_SUBSTMT_REFERENCE;
2503 case YANG_REVISION_DATE:
2504 return LYEXT_SUBSTMT_REVISIONDATE;
2505 case YANG_UNITS:
2506 return LYEXT_SUBSTMT_UNITS;
2507 case YANG_VALUE:
2508 return LYEXT_SUBSTMT_VALUE;
2509 case YANG_YANG_VERSION:
2510 return LYEXT_SUBSTMT_VERSION;
2511 case YANG_MODIFIER:
2512 return LYEXT_SUBSTMT_MODIFIER;
2513 case YANG_REQUIRE_INSTANCE:
2514 return LYEXT_SUBSTMT_REQINSTANCE;
2515 case YANG_YIN_ELEMENT:
2516 return LYEXT_SUBSTMT_YINELEM;
2517 case YANG_CONFIG:
2518 return LYEXT_SUBSTMT_CONFIG;
2519 case YANG_MANDATORY:
2520 return LYEXT_SUBSTMT_MANDATORY;
2521 case YANG_ORDERED_BY:
2522 return LYEXT_SUBSTMT_ORDEREDBY;
2523 case YANG_STATUS:
2524 return LYEXT_SUBSTMT_STATUS;
2525 case YANG_FRACTION_DIGITS:
2526 return LYEXT_SUBSTMT_FRACDIGITS;
2527 case YANG_MAX_ELEMENTS:
2528 return LYEXT_SUBSTMT_MAX;
2529 case YANG_MIN_ELEMENTS:
2530 return LYEXT_SUBSTMT_MIN;
2531 case YANG_POSITION:
2532 return LYEXT_SUBSTMT_POSITION;
2533 case YANG_UNIQUE:
2534 return LYEXT_SUBSTMT_UNIQUE;
2535 case YANG_IF_FEATURE:
2536 return LYEXT_SUBSTMT_IFFEATURE;
2537 default:
2538 return LYEXT_SUBSTMT_SELF;
2539 }
2540}
2541
David Sedlákc5b20842019-08-13 10:18:31 +02002542/**
2543 * @brief map keyword to keyword-group.
2544 *
2545 * @param[in] ctx YIN parser context used for logging.
2546 * @param[in] kw Keyword that is child of module or submodule.
2547 * @param[out] group Group of keyword.
2548 *
2549 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2550 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002551static LY_ERR
2552kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2553{
2554 switch (kw) {
2555 /* module header */
2556 case YANG_NONE:
2557 case YANG_NAMESPACE:
2558 case YANG_PREFIX:
2559 case YANG_BELONGS_TO:
2560 case YANG_YANG_VERSION:
2561 *group = Y_MOD_MODULE_HEADER;
2562 break;
2563 /* linkage */
2564 case YANG_INCLUDE:
2565 case YANG_IMPORT:
2566 *group = Y_MOD_LINKAGE;
2567 break;
2568 /* meta */
2569 case YANG_ORGANIZATION:
2570 case YANG_CONTACT:
2571 case YANG_DESCRIPTION:
2572 case YANG_REFERENCE:
2573 *group = Y_MOD_META;
2574 break;
2575 /* revision */
2576 case YANG_REVISION:
2577 *group = Y_MOD_REVISION;
2578 break;
2579 /* body */
2580 case YANG_ANYDATA:
2581 case YANG_ANYXML:
2582 case YANG_AUGMENT:
2583 case YANG_CHOICE:
2584 case YANG_CONTAINER:
2585 case YANG_DEVIATION:
2586 case YANG_EXTENSION:
2587 case YANG_FEATURE:
2588 case YANG_GROUPING:
2589 case YANG_IDENTITY:
2590 case YANG_LEAF:
2591 case YANG_LEAF_LIST:
2592 case YANG_LIST:
2593 case YANG_NOTIFICATION:
2594 case YANG_RPC:
2595 case YANG_TYPEDEF:
2596 case YANG_USES:
2597 case YANG_CUSTOM:
2598 *group = Y_MOD_BODY;
2599 break;
2600 default:
2601 LOGINT(ctx->xml_ctx.ctx);
2602 return LY_EINT;
2603 }
2604
2605 return LY_SUCCESS;
2606}
2607
David Sedlákc5b20842019-08-13 10:18:31 +02002608/**
2609 * @brief Check if relative order of two keywords is valid.
2610 *
2611 * @param[in] ctx YIN parser context used for logging.
2612 * @param[in] kw Current keyword.
2613 * @param[in] next_kw Next keyword.
2614 * @param[in] parrent Identification of parrent element, can be se to to YANG_MODULE of YANG_SUBMODULE,
2615 * because relative order is required only in module and submodule sub-elements, used for logging.
2616 *
2617 * @return LY_SUCCESS on succes and LY_EVALID if relative order is invalid.
2618 */
David Sedláke6cd89e2019-08-07 12:46:02 +02002619static LY_ERR
2620yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2621{
2622 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2623 enum yang_module_stmt gr, next_gr;
2624
2625 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2626 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2627
2628 if (gr > next_gr) {
2629 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2630 return LY_EVALID;
2631 }
2632
2633 return LY_SUCCESS;
2634}
2635
David Sedlákd6e56892019-07-01 15:40:24 +02002636LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002637yin_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 +02002638 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 +02002639{
2640 LY_ERR ret = LY_SUCCESS;
David Sedlák8e7bda82019-07-16 17:57:50 +02002641 char *out = NULL;
David Sedlákc5b20842019-08-13 10:18:31 +02002642 const char *prefix, *name;
2643 size_t out_len = 0, prefix_len, name_len;
David Sedlák8e7bda82019-07-16 17:57:50 +02002644 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002645 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002646 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002647 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002648 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002649
David Sedlákb0faad82019-07-04 14:28:59 +02002650 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002651
David Sedlákda8ffa32019-07-08 14:17:10 +02002652 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2653 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002654 /* current element has subelements as content */
2655 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002656 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákc5b20842019-08-13 10:18:31 +02002657 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
David Sedlákd6e56892019-07-01 15:40:24 +02002658 LY_CHECK_GOTO(ret, cleanup);
David Sedlákc5b20842019-08-13 10:18:31 +02002659 if (!name) {
David Sedlákd6e56892019-07-01 15:40:24 +02002660 /* end of current element reached */
2661 break;
2662 }
David Sedlák1af868e2019-07-17 17:03:14 +02002663 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002664 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002665 last_kw = kw;
David Sedlákc5b20842019-08-13 10:18:31 +02002666 kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002667
2668 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002669 subelem = get_record(kw, subelem_info_size, subelem_info);
2670 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002671 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2672 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2673 } else {
David Sedlákc5b20842019-08-13 10:18:31 +02002674 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(current_element));
David Sedlák4ffcec82019-07-25 15:10:21 +02002675 }
David Sedlákd6e56892019-07-01 15:40:24 +02002676 ret = LY_EVALID;
2677 goto cleanup;
2678 }
2679
David Sedláke6cd89e2019-08-07 12:46:02 +02002680 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2681 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2682 LY_CHECK_GOTO(ret, cleanup);
2683 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002684
David Sedlák4ffcec82019-07-25 15:10:21 +02002685 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002686 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002687 /* subelement uniquenes */
David Sedlák1538a842019-08-08 15:38:51 +02002688 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +02002689 return LY_EVALID;
2690 }
David Sedlák1af868e2019-07-17 17:03:14 +02002691 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002692 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002693 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002694 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002695 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002696 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002697 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002698 if (ctx->mod_version < 2) {
David Sedlák1538a842019-08-08 15:38:51 +02002699 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002700 ret = LY_EVALID;
2701 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002702 }
2703 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002704 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002705 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002706
David Sedlákd6e56892019-07-01 15:40:24 +02002707 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002708 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002709 case YANG_CUSTOM:
David Sedlákc5b20842019-08-13 10:18:31 +02002710 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name, prefix_len),
2711 namelen2fulllen(name_len, prefix_len),
David Sedlák1af868e2019-07-17 17:03:14 +02002712 kw2lyext_substmt(current_element),
2713 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002714 break;
2715 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002716 case YANG_RPC:
David Sedlák6881b512019-08-13 12:52:00 +02002717 ret = yin_parse_action(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002718 break;
2719 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002720 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002721 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002722 break;
2723 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002724 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002725 break;
2726 case YANG_AUGMENT:
David Sedlák6881b512019-08-13 12:52:00 +02002727 ret = yin_parse_augment(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002728 break;
2729 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002730 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002731 type = (struct lysp_type *)subelem->dest;
2732 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002733 Y_PREF_IDENTIF_ARG, exts);
2734 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002735 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002736 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002737 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2738 } else {
2739 LOGINT(ctx->xml_ctx.ctx);
2740 ret = LY_EINT;
2741 }
David Sedlákd6e56892019-07-01 15:40:24 +02002742 break;
2743 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002744 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002745 break;
2746 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002747 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002748 break;
2749 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002750 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002751 break;
2752 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002753 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002754 break;
2755 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002756 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002757 break;
2758 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002759 case YANG_DESCRIPTION:
2760 case YANG_ORGANIZATION:
2761 case YANG_REFERENCE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002762 ret = yin_parse_meta_element(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002763 break;
2764 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002765 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002766 break;
2767 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002768 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2769 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2770 YIN_ARG_VALUE, Y_STR_ARG, exts);
2771 } else {
2772 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2773 YIN_ARG_VALUE, Y_STR_ARG, exts);
2774 }
David Sedlákd6e56892019-07-01 15:40:24 +02002775 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002776 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002777 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002778 break;
2779 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002780 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002781 break;
David Sedlák43801c92019-08-05 15:58:54 +02002782 case YANG_ENUM:
2783 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2784 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002785 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002786 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002787 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002788 break;
2789 case YANG_ERROR_MESSAGE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002790 ret = yin_parse_err_msg_element(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002791 break;
2792 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002793 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002794 break;
2795 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002796 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002797 break;
2798 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002799 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002800 break;
2801 case YANG_GROUPING:
David Sedlák6881b512019-08-13 12:52:00 +02002802 ret = yin_parse_grouping(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002803 break;
2804 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002805 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002806 break;
2807 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002808 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2809 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002810 break;
2811 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002812 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002813 break;
2814 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002815 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002816 break;
2817 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002818 case YANG_OUTPUT:
2819 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002820 break;
2821 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002822 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2823 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002824 break;
2825 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002826 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002827 break;
2828 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002829 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002830 break;
2831 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002832 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002833 type->length = calloc(1, sizeof *type->length);
2834 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002835 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002836 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002837 break;
2838 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002839 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002840 break;
2841 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002842 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002843 break;
2844 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002845 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002846 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002847 break;
2848 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002849 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002850 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002851 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002852 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002853 break;
2854 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002855 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002856 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002857 break;
2858 case YANG_NOTIFICATION:
David Sedlák6881b512019-08-13 12:52:00 +02002859 ret = yin_parse_notification(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002860 break;
2861 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002862 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002863 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002864 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002865 type = (struct lysp_type *)subelem->dest;
2866 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlákd1144562019-08-06 12:36:14 +02002867 YIN_ARG_VALUE, Y_STR_ARG, &type->exts);
David Sedlák58979872019-07-12 11:42:43 +02002868 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002869 break;
2870 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002871 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002872 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002873 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002874 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002875 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2876 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002877 break;
2878 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002879 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2880 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002881 break;
2882 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002883 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2884 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002885 break;
2886 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002887 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002888 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002889 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002890 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002891 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002892 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002893 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002894 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002895 break;
2896 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002897 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002898 break;
2899 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002900 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002901 break;
2902 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002903 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002904 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002905 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002906 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002907 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002908 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002909 if (current_element == YANG_DEVIATE) {
2910 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2911 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2912 type = *((struct lysp_type **)subelem->dest);
2913 } else {
2914 type = (struct lysp_type *)subelem->dest;
2915 }
David Sedlák374d2b32019-07-17 15:06:55 +02002916 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002917 if (current_element == YANG_TYPE) {
2918 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002919 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002920 type = nested_type;
2921 }
David Sedlák1af868e2019-07-17 17:03:14 +02002922 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002923 break;
2924 case YANG_TYPEDEF:
David Sedlák6881b512019-08-13 12:52:00 +02002925 ret = yin_parse_typedef(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002926 break;
2927 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002928 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002929 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002930 break;
2931 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002932 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002933 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002934 break;
2935 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002936 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002937 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002938 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002939 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002940 break;
2941 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002942 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002943 break;
2944 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002945 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002946 break;
2947 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002948 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002949 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002950 break;
2951 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002952 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002953 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002954 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002955 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002956 FREE_ARRAY(ctx, attrs, free_arg_rec);
2957 attrs = NULL;
2958 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002959 }
2960 } else {
2961 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002962 /* save text content, if text_content isn't set, it's just ignored */
David Sedlákc5b20842019-08-13 10:18:31 +02002963 /* no resources are allocated in this branch, no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002964 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002965 if (text_content) {
2966 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002967 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002968 if (!*text_content) {
2969 free(out);
2970 return LY_EMEM;
2971 }
2972 } else {
2973 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002974 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002975 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002976 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002977 }
2978 }
2979 }
David Sedlákd6e56892019-07-01 15:40:24 +02002980 /* load closing element */
David Sedlákc5b20842019-08-13 10:18:31 +02002981 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákd6e56892019-07-01 15:40:24 +02002982 }
2983 }
David Sedlák8b754462019-07-25 16:22:13 +02002984 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2985 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002986
2987cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002988 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002989 return ret;
2990}
2991
David Sedlák619db942019-07-03 14:47:30 +02002992LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002993yin_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 +02002994 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002995{
2996 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002997 char *out;
2998 const char *name, *prefix;
2999 size_t out_len, prefix_len, name_len;
3000 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003001 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02003002 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3003 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003004
David Sedlákda8ffa32019-07-08 14:17:10 +02003005 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003006
3007 e->yin = 0;
3008 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02003009 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02003010 e->insubstmt = subelem;
3011 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003012 e->yin |= LYS_YIN;
3013
David Sedlákb1a78352019-06-28 16:16:29 +02003014 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02003015 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02003016 if (!iter->prefix) {
3017 new_subelem = calloc(1, sizeof(*new_subelem));
3018 if (!e->child) {
3019 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02003020 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02003021 last_subelem->next = new_subelem;
3022 }
3023 last_subelem = new_subelem;
3024
3025 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003026 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
3027 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003028 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003029 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
3030 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003031 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003032 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
3033 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003034 }
3035 }
3036 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003037
David Sedlákf250ecf2019-07-01 11:02:05 +02003038 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003039 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3040 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003041 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003042 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3043 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003044 if (!name) {
3045 /* end of extension instance reached */
3046 break;
3047 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003048 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003049 if (!e->child) {
3050 e->child = new_subelem;
3051 } else {
3052 last_subelem->next = new_subelem;
3053 }
3054 last_subelem = new_subelem;
3055 }
David Sedlák555c7202019-07-04 12:14:12 +02003056 } else {
3057 /* save text content */
3058 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003059 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02003060 if (!e->argument) {
3061 free(out);
3062 return LY_EMEM;
3063 }
3064 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003065 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003066 LY_CHECK_RET(!e->argument, LY_EMEM);
3067 }
David Sedlákda8ffa32019-07-08 14:17:10 +02003068 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02003069 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02003070 }
David Sedlákb1a78352019-06-28 16:16:29 +02003071 }
3072
3073 return LY_SUCCESS;
3074}
3075
3076LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003077yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3078 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003079{
3080 LY_ERR ret = LY_SUCCESS;
3081 const char *temp_prefix, *temp_name;
3082 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003083 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003084 int dynamic;
3085 struct yin_arg_record *subelem_args = NULL;
3086 struct lysp_stmt *last = NULL, *new = NULL;
3087
3088 /* allocate new structure for element */
3089 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003090 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3091 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003092
3093 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003094 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003095 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003096 /* add new element to linked-list */
3097 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003098 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003099 if (!(*element)->child) {
3100 /* save first */
3101 (*element)->child = new;
3102 } else {
3103 last->next = new;
3104 }
3105 last = new;
3106
3107 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003108 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 +02003109 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003110 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003111 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003112 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3113 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003114 /* attributes with prefix are ignored */
3115 if (!temp_prefix) {
3116 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003117 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02003118 if (!last->arg) {
3119 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003120 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02003121 ret = LY_EMEM;
3122 goto err;
3123 }
3124 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003125 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3126 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003127 }
3128 }
3129 }
3130
3131 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003132 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003133 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003134 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003135 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003136 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 +02003137 LY_CHECK_GOTO(ret, err);
3138 if (!name) {
3139 /* end of element reached */
3140 break;
3141 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003142 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003143 LY_CHECK_GOTO(ret, err);
3144 last = last->next;
3145 }
3146 } else {
3147 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003148 if (out_len != 0) {
3149 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003150 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02003151 if (!(*element)->arg) {
3152 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003153 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02003154 ret = LY_EMEM;
3155 goto err;
3156 }
3157 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003158 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3159 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003160 }
David Sedlákb1a78352019-06-28 16:16:29 +02003161 }
3162 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003163 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 +02003164 LY_CHECK_GOTO(ret, err);
3165 }
3166
David Sedlákda8ffa32019-07-08 14:17:10 +02003167 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02003168 return LY_SUCCESS;
3169
3170err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003171 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003172 return ret;
3173}
3174
3175LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003176yin_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 +02003177{
David Sedlák4f03b932019-07-26 13:01:47 +02003178 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3179 struct tree_node_meta node_meta = {NULL, &mod->data};
David Sedlák6881b512019-08-13 12:52:00 +02003180 struct tree_node_meta aug_meta = {NULL, (struct lysp_node **)&mod->augments};
3181 struct tree_node_meta grp_meta = {NULL, (struct lysp_node **)&mod->groupings};
David Sedlák4f03b932019-07-26 13:01:47 +02003182 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
David Sedlák6881b512019-08-13 12:52:00 +02003183 struct tree_node_meta notif_meta = {NULL, (struct lysp_node **)&mod->notifs};
3184 struct tree_node_meta act_meta = {NULL, (struct lysp_node **)&mod->rpcs};
3185 struct tree_node_meta tpdf_meta = {NULL, (struct lysp_node **)&mod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02003186 struct import_meta imp_meta = {mod->mod->prefix, &mod->imports};
David Sedlák4f03b932019-07-26 13:01:47 +02003187 struct yin_subelement subelems[28] = {
3188 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3189 {YANG_ANYXML, &node_meta, 0},
3190 {YANG_AUGMENT, &aug_meta, 0},
3191 {YANG_CHOICE, &node_meta, 0},
3192 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
3193 {YANG_CONTAINER, &node_meta, 0},
3194 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
3195 {YANG_DEVIATION, &mod->deviations, 0},
3196 {YANG_EXTENSION, &mod->extensions, 0},
3197 {YANG_FEATURE, &mod->features, 0},
3198 {YANG_GROUPING, &grp_meta, 0},
3199 {YANG_IDENTITY, &mod->identities, 0},
David Sedlák298ff6d2019-07-26 14:29:03 +02003200 {YANG_IMPORT, &imp_meta, 0},
David Sedlák4f03b932019-07-26 13:01:47 +02003201 {YANG_INCLUDE, &inc_meta, 0},
3202 {YANG_LEAF, &node_meta, 0},
3203 {YANG_LEAF_LIST, &node_meta, 0},
3204 {YANG_LIST, &node_meta, 0},
3205 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3206 {YANG_NOTIFICATION, &notif_meta, 0},
3207 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3208 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3209 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3210 {YANG_REVISION, &mod->revs, 0},
3211 {YANG_RPC, &act_meta, 0},
3212 {YANG_TYPEDEF, &tpdf_meta, 0},
3213 {YANG_USES, &node_meta, 0},
3214 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003215 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003216 };
David Sedlák3b4db242018-10-19 16:11:01 +02003217
David Sedlák4f03b932019-07-26 13:01:47 +02003218 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003219}
3220
3221LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003222yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3223{
3224 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3225 struct tree_node_meta node_meta = {NULL, &submod->data};
David Sedlák6881b512019-08-13 12:52:00 +02003226 struct tree_node_meta aug_meta = {NULL, (struct lysp_node **)&submod->augments};
3227 struct tree_node_meta grp_meta = {NULL, (struct lysp_node **)&submod->groupings};
David Sedlák298ff6d2019-07-26 14:29:03 +02003228 struct include_meta inc_meta = {submod->name, &submod->includes};
David Sedlák6881b512019-08-13 12:52:00 +02003229 struct tree_node_meta notif_meta = {NULL, (struct lysp_node **)&submod->notifs};
3230 struct tree_node_meta act_meta = {NULL, (struct lysp_node **)&submod->rpcs};
3231 struct tree_node_meta tpdf_meta = {NULL, (struct lysp_node **)&submod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02003232 struct import_meta imp_meta = {submod->prefix, &submod->imports};
3233 struct yin_subelement subelems[27] = {
3234 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3235 {YANG_ANYXML, &node_meta, 0},
3236 {YANG_AUGMENT, &aug_meta, 0},
3237 {YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3238 {YANG_CHOICE, &node_meta, 0},
3239 {YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE},
3240 {YANG_CONTAINER, &node_meta, 0},
3241 {YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE},
3242 {YANG_DEVIATION, &submod->deviations, 0},
3243 {YANG_EXTENSION, &submod->extensions, 0},
3244 {YANG_FEATURE, &submod->features, 0},
3245 {YANG_GROUPING, &grp_meta, 0},
3246 {YANG_IDENTITY, &submod->identities, 0},
3247 {YANG_IMPORT, &imp_meta, 0},
3248 {YANG_INCLUDE, &inc_meta, 0},
3249 {YANG_LEAF, &node_meta, 0},
3250 {YANG_LEAF_LIST, &node_meta, 0},
3251 {YANG_LIST, &node_meta, 0},
3252 {YANG_NOTIFICATION, &notif_meta, 0},
3253 {YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE},
3254 {YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE},
3255 {YANG_REVISION, &submod->revs, 0},
3256 {YANG_RPC, &act_meta, 0},
3257 {YANG_TYPEDEF, &tpdf_meta, 0},
3258 {YANG_USES, &node_meta, 0},
3259 {YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3260 {YANG_CUSTOM, NULL, 0}
3261 };
3262
3263 return yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3264}
3265
3266LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003267yin_parse_submodule(struct yin_parser_ctx **yin_ctx, struct ly_ctx *ctx, struct lys_parser_ctx *main_ctx, const char *data, struct lysp_submodule **submod)
David Sedlák8985a142019-07-31 16:43:06 +02003268{
3269 enum yang_keyword kw = YANG_NONE;
3270 LY_ERR ret = LY_SUCCESS;
3271 const char *prefix, *name;
3272 size_t prefix_len, name_len;
3273 struct yin_arg_record *attrs = NULL;
3274 struct lysp_submodule *mod_p = NULL;
3275
3276 /* create context */
3277 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003278 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003279 (*yin_ctx)->xml_ctx.ctx = ctx;
3280 (*yin_ctx)->xml_ctx.line = 1;
3281
David Sedlák1b623122019-08-05 15:27:49 +02003282 /* map the typedefs and groupings list from main context to the submodule's context */
3283 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3284 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3285
David Sedlák8985a142019-07-31 16:43:06 +02003286 /* check submodule */
3287 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3288 LY_CHECK_GOTO(ret, cleanup);
3289 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3290 LY_CHECK_GOTO(ret, cleanup);
3291 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3292
3293 if (kw == YANG_MODULE) {
3294 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3295 ret = LY_EINVAL;
3296 goto cleanup;
3297 } else if (kw != YANG_SUBMODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003298 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák8985a142019-07-31 16:43:06 +02003299 ret = LY_EVALID;
3300 goto cleanup;
3301 }
3302
3303 mod_p = calloc(1, sizeof *mod_p);
3304 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3305 mod_p->parsing = 1;
3306
3307 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3308 LY_CHECK_GOTO(ret, cleanup);
3309
David Sedlák6d781b62019-08-02 15:22:52 +02003310 name = NULL;
3311 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3312 const char *temp_data = data;
3313 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3314 data = temp_data;
3315 }
3316 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003317 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, data, strlen(data) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003318 ret = LY_EVALID;
3319 goto cleanup;
3320 }
3321
David Sedlák8985a142019-07-31 16:43:06 +02003322 mod_p->parsing = 0;
3323 *submod = mod_p;
3324
3325cleanup:
3326 if (ret) {
3327 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003328 yin_parser_ctx_free(*yin_ctx);
3329 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003330 }
3331
3332 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3333 return ret;
3334}
3335
3336LY_ERR
3337yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003338{
David Sedláke4889912018-11-02 09:52:40 +01003339 LY_ERR ret = LY_SUCCESS;
3340 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003341 struct lysp_module *mod_p = NULL;
3342 const char *prefix, *name;
3343 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003344 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003345
David Sedlák8985a142019-07-31 16:43:06 +02003346 /* create context */
3347 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003348 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003349 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3350 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003351
David Sedlák8985a142019-07-31 16:43:06 +02003352 /* check module */
3353 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003354 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003355 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003356 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003357 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003358 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003359 LOGERR(mod->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
David Sedlák3017da42019-02-15 09:48:04 +01003360 ret = LY_EINVAL;
3361 goto cleanup;
3362 } else if (kw != YANG_MODULE) {
David Sedlák1538a842019-08-08 15:38:51 +02003363 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003364 ret = LY_EVALID;
3365 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003366 }
3367
David Sedlák3017da42019-02-15 09:48:04 +01003368 /* allocate module */
3369 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003370 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003371 mod_p->mod = mod;
3372 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003373
David Sedlák00250342019-06-21 14:19:39 +02003374 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003375 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003376 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003377
David Sedlák1b623122019-08-05 15:27:49 +02003378 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003379 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3380 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3381 }
3382 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
David Sedlák1538a842019-08-08 15:38:51 +02003383 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, data, strlen(data) > 15 ? "..." : "");
David Sedlák6d781b62019-08-02 15:22:52 +02003384
3385 ret = LY_EVALID;
3386 goto cleanup;
3387 }
3388
David Sedlák3017da42019-02-15 09:48:04 +01003389 mod_p->parsing = 0;
3390 mod->parsed = mod_p;
3391
3392cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003393 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003394 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003395 yin_parser_ctx_free(*yin_ctx);
3396 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003397 }
David Sedlák8985a142019-07-31 16:43:06 +02003398 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003399 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003400}