blob: 14ccb929533c99ca60d9fc626e7449cda3a43d2a [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ák872c7b42018-10-26 13:15:20 +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áka7406952019-04-05 10:33:07 +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ák555c7202019-07-04 12:14:12 +0200170 struct sized_string prefix, name;
David Sedláka7406952019-04-05 10:33:07 +0200171
David Sedlák555c7202019-07-04 12:14:12 +0200172 /* load all attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +0200173 while (ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
174 ret = lyxml_get_attribute(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlák00250342019-06-21 14:19:39 +0200175 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200176
David Sedlákda8ffa32019-07-08 14:17:10 +0200177 if (ctx->xml_ctx.status == LYXML_ATTR_CONTENT) {
178 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, *attrs, argument_record, ret, cleanup);
David Sedlák555c7202019-07-04 12:14:12 +0200179 argument_record->name = name.value;
180 argument_record->name_len = name.len;
181 argument_record->prefix = prefix.value;
182 argument_record->prefix_len = prefix.len;
David Sedlákda8ffa32019-07-08 14:17:10 +0200183 ret = lyxml_get_string(&ctx->xml_ctx, data, &argument_record->content, &argument_record->content_len,
David Sedlák57715b12019-06-17 13:05:22 +0200184 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák00250342019-06-21 14:19:39 +0200185 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200186 }
187 }
188
David Sedlák8f7a1172019-06-20 14:42:18 +0200189cleanup:
190 if (ret != LY_SUCCESS) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200191 FREE_ARRAY(ctx, *attrs, free_arg_rec);
David Sedlákb4e44562019-07-04 15:42:12 +0200192 *attrs = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200193 }
194 return ret;
195}
196
David Sedlák4a650532019-07-10 11:55:18 +0200197LY_ERR
198yin_validate_value(struct yin_parser_ctx *ctx, enum yang_arg val_type, char *val, size_t len)
199{
200 int prefix = 0;
201 unsigned int c;
202 size_t utf8_char_len;
203 size_t already_read = 0;
204 while (already_read < len) {
205 LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
206 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
207 already_read += utf8_char_len;
208 LY_CHECK_ERR_RET(already_read > len, LOGINT(ctx->xml_ctx.ctx), LY_EINT);
209
210 switch (val_type) {
211 case Y_IDENTIF_ARG:
212 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, NULL));
213 break;
214 case Y_PREF_IDENTIF_ARG:
215 LY_CHECK_RET(lysp_check_identifierchar((struct lys_parser_ctx *)ctx, c, !already_read, &prefix));
216 break;
217 case Y_STR_ARG:
218 case Y_MAYBE_STR_ARG:
219 LY_CHECK_RET(lysp_check_stringchar((struct lys_parser_ctx *)ctx, c));
220 break;
221 }
222 }
223
224 return LY_SUCCESS;
225}
226
David Sedlákb4e44562019-07-04 15:42:12 +0200227/**
228 * @brief Parse yin argument.
229 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200230 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200231 * @param[in] attrs ([Sized array](@ref sizedarrays)) of attributes.
David Sedlákb4e44562019-07-04 15:42:12 +0200232 * @param[in,out] data Data to read from.
David Sedlák4a650532019-07-10 11:55:18 +0200233 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
234 * special argument).
David Sedlákb4e44562019-07-04 15:42:12 +0200235 * @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 +0200236 * @param[in] val_type Type of expected value of attribute.
David Sedlákb4e44562019-07-04 15:42:12 +0200237 * @param[in] current_element Identification of current element, used for logging.
238 *
239 * @return LY_ERR values.
240 */
241static LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +0200242yin_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 +0200243 const char **arg_val, enum yang_arg val_type, enum yang_keyword current_element)
David Sedlák8f7a1172019-06-20 14:42:18 +0200244{
David Sedlák8f7a1172019-06-20 14:42:18 +0200245 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
246 struct yin_arg_record *iter = NULL;
David Sedlák619db942019-07-03 14:47:30 +0200247 bool found = false;
David Sedlák8f7a1172019-06-20 14:42:18 +0200248
David Sedlák1bccdfa2019-06-17 15:55:27 +0200249 /* validation of attributes */
David Sedlák1f90d252019-07-10 17:09:32 +0200250 LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
David Sedlák00250342019-06-21 14:19:39 +0200251 /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
252 if (!iter->prefix) {
David Sedlák060b00e2019-06-19 11:12:06 +0200253 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200254 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200255 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200256 } else if (arg == arg_type) {
David Sedlák292763b2019-07-09 11:10:53 +0200257 LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Duplicit definition of %s attribute in %s element",
258 yin_attr2str(arg), ly_stmt2str(current_element)), LY_EVALID);
David Sedlák619db942019-07-03 14:47:30 +0200259 found = true;
David Sedlák4a650532019-07-10 11:55:18 +0200260 LY_CHECK_RET(yin_validate_value(ctx, val_type, iter->content, iter->content_len));
David Sedlák57715b12019-06-17 13:05:22 +0200261 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200262 *arg_val = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
David Sedlák619db942019-07-03 14:47:30 +0200263 LY_CHECK_RET(!(*arg_val), LY_EMEM);
David Sedlák00250342019-06-21 14:19:39 +0200264 /* string is no longer supposed to be freed when the sized array is freed */
265 iter->dynamic_content = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200266 } else {
David Sedlák99295322019-07-17 11:34:18 +0200267 if (iter->content_len == 0) {
268 *arg_val = lydict_insert(ctx->xml_ctx.ctx, "", 0);
269 } else {
270 *arg_val = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
271 LY_CHECK_RET(!(*arg_val), LY_EMEM);
272 }
David Sedlák57715b12019-06-17 13:05:22 +0200273 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200274 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +0200275 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\" of %s element.", iter->name_len, iter->name, ly_stmt2str(current_element));
David Sedlák619db942019-07-03 14:47:30 +0200276 return LY_EVALID;
David Sedláka7406952019-04-05 10:33:07 +0200277 }
278 }
279 }
280
David Sedlák292763b2019-07-09 11:10:53 +0200281 /* anything else than Y_MAYBE_STR_ARG is mandatory */
282 if (val_type != Y_MAYBE_STR_ARG && !found) {
David Sedlák9c40a922019-07-08 17:04:43 +0200283 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 +0200284 return LY_EVALID;
285 }
286
287 return LY_SUCCESS;
David Sedláka7406952019-04-05 10:33:07 +0200288}
289
David Sedlákd6e56892019-07-01 15:40:24 +0200290/**
David Sedlákda8ffa32019-07-08 14:17:10 +0200291 * @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 +0200292 *
293 * @param[in] type Type of wanted record.
294 * @param[in] array_size Size of array.
295 * @param[in] array Searched array.
296 *
297 * @return Pointer to desired record on success, NULL if element is not in the array.
298 */
David Sedlákb4e44562019-07-04 15:42:12 +0200299static struct yin_subelement *
David Sedlákb0faad82019-07-04 14:28:59 +0200300get_record(enum yang_keyword type, signed char array_size, struct yin_subelement *array)
David Sedlákd6e56892019-07-01 15:40:24 +0200301{
David Sedlákb0faad82019-07-04 14:28:59 +0200302 signed char left = 0, right = array_size - 1, middle;
303
304 while (left <= right) {
305 middle = left + (right - left) / 2;
306
307 if (array[middle].type == type) {
308 return &array[middle];
309 }
310
311 if (array[middle].type < type) {
312 left = middle + 1;
313 } else {
314 right = middle - 1;
David Sedlákd6e56892019-07-01 15:40:24 +0200315 }
316 }
317
318 return NULL;
319}
320
David Sedlákbba38e52019-07-09 15:20:01 +0200321/**
322 * @brief Helper function to check mandatory constraint of subelement.
323 *
324 * @param[in,out] ctx Yin parser context for logging and to store current state.
325 * @param[in] subelem_info Array of information about subelements.
326 * @param[in] subelem_info_size Size of subelem_info array.
327 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
328 *
329 * @return LY_ERR values.
330 */
331static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200332yin_check_subelem_mandatory_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedlákb0faad82019-07-04 14:28:59 +0200333 signed char subelem_info_size, enum yang_keyword current_element)
David Sedlák21f87cd2019-07-03 16:53:23 +0200334{
David Sedlákb0faad82019-07-04 14:28:59 +0200335 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200336 /* 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 +0200337 if (subelem_info[i].flags & YIN_SUBELEM_MANDATORY && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200338 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory subelement %s of %s element.",
David Sedlák555c7202019-07-04 12:14:12 +0200339 ly_stmt2str(subelem_info[i].type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200340 return LY_EVALID;
341 }
342 }
343
344 return LY_SUCCESS;
345}
346
David Sedlákbba38e52019-07-09 15:20:01 +0200347/**
348 * @brief Helper function to check "first" constraint of subelement.
349 *
350 * @param[in,out] ctx Yin parser context for logging and to store current state.
351 * @param[in] subelem_info Array of information about subelements.
352 * @param[in] subelem_info_size Size of subelem_info array.
353 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
354 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement.
355 *
356 * @return LY_ERR values.
357 */
358static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200359yin_check_subelem_first_constraint(struct yin_parser_ctx *ctx, struct yin_subelement *subelem_info,
David Sedláke1a30302019-07-10 13:49:38 +0200360 signed char subelem_info_size, enum yang_keyword current_element,
361 struct yin_subelement *exp_first)
David Sedlák21f87cd2019-07-03 16:53:23 +0200362{
David Sedlákb0faad82019-07-04 14:28:59 +0200363 for (signed char i = 0; i < subelem_info_size; ++i) {
David Sedlák21f87cd2019-07-03 16:53:23 +0200364 if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
David Sedlákda8ffa32019-07-08 14:17:10 +0200365 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Subelement %s of %s element must be defined as first subelement.",
David Sedlák555c7202019-07-04 12:14:12 +0200366 ly_stmt2str(exp_first->type), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +0200367 return LY_EVALID;
368 }
369 }
370
371 return LY_SUCCESS;
372}
373
David Sedlákbba38e52019-07-09 15:20:01 +0200374/**
375 * @brief Helper function to check if array of information about subelements is in ascending order.
376 *
377 * @param[in] subelem_info Array of information about subelements.
378 * @param[in] subelem_info_size Size of subelem_info array.
379 *
380 * @return True iff subelem_info array is in ascending order, False otherwise.
381 */
David Sedlák5545f5d2019-07-11 11:55:16 +0200382#ifndef NDEBUG
David Sedlákbba38e52019-07-09 15:20:01 +0200383static bool
David Sedlákb0faad82019-07-04 14:28:59 +0200384is_ordered(struct yin_subelement *subelem_info, signed char subelem_info_size)
385{
David Sedlák292763b2019-07-09 11:10:53 +0200386 enum yang_keyword current = YANG_NONE; /* 0 (minimal value) */
David Sedlákb0faad82019-07-04 14:28:59 +0200387
388 for (signed char i = 0; i < subelem_info_size; ++i) {
389 if (subelem_info[i].type <= current) {
390 return false;
391 }
392 current = subelem_info[i].type;
393 }
394
395 return true;
396}
David Sedlák5545f5d2019-07-11 11:55:16 +0200397#endif
David Sedlákb0faad82019-07-04 14:28:59 +0200398
David Sedlákd6e56892019-07-01 15:40:24 +0200399/**
David Sedlákb4e44562019-07-04 15:42:12 +0200400 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
401 * for example prefix or namespace element.
David Sedlákd6e56892019-07-01 15:40:24 +0200402 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200403 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200404 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákd6e56892019-07-01 15:40:24 +0200405 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákb4e44562019-07-04 15:42:12 +0200406 * @param[in] kw Type of current element.
407 * @param[out] value Where value of attribute should be stored.
408 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200409 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlákda8ffa32019-07-08 14:17:10 +0200410 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200411 *
David Sedlákd6e56892019-07-01 15:40:24 +0200412 * @return LY_ERR values.
413 */
David Sedlákb4e44562019-07-04 15:42:12 +0200414static LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +0200415yin_parse_simple_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlák292763b2019-07-09 11:10:53 +0200416 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 +0200417{
David Sedlák1f90d252019-07-10 17:09:32 +0200418 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák968ac342019-07-11 15:17:59 +0200419 struct yin_subelement subelems[1] = {
420 {YANG_CUSTOM, NULL, 0}
421 };
David Sedlákb4e44562019-07-04 15:42:12 +0200422
David Sedlákda8ffa32019-07-08 14:17:10 +0200423 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200424}
425
426/**
David Sedlákd3983112019-07-12 11:20:56 +0200427 * @brief Parse pattern element.
428 *
429 * @param[in,out] ctx Yin parser context for logging and to store current state.
430 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
431 * @param[in,out] data Data to read from, always moved to currently handled character.
432 * @param[in,out] patterns Restrictions to add to.
433 *
434 * @return LY_ERR values.
435 */
436static LY_ERR
437yin_parse_pattern(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
438 struct lysp_type *type)
439{
440 const char *real_value = NULL;
441 char *saved_value = NULL;
442 struct lysp_restr *restr;
443
444 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->patterns, restr, LY_EMEM);
445 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &real_value, Y_STR_ARG, YANG_PATTERN));
446 size_t len = strlen(real_value);
447
448 saved_value = malloc(len + 2);
449 LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
450 memmove(saved_value + 1, real_value, len);
451 FREE_STRING(ctx->xml_ctx.ctx, real_value);
452 saved_value[0] = 0x06;
453 saved_value[len + 1] = '\0';
454 restr->arg = lydict_insert_zc(ctx->xml_ctx.ctx, saved_value);
455 LY_CHECK_ERR_RET(!restr->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
456 type->flags |= LYS_SET_PATTERN;
457
458 struct yin_subelement subelems[6] = {
459 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
460 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
461 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
462 {YANG_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
463 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
464 {YANG_CUSTOM, NULL, 0}
465 };
466 return yin_parse_content(ctx, subelems, 6, data, YANG_PATTERN, NULL, &restr->exts);
467}
468
David Sedlákf75d55e2019-07-12 16:52:50 +0200469static LY_ERR
470yin_parse_fracdigits(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
471 struct lysp_type *type)
472{
473 const char *temp_val = NULL;
474 char *ptr;
475 unsigned long int num;
476
477 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_FRACTION_DIGITS));
478
479 if (temp_val[0] == '\0' || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
480 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
481 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
482 return LY_EVALID;
483 }
484
485 errno = 0;
486 num = strtoul(temp_val, &ptr, 10);
487 if (*ptr != '\0') {
488 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
489 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
490 return LY_EVALID;
491 }
492 if ((errno == ERANGE) || (num > 18)) {
493 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "fraction-digits");
494 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
495 return LY_EVALID;
496 }
David Sedlák2ab5d8e2019-07-16 11:19:41 +0200497 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedlákf75d55e2019-07-12 16:52:50 +0200498 type->fraction_digits = num;
499 type->flags |= LYS_SET_FRDIGITS;
500 struct yin_subelement subelems[1] = {
David Sedlákd1144562019-08-06 12:36:14 +0200501 {YANG_CUSTOM, NULL, 0}
David Sedlákf75d55e2019-07-12 16:52:50 +0200502 };
503 return yin_parse_content(ctx, subelems, 1, data, YANG_FRACTION_DIGITS, NULL, &type->exts);
504}
505
David Sedlák07869a52019-07-12 14:28:19 +0200506/**
David Sedlák43801c92019-08-05 15:58:54 +0200507 * @brief Parse enum element.
David Sedlák07869a52019-07-12 14:28:19 +0200508 *
509 * @param[in,out] ctx YIN parser context for logging and to store current state.
510 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
511 * @param[in,out] data Data to read from, always moved to currently handled character.
512 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
513 * @param[in,out] enums Enums or bits to add to.
514 *
515 * @return LY_ERR values.
516 */
David Sedlákca36c422019-07-12 12:47:55 +0200517static LY_ERR
David Sedlák43801c92019-08-05 15:58:54 +0200518yin_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 +0200519{
David Sedlák07869a52019-07-12 14:28:19 +0200520 struct lysp_type_enum *en;
David Sedlák1e696782019-07-17 15:06:07 +0200521
David Sedlák43801c92019-08-05 15:58:54 +0200522 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->enums, en, LY_EMEM);
523 type->flags |= LYS_SET_ENUM;
524 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_ENUM));
525 LY_CHECK_RET(lysp_check_enum_name((struct lys_parser_ctx *)ctx, en->name, strlen(en->name)));
526 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(en->name), "enum");
527 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "enum", en->name);
David Sedlákca36c422019-07-12 12:47:55 +0200528
529 struct yin_subelement subelems[6] = {
David Sedlák07869a52019-07-12 14:28:19 +0200530 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
531 {YANG_IF_FEATURE, &en->iffeatures, 0},
David Sedlák07869a52019-07-12 14:28:19 +0200532 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
533 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
David Sedlák43801c92019-08-05 15:58:54 +0200534 {YANG_VALUE, en, YIN_SUBELEM_UNIQUE},
David Sedlákca36c422019-07-12 12:47:55 +0200535 {YANG_CUSTOM, NULL, 0}
536 };
David Sedlák43801c92019-08-05 15:58:54 +0200537 return yin_parse_content(ctx, subelems, 6, data, YANG_ENUM, NULL, &en->exts);
538}
539
540/**
541 * @brief Parse bit element.
542 *
543 * @param[in,out] ctx YIN parser context for logging and to store current state.
544 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
545 * @param[in,out] data Data to read from, always moved to currently handled character.
546 * @param[in] enum_kw Identification of actual keyword, can be set to YANG_BIT or YANG_ENUM.
547 * @param[in,out] enums Enums or bits to add to.
548 *
549 * @return LY_ERR values.
550 */
551static LY_ERR
552yin_parse_bit(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
553 struct lysp_type *type)
554{
555 struct lysp_type_enum *en;
556
557 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, type->bits, en, LY_EMEM);
558 type->flags |= LYS_SET_BIT;
559 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, YANG_BIT));
560 CHECK_UNIQUENESS((struct lys_parser_ctx *)ctx, type->enums, name, "bit", en->name);
561
562 struct yin_subelement subelems[6] = {
563 {YANG_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
564 {YANG_IF_FEATURE, &en->iffeatures, 0},
565 {YANG_POSITION, en, YIN_SUBELEM_UNIQUE},
566 {YANG_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
567 {YANG_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
568 {YANG_CUSTOM, NULL, 0}
569 };
570 return yin_parse_content(ctx, subelems, 6, data, YANG_BIT, NULL, &en->exts);
David Sedlákca36c422019-07-12 12:47:55 +0200571}
572
David Sedlákd3983112019-07-12 11:20:56 +0200573/**
David Sedlák5f8191e2019-07-08 16:35:52 +0200574 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
575 * more instances, such as base or if-feature.
576 *
577 * @param[in,out] ctx YIN parser context for logging and to store current state.
David Sedlákbba38e52019-07-09 15:20:01 +0200578 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlák5f8191e2019-07-08 16:35:52 +0200579 * @param[in,out] data Data to read from, always moved to currently handled character.
580 * @param[in] kw Type of current element.
581 * @param[out] values Parsed values to add to.
582 * @param[in] arg_type Expected type of attribute.
David Sedlák292763b2019-07-09 11:10:53 +0200583 * @param[in] arg_val_type Type of expected value of attribute.
David Sedlák5f8191e2019-07-08 16:35:52 +0200584 * @param[in,out] exts Extension instance to add to.
585 *
586 * @return LY_ERR values.
587 */
588static LY_ERR
589yin_parse_simple_elements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword kw,
David Sedlák292763b2019-07-09 11:10:53 +0200590 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 +0200591{
592 const char **value;
David Sedlák5f8191e2019-07-08 16:35:52 +0200593 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *values, value, LY_EMEM);
David Sedlákcb5d83f2019-07-09 09:32:53 +0200594 uint32_t index = LY_ARRAY_SIZE(*values) - 1;
David Sedlák968ac342019-07-11 15:17:59 +0200595 struct yin_subelement subelems[1] = {
596 {YANG_CUSTOM, &index, 0}
597 };
598
David Sedlák1f90d252019-07-10 17:09:32 +0200599 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, value, arg_val_type, kw));
David Sedlák5f8191e2019-07-08 16:35:52 +0200600
601 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, exts);
602}
603
604/**
David Sedlákcf5569a2019-07-11 13:31:34 +0200605 * @brief Parse require instance element.
606 *
607 * @param[in,out] ctx Yin parser context for logging and to store current state.
608 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
609 * @param[in,out] data Data to read from, always moved to currently handled character.
610 * @prama[out] type Type structure to store value, flag and extensions.
611 *
612 * @return LY_ERR values.
613 */
614static LY_ERR
615yin_pasrse_reqinstance(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs,
616 const char **data, struct lysp_type *type)
617{
618 const char *temp_val = NULL;
David Sedlák968ac342019-07-11 15:17:59 +0200619 struct yin_subelement subelems[1] = {
620 {YANG_CUSTOM, NULL, 0}
621 };
David Sedlákcf5569a2019-07-11 13:31:34 +0200622
623 type->flags |= LYS_SET_REQINST;
624 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_REQUIRE_INSTANCE));
625 if (strcmp(temp_val, "true") == 0) {
626 type->require_instance = 1;
627 } else if (strcmp(temp_val, "false") != 0) {
628 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "require-instance");
629 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
630 return LY_EVALID;
631 }
632 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
633
634 return yin_parse_content(ctx, subelems, 1, data, YANG_REQUIRE_INSTANCE, NULL, &type->exts);
635}
636
637/**
David Sedlákce77bf52019-07-11 16:59:31 +0200638 * @brief Parse modifier element.
639 *
640 * @param[in,out] ctx Yin parser context for logging and to store current state.
641 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
642 * @param[in,out] data Data to read from, always moved to currently handled character.
643 * @param[in,out] pat Value to write to.
644 * @param[in,out] exts Extension instances to add to.
645 *
646 * @return LY_ERR values.
647 */
648static LY_ERR
649yin_parse_modifier(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
650 const char **pat, struct lysp_ext_instance **exts)
651{
David Sedlákd3983112019-07-12 11:20:56 +0200652 assert(**pat == 0x06);
David Sedlákce77bf52019-07-11 16:59:31 +0200653 const char *temp_val;
654 char *modified_val;
655 struct yin_subelement subelems[1] = {
656 {YANG_CUSTOM, NULL, 0}
657 };
658
659 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MODIFIER));
660 if (strcmp(temp_val, "invert-match") != 0) {
661 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "modifier");
662 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
663 return LY_EVALID;
664 }
David Sedlákd3983112019-07-12 11:20:56 +0200665 lydict_remove(ctx->xml_ctx.ctx, temp_val);
David Sedlákce77bf52019-07-11 16:59:31 +0200666
667 /* allocate new value */
David Sedlákd3983112019-07-12 11:20:56 +0200668 modified_val = malloc(strlen(*pat) + 1);
David Sedlákce77bf52019-07-11 16:59:31 +0200669 LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákd3983112019-07-12 11:20:56 +0200670 strcpy(modified_val, *pat);
671 lydict_remove(ctx->xml_ctx.ctx, *pat);
David Sedlákce77bf52019-07-11 16:59:31 +0200672
673 /* modify the new value */
674 modified_val[0] = 0x15;
675 *pat = lydict_insert_zc(ctx->xml_ctx.ctx, modified_val);
676
677 return yin_parse_content(ctx, subelems, 1, data, YANG_MODIFIER, NULL, exts);
678}
679
680/**
David Sedlákb7296dd2019-07-11 14:58:38 +0200681 * @brief Parse a restriction element (length, range or one instance of must).
682 *
683 * @param[in,out] ctx Yin parser context for logging and to store current state.
684 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
685 * @param[in,out] data Data to read from, always moved to currently handled character.
686 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to YANG_MUST, YANG_LENGTH or YANG_RANGE.
687 * @param[in]
688 */
689static LY_ERR
690yin_parse_restriction(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
691 enum yang_keyword restr_kw, struct lysp_restr *restr)
692{
693 assert(restr_kw == YANG_MUST || restr_kw == YANG_LENGTH || restr_kw == YANG_RANGE);
694 struct yin_subelement subelems[5] = {
David Sedlák968ac342019-07-11 15:17:59 +0200695 {YANG_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
696 {YANG_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
697 {YANG_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
698 {YANG_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
699 {YANG_CUSTOM, NULL, 0}
700 };
David Sedlákb7296dd2019-07-11 14:58:38 +0200701 /* argument of must is called condition, but argument of length and range is called value */
702 enum YIN_ARGUMENT arg_type = (restr_kw == YANG_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
703 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, arg_type, &restr->arg, Y_STR_ARG, restr_kw));
704
705 return yin_parse_content(ctx, subelems, 5, data, restr_kw, NULL, &restr->exts);
706}
707
708/**
David Sedlákbc9ec9c2019-07-11 15:53:55 +0200709 * @brief Parse must element.
710 *
711 * @param[in,out] ctx YIN parser context for logging and to store current state.
712 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
713 * @param[in,out] data Data to read from, always moved to currently handled character.
714 * @param[in,out] restrs Restrictions to add to.
715 *
716 * @return LY_ERR values.
717 */
718static LY_ERR
719yin_parse_must(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_restr **restrs)
720{
721 struct lysp_restr *restr;
722
723 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *restrs, restr, LY_EMEM);
724 return yin_parse_restriction(ctx, attrs, data, YANG_MUST, restr);
725}
726
727/**
David Sedlák5545f5d2019-07-11 11:55:16 +0200728 * @brief Parse position or value element.
729 *
730 * @param[in,out] ctx YIN parser context for logging and to store current state.
731 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
732 * @param[in,out] data Data to read from, always moved to currently handled character.
733 * @param[in] kw Type of current element, can be set to YANG_POSITION or YANG_VALUE.
734 * @param[out] enm Enum structure to save value, flags and extensions.
735 *
736 * @return LY_ERR values.
737 */
738static LY_ERR
739yin_parse_value_pos_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
740 enum yang_keyword kw, struct lysp_type_enum *enm)
741{
742 assert(kw == YANG_POSITION || kw == YANG_VALUE);
743 const char *temp_val = NULL;
744 char *ptr;
745 long int num;
746 unsigned long int unum;
747
748 /* set value flag */
749 enm->flags |= LYS_SET_VALUE;
750
751 /* get attribute value */
David Sedlákcf5569a2019-07-11 13:31:34 +0200752 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 +0200753 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '+') ||
754 ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((kw == YANG_POSITION) && !strcmp(temp_val, "-0"))) {
David Sedlák5545f5d2019-07-11 11:55:16 +0200755 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
756 goto error;
757 }
758
759 /* convert value */
760 errno = 0;
761 if (kw == YANG_VALUE) {
762 num = strtol(temp_val, &ptr, 10);
763 if (num < INT64_C(-2147483648) || num > INT64_C(2147483647)) {
764 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
765 goto error;
766 }
767 } else {
768 unum = strtoul(temp_val, &ptr, 10);
769 if (unum > UINT64_C(4294967295)) {
770 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
771 goto error;
772 }
773 }
774 /* check if whole argument value was converted */
775 if (*ptr != '\0') {
776 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, ly_stmt2str(kw));
David Sedlákebcd0eb2019-07-16 17:55:12 +0200777 goto error;
David Sedlák5545f5d2019-07-11 11:55:16 +0200778 }
779 if (errno == ERANGE) {
780 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, ly_stmt2str(kw));
781 goto error;
782 }
783 /* save correctly ternary operator can't be used because num and unum have different signes */
784 if (kw == YANG_VALUE) {
785 enm->value = num;
786 } else {
787 enm->value = unum;
788 }
789 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
790
791 /* parse subelements */
David Sedlák968ac342019-07-11 15:17:59 +0200792 struct yin_subelement subelems[1] = {
793 {YANG_CUSTOM, NULL, 0}
794 };
David Sedlák5545f5d2019-07-11 11:55:16 +0200795 return yin_parse_content(ctx, subelems, 1, data, kw, NULL, &enm->exts);
796
797 error:
798 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
799 return LY_EVALID;
800}
801
David Sedlák05404f62019-07-24 14:11:53 +0200802
803/**
804 * @brief Parse belongs-to element.
805 *
806 * @param[in] ctx Yin parser context for logging and to store current state.
807 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
808 * @param[in,out] data Data to read from, always moved to currently handled character.
809 * @param[out] submod Structure of submodule that is being parsed.
810 * @param[in,out] exts Extension instances to add to.
811 *
812 * @return LY_ERR values
813 */
814static LY_ERR
815yin_parse_belongs_to(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
816 struct lysp_submodule *submod, struct lysp_ext_instance **exts)
817{
818 struct yin_subelement subelems[2] = {
819 {YANG_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
820 {YANG_CUSTOM, NULL, 0}
821 };
822 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &submod->belongsto, Y_IDENTIF_ARG, YANG_BELONGS_TO));
823
824 return yin_parse_content(ctx, subelems, 2, data, YANG_BELONGS_TO, NULL, exts);
825}
826
David Sedlák5545f5d2019-07-11 11:55:16 +0200827/**
David Sedlákc1771b12019-07-10 15:55:46 +0200828 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
David Sedlákb4e44562019-07-04 15:42:12 +0200829 * text element as child
830 *
David Sedlákda8ffa32019-07-08 14:17:10 +0200831 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200832 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákcf5569a2019-07-11 13:31:34 +0200833 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlákc1771b12019-07-10 15:55:46 +0200834 * @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 +0200835 * @param[out] value Where the content of meta element should be stored.
David Sedlákbba38e52019-07-09 15:20:01 +0200836 * @param[in,out] exts Extension instance to add to.
David Sedlákb4e44562019-07-04 15:42:12 +0200837 *
838 * @return LY_ERR values.
839 */
840static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200841yin_parse_meta_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
842 enum yang_keyword elem_type, const char **value, struct lysp_ext_instance **exts)
David Sedlákb4e44562019-07-04 15:42:12 +0200843{
844 assert(elem_type == YANG_ORGANIZATION || elem_type == YANG_CONTACT || elem_type == YANG_DESCRIPTION || elem_type == YANG_REFERENCE);
845
David Sedlák968ac342019-07-11 15:17:59 +0200846 struct yin_subelement subelems[2] = {
847 {YANG_CUSTOM, NULL, 0},
848 {YIN_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
849 };
David Sedlákdf2a9732019-08-07 13:23:16 +0200850 /* check attributes */
851 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 +0200852
David Sedlákdf2a9732019-08-07 13:23:16 +0200853 /* parse content */
David Sedlákda8ffa32019-07-08 14:17:10 +0200854 return yin_parse_content(ctx, subelems, 2, data, elem_type, NULL, exts);
David Sedlákb4e44562019-07-04 15:42:12 +0200855}
856
857/**
David Sedlákc1771b12019-07-10 15:55:46 +0200858 * @brief Parse error-message element.
859 *
860 * @param[in,out] ctx Yin parser context for logging and to store current state.
David Sedlákdf2a9732019-08-07 13:23:16 +0200861 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
David Sedlákc1771b12019-07-10 15:55:46 +0200862 * @param[in,out] data Data to read from.
863 * @param[out] value Where the content of error-message element should be stored.
864 * @param[in,out] exts Extension instance to add to.
865 *
866 * @return LY_ERR values.
867 */
868static LY_ERR
David Sedlákdf2a9732019-08-07 13:23:16 +0200869yin_parse_err_msg_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
870 const char **value, struct lysp_ext_instance **exts)
David Sedlákc1771b12019-07-10 15:55:46 +0200871{
David Sedlák968ac342019-07-11 15:17:59 +0200872 struct yin_subelement subelems[2] = {
873 {YANG_CUSTOM, NULL, 0},
874 {YIN_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
875 };
David Sedlákc1771b12019-07-10 15:55:46 +0200876
David Sedlákdf2a9732019-08-07 13:23:16 +0200877 /* check attributes */
878 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, YANG_ERROR_MESSAGE));
879
David Sedlákc1771b12019-07-10 15:55:46 +0200880 return yin_parse_content(ctx, subelems, 2, data, YANG_ERROR_MESSAGE, NULL, exts);
881}
882
883/**
David Sedlák374d2b32019-07-17 15:06:55 +0200884 * @brief parse type element.
885 *
886 * @brief Parse position or value element.
887 *
888 * @param[in,out] ctx YIN parser context for logging and to store current state.
889 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
890 * @param[in,out] data Data to read from, always moved to currently handled character.
891 * @param[in,out] type Type to wrote to.
892 * @param[in,out] exts Extension instance to add to.
893 *
894 * @return LY_ERR values.
895 */
896static LY_ERR
897yin_parse_type(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_type *type)
898{
899 struct yin_subelement subelems[11] = {
900 {YANG_BASE, type, 0},
901 {YANG_BIT, type, 0},
902 {YANG_ENUM, type, 0},
903 {YANG_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
904 {YANG_LENGTH, type, YIN_SUBELEM_UNIQUE},
905 {YANG_PATH, type, YIN_SUBELEM_UNIQUE},
906 {YANG_PATTERN, type, 0},
907 {YANG_RANGE, type, YIN_SUBELEM_UNIQUE},
908 {YANG_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
909 {YANG_TYPE, type},
910 {YANG_CUSTOM, NULL, 0},
911 };
912 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, YANG_TYPE));
913 return yin_parse_content(ctx, subelems, 11, data, YANG_TYPE, NULL, &type->exts);
914}
915
David Sedlák1af868e2019-07-17 17:03:14 +0200916/**
917 * @brief Parse max-elements element.
918 *
919 * @param[in,out] ctx YIN parser context for logging and to store current state.
920 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
921 * @param[in,out] data Data to read from, always moved to currently handled character.
922 * @param[in,out] max Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200923 * @param[in] flags Flags to write to.
David Sedlák1af868e2019-07-17 17:03:14 +0200924 * @param[in,out] exts Extension instances to add to.
925 *
926 * @return LY_ERR values.
927 */
928static LY_ERR
929yin_parse_maxelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *max,
930 uint16_t *flags, struct lysp_ext_instance **exts)
931{
932 const char *temp_val = NULL;
933 char *ptr;
934 unsigned long int num;
935 struct yin_subelement subelems[1] = {
936 {YANG_CUSTOM, NULL, 0},
937 };
David Sedlák374d2b32019-07-17 15:06:55 +0200938
David Sedlák1af868e2019-07-17 17:03:14 +0200939 *flags |= LYS_SET_MAX;
940 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MAX_ELEMENTS));
941 if (!temp_val || temp_val[0] == '\0' || temp_val[0] == '0' || (temp_val[0] != 'u' && !isdigit(temp_val[0]))) {
942 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
943 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
944 return LY_EVALID;
945 }
946
947 if (strcmp(temp_val, "unbounded")) {
948 errno = 0;
949 num = strtoul(temp_val, &ptr, 10);
950 if (*ptr != '\0') {
951 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "max-elements");
952 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
953 return LY_EVALID;
954 }
955 if ((errno == ERANGE) || (num > UINT32_MAX)) {
956 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "max-elements");
957 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
958 return LY_EVALID;
959 }
960 *max = num;
961 }
962 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
963 return yin_parse_content(ctx, subelems, 1, data, YANG_MAX_ELEMENTS, NULL, exts);
964}
David Sedlák374d2b32019-07-17 15:06:55 +0200965
966/**
David Sedlák09e18c92019-07-18 11:17:11 +0200967 * @brief Parse max-elements element.
968 *
969 * @param[in,out] ctx YIN parser context for logging and to store current state.
970 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
971 * @param[in,out] data Data to read from, always moved to currently handled character.
972 * @param[in,out] min Value to write to.
David Sedláka2dad212019-07-18 12:45:19 +0200973 * @param[in] flags Flags to write to.
David Sedlák09e18c92019-07-18 11:17:11 +0200974 * @param[in,out] exts Extension instances to add to.
975 *
976 * @return LY_ERR values.
977 */
978static LY_ERR
979yin_parse_minelements(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint32_t *min,
980 uint16_t *flags, struct lysp_ext_instance **exts)
981{
982 const char *temp_val = NULL;
983 char *ptr;
984 unsigned long int num;
985 struct yin_subelement subelems[1] = {
986 {YANG_CUSTOM, NULL, 0},
987 };
988
989 *flags |= LYS_SET_MIN;
David Sedláka2dad212019-07-18 12:45:19 +0200990 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 +0200991
992 if (!temp_val || temp_val[0] == '\0' || (temp_val[0] == '0' && temp_val[1] != '\0')) {
993 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
994 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
995 return LY_EVALID;
996 }
997
998 errno = 0;
999 num = strtoul(temp_val, &ptr, 10);
1000 if (ptr[0] != 0) {
1001 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "min-elements");
1002 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1003 return LY_EVALID;
1004 }
1005 if (errno == ERANGE || num > UINT32_MAX) {
1006 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_OOB, strlen(temp_val), temp_val, "min-elements");
1007 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1008 return LY_EVALID;
1009 }
1010 *min = num;
1011 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
David Sedláka2dad212019-07-18 12:45:19 +02001012 return yin_parse_content(ctx, subelems, 1, data, YANG_MIN_ELEMENTS, NULL, exts);
David Sedlák09e18c92019-07-18 11:17:11 +02001013}
1014
David Sedláka2dad212019-07-18 12:45:19 +02001015/**
1016 * @brief Parse min-elements or max-elements element.
1017 *
1018 * @param[in,out] ctx YIN parser context for logging and to store current state.
1019 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1020 * @param[in,out] data Data to read from, always moved to currently handled character.
1021 * @param[in] parent Identification of parent element.
1022 * @param[in] current Identification of current element.
1023 * @param[in] dest Where the parsed value and flags should be stored.
1024 *
1025 * @return LY_ERR values.
1026 */
David Sedlák09e18c92019-07-18 11:17:11 +02001027static LY_ERR
1028yin_parse_minmax(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1029 enum yang_keyword parent, enum yang_keyword current, void *dest)
1030{
1031 assert(current == YANG_MAX_ELEMENTS || current == YANG_MIN_ELEMENTS);
David Sedlák4ffcec82019-07-25 15:10:21 +02001032 assert(parent == YANG_LEAF_LIST || parent == YANG_REFINE || parent == YANG_LIST || parent == YANG_DEVIATE);
David Sedlák09e18c92019-07-18 11:17:11 +02001033 uint32_t *lim;
1034 uint16_t *flags;
1035 struct lysp_ext_instance **exts;
1036
1037 if (parent == YANG_LEAF_LIST) {
1038 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1039 flags = &((struct lysp_node_leaflist *)dest)->flags;
1040 exts = &((struct lysp_node_leaflist *)dest)->exts;
1041 } else if (parent == YANG_REFINE) {
1042 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1043 flags = &((struct lysp_refine *)dest)->flags;
1044 exts = &((struct lysp_refine *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001045 } else if (parent == YANG_LIST) {
David Sedlák09e18c92019-07-18 11:17:11 +02001046 lim = (current == YANG_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1047 flags = &((struct lysp_node_list *)dest)->flags;
1048 exts = &((struct lysp_node_list *)dest)->exts;
David Sedlák4ffcec82019-07-25 15:10:21 +02001049 } else {
1050 lim = ((struct minmax_dev_meta *)dest)->lim;
1051 flags = ((struct minmax_dev_meta *)dest)->flags;
1052 exts = ((struct minmax_dev_meta *)dest)->exts;
David Sedlák09e18c92019-07-18 11:17:11 +02001053 }
1054
1055 if (current == YANG_MAX_ELEMENTS) {
1056 LY_CHECK_RET(yin_parse_maxelements(ctx, attrs, data, lim, flags, exts));
1057 } else {
1058 LY_CHECK_RET(yin_parse_minelements(ctx, attrs, data, lim, flags, exts));
1059 }
1060
1061 return LY_SUCCESS;
1062}
1063
1064/**
David Sedláka2dad212019-07-18 12:45:19 +02001065 * @brief Parser ordered-by element.
1066 *
1067 * @param[in,out] ctx YIN parser context for logging and to store current state.
1068 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1069 * @param[in,out] data Data to read from, always moved to currently handled character.
1070 * @param[out] flags Flags to write to.
1071 * @param[in,out] exts Extension instance to add to.
1072 *
1073 * @return LY_ERR values.
1074 */
1075static LY_ERR
1076yin_parse_orderedby(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1077 uint16_t *flags, struct lysp_ext_instance **exts)
1078{
1079 const char *temp_val;
1080 struct yin_subelement subelems[1] = {
1081 {YANG_CUSTOM, NULL, 0},
1082 };
1083
1084 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_ORDERED_BY));
1085 if (strcmp(temp_val, "system") == 0) {
1086 *flags |= LYS_ORDBY_SYSTEM;
1087 } else if (strcmp(temp_val, "user") == 0) {
1088 *flags |= LYS_ORDBY_USER;
1089 } else {
1090 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "ordered-by");
1091 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1092 return LY_EVALID;
1093 }
1094 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1095
1096 return yin_parse_content(ctx, subelems, 1, data, YANG_ORDERED_BY, NULL, exts);
1097}
1098
1099/**
David Sedlák8a83bbb2019-07-18 14:46:00 +02001100 * @brief parse any-data or any-xml element.
1101 *
1102 * @param[in,out] ctx YIN parser context for logging and to store current state.
1103 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1104 * @param[in,out] data Data to read from, always moved to currently handled character.
1105 * @param[in] any_kw Identification of current element, can be set to YANG_ANY_DATA or YANG_ANY_XML
David Sedlák05404f62019-07-24 14:11:53 +02001106 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák8a83bbb2019-07-18 14:46:00 +02001107 *
1108 * @return LY_ERR values.
1109 */
1110static LY_ERR
1111yin_parse_any(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1112 enum yang_keyword any_kw, struct tree_node_meta *node_meta)
1113{
David Sedlák8a83bbb2019-07-18 14:46:00 +02001114 struct lysp_node_anydata *any;
1115
David Sedlák8d552d62019-08-06 15:29:05 +02001116 /* create new sibling */
1117 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, any, next);
David Sedlák8a83bbb2019-07-18 14:46:00 +02001118 any->nodetype = (any_kw == YANG_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1119 any->parent = node_meta->parent;
1120
David Sedlák8a83bbb2019-07-18 14:46:00 +02001121 /* parser argument */
David Sedlák203ca3a2019-07-18 15:26:25 +02001122 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 +02001123
1124 struct yin_subelement subelems[9] = {
1125 {YANG_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1126 {YANG_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1127 {YANG_IF_FEATURE, &any->iffeatures, 0},
1128 {YANG_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1129 {YANG_MUST, &any->musts, 0},
1130 {YANG_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1131 {YANG_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1132 {YANG_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1133 {YANG_CUSTOM, NULL, 0},
1134 };
1135 return yin_parse_content(ctx, subelems, 9, data, any_kw, NULL, &any->exts);
1136}
1137
1138/**
David Sedlák203ca3a2019-07-18 15:26:25 +02001139 * @brief parse leaf element.
1140 *
1141 * @param[in,out] ctx YIN parser context for logging and to store current state.
1142 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1143 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001144 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák203ca3a2019-07-18 15:26:25 +02001145 *
1146 * @return LY_ERR values.
1147 */
1148static LY_ERR
1149yin_parse_leaf(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1150 struct tree_node_meta *node_meta)
1151{
David Sedlák203ca3a2019-07-18 15:26:25 +02001152 struct lysp_node_leaf *leaf;
1153
David Sedlák8d552d62019-08-06 15:29:05 +02001154 /* create structure new leaf */
1155 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, leaf, next);
David Sedlák203ca3a2019-07-18 15:26:25 +02001156 leaf->nodetype = LYS_LEAF;
1157 leaf->parent = node_meta->parent;
1158
David Sedlák203ca3a2019-07-18 15:26:25 +02001159 /* parser argument */
1160 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, YANG_LEAF));
1161
1162 /* parse content */
1163 struct yin_subelement subelems[12] = {
1164 {YANG_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1165 {YANG_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1166 {YANG_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1167 {YANG_IF_FEATURE, &leaf->iffeatures, 0},
1168 {YANG_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1169 {YANG_MUST, &leaf->musts, 0},
1170 {YANG_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1171 {YANG_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1172 {YANG_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1173 {YANG_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1174 {YANG_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1175 {YANG_CUSTOM, NULL, 0},
David Sedlák05404f62019-07-24 14:11:53 +02001176 };
David Sedlák203ca3a2019-07-18 15:26:25 +02001177 return yin_parse_content(ctx, subelems, 12, data, YANG_LEAF, NULL, &leaf->exts);
1178}
1179
1180/**
David Sedlákc3da3ef2019-07-19 12:56:08 +02001181 * @brief Parse leaf-list element.
1182 *
1183 * @param[in,out] ctx YIN parser context for logging and to store current state.
1184 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1185 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001186 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákc3da3ef2019-07-19 12:56:08 +02001187 *
1188 * @return LY_ERR values.
1189 */
1190static LY_ERR
1191yin_parse_leaflist(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1192 struct tree_node_meta *node_meta)
1193{
David Sedlákc3da3ef2019-07-19 12:56:08 +02001194 struct lysp_node_leaflist *llist;
David Sedlákc3da3ef2019-07-19 12:56:08 +02001195
David Sedlák8d552d62019-08-06 15:29:05 +02001196 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, llist, next);
1197
David Sedlákc3da3ef2019-07-19 12:56:08 +02001198 llist->nodetype = LYS_LEAFLIST;
1199 llist->parent = node_meta->parent;
1200
David Sedlákc3da3ef2019-07-19 12:56:08 +02001201 /* parse argument */
1202 yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, YANG_LEAF_LIST);
1203
1204 /* parse content */
1205 struct yin_subelement subelems[14] = {
1206 {YANG_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1207 {YANG_DEFAULT, &llist->dflts, 0},
1208 {YANG_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1209 {YANG_IF_FEATURE, &llist->iffeatures, 0},
1210 {YANG_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1211 {YANG_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1212 {YANG_MUST, &llist->musts, 0},
1213 {YANG_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1214 {YANG_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1215 {YANG_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1216 {YANG_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1217 {YANG_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1218 {YANG_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1219 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001220 };
David Sedlákc3da3ef2019-07-19 12:56:08 +02001221 LY_CHECK_RET(yin_parse_content(ctx, subelems, 14, data, YANG_LEAF_LIST, NULL, &llist->exts));
1222
1223 /* invalid combination of subelements */
1224 if ((llist->min) && (llist->dflts)) {
1225 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB, "min-elements", "default", "leaf-list");
1226 return LY_EVALID;
1227 }
1228 if (llist->max && llist->min > llist->max) {
1229 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1230 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1231 llist->min, llist->max);
1232 return LY_EVALID;
1233 }
1234
1235 return LY_SUCCESS;
1236}
1237
1238/**
David Sedlák04e17b22019-07-19 15:29:48 +02001239 * @brief Parse typedef element.
1240 *
1241 * @param[in,out] ctx YIN parser context for logging and to store current state.
1242 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1243 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001244 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
David Sedlák04e17b22019-07-19 15:29:48 +02001245 *
1246 * @return LY_ERR values.
1247 */
1248static LY_ERR
1249yin_parse_typedef(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1250 struct typedef_meta *typedef_meta)
1251{
1252 struct lysp_tpdf *tpdf;
1253 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *typedef_meta->typedefs, tpdf, LY_EMEM);
1254
1255 /* parse argument */
1256 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, YANG_TYPEDEF));
1257
1258 /* parse content */
1259 struct yin_subelement subelems[7] = {
1260 {YANG_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1261 {YANG_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1262 {YANG_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1263 {YANG_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1264 {YANG_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1265 {YANG_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1266 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001267 };
David Sedlák04e17b22019-07-19 15:29:48 +02001268 LY_CHECK_RET(yin_parse_content(ctx, subelems, 7, data, YANG_TYPEDEF, NULL, &tpdf->exts));
1269
1270 /* store data for collision check */
1271 if (typedef_meta->parent && !(typedef_meta->parent->nodetype & (LYS_GROUPING | LYS_ACTION | LYS_INOUT | LYS_NOTIF))) {
1272 ly_set_add(&ctx->tpdfs_nodes, typedef_meta->parent, 0);
1273 }
1274
1275 return LY_SUCCESS;
1276}
1277
1278/**
David Sedlákd2d676a2019-07-22 11:28:19 +02001279 * @brief Parse refine element.
1280 *
1281 * @param[in,out] ctx YIN parser context for logging and to store current state.
1282 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1283 * @param[in,out] data Data to read from, always moved to currently handled character.
1284 * @param[in,out] refines Refines to add to.
1285 *
1286 * @return LY_ERR values.
1287 */
1288static LY_ERR
1289yin_parse_refine(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1290 struct lysp_refine **refines)
1291{
1292 struct lysp_refine *rf;
1293
1294 /* allocate new refine */
1295 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *refines, rf, LY_EMEM);
1296
1297 /* parse attribute */
1298 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, YANG_REFINE));
1299 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(rf->nodeid), "refine");
1300
1301 /* parse content */
1302 struct yin_subelement subelems[11] = {
1303 {YANG_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1304 {YANG_DEFAULT, &rf->dflts, 0},
1305 {YANG_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1306 {YANG_IF_FEATURE, &rf->iffeatures, 0},
1307 {YANG_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1308 {YANG_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1309 {YANG_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1310 {YANG_MUST, &rf->musts, 0},
1311 {YANG_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1312 {YANG_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1313 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001314 };
David Sedlákd2d676a2019-07-22 11:28:19 +02001315 return yin_parse_content(ctx, subelems, 11, data, YANG_REFINE, NULL, &rf->exts);
1316}
1317
1318/**
David Sedlák0d6de5a2019-07-22 13:25:44 +02001319 * @brief Parse uses element.
1320 *
1321 * @param[in,out] ctx YIN parser context for logging and to store current state.
1322 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1323 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001324 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák0d6de5a2019-07-22 13:25:44 +02001325 *
1326 * @return LY_ERR values.
1327 */
1328static LY_ERR
1329yin_parse_uses(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1330 struct tree_node_meta *node_meta)
1331{
David Sedlák0d6de5a2019-07-22 13:25:44 +02001332 struct lysp_node_uses *uses;
1333
David Sedlák8d552d62019-08-06 15:29:05 +02001334 /* create new uses */
1335 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, uses, next);
David Sedlák0d6de5a2019-07-22 13:25:44 +02001336 uses->nodetype = LYS_USES;
1337 uses->parent = node_meta->parent;
1338
David Sedlák0d6de5a2019-07-22 13:25:44 +02001339 /* parse argument */
1340 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, YANG_USES));
1341
1342 /* parse content */
1343 struct augment_meta augments = {(struct lysp_node *)uses, &uses->augments};
1344 struct yin_subelement subelems[8] = {
1345 {YANG_AUGMENT, &augments, 0},
1346 {YANG_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1347 {YANG_IF_FEATURE, &uses->iffeatures, 0},
1348 {YANG_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1349 {YANG_REFINE, &uses->refines, 0},
1350 {YANG_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1351 {YANG_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1352 {YANG_CUSTOM, NULL, 0},
David Sedlákaa854b02019-07-22 14:17:10 +02001353 };
David Sedlák0d6de5a2019-07-22 13:25:44 +02001354 LY_CHECK_RET(yin_parse_content(ctx, subelems, 8, data, YANG_USES, NULL, &uses->exts));
1355 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, uses->augments, NULL, NULL));
1356
1357 return LY_SUCCESS;
1358}
1359
1360/**
David Sedlákaa854b02019-07-22 14:17:10 +02001361 * @brief Parse revision element.
1362 *
1363 * @param[in,out] ctx YIN parser context for logging and to store current state.
1364 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1365 * @param[in,out] data Data to read from, always moved to currently handled character.
1366 * @param[in,out] revs Parsed revisions to add to.
1367 *
1368 * @return LY_ERR values.
1369 */
1370static LY_ERR
1371yin_parse_revision(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1372 struct lysp_revision **revs)
1373{
1374 struct lysp_revision *rev;
1375 const char *temp_date = NULL;
1376
1377 /* allocate new reivison */
1378 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *revs, rev, LY_EMEM);
1379
1380 /* parse argument */
1381 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_date, Y_STR_ARG, YANG_REVISION));
1382 /* check value */
1383 if (lysp_check_date((struct lys_parser_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1384 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1385 return LY_EVALID;
1386 }
1387 strcpy(rev->date, temp_date);
1388 FREE_STRING(ctx->xml_ctx.ctx, temp_date);
1389
1390 /* parse content */
1391 struct yin_subelement subelems[3] = {
1392 {YANG_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1393 {YANG_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1394 {YANG_CUSTOM, NULL, 0},
1395 };
1396 return yin_parse_content(ctx, subelems, 3, data, YANG_REVISION, NULL, &rev->exts);
1397}
1398
David Sedlák5e13dea2019-07-22 16:06:45 +02001399/**
1400 * @brief Parse include element.
1401 *
1402 * @param[in,out] ctx YIN parser context for logging and to store current state.
1403 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1404 * @param[in,out] data Data to read from, always moved to currently handled character.
1405 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1406 *
1407 * @return LY_ERR values.
1408 */
David Sedlák0c2bab92019-07-22 15:33:19 +02001409static LY_ERR
1410yin_parse_include(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1411 struct include_meta *inc_meta)
1412{
1413 struct lysp_include *inc;
1414
1415 /* allocate new include */
1416 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *inc_meta->includes, inc, LY_EMEM);
1417
1418 /* parse argument */
1419 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, YANG_INCLUDE));
1420
1421 /* submodules share the namespace with the module names, so there must not be
1422 * a module of the same name in the context, no need for revision matching */
1423 if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xml_ctx.ctx, inc->name)) {
1424 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YANG,
1425 "Name collision between module and submodule of name \"%s\".", inc->name);
1426 return LY_EVALID;
1427 }
1428
1429 /* parse content */
1430 struct yin_subelement subelems[4] = {
1431 {YANG_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1432 {YANG_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1433 {YANG_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1434 {YANG_CUSTOM, NULL, 0},
1435 };
1436 return yin_parse_content(ctx, subelems, 4, data, YANG_INCLUDE, NULL, &inc->exts);
1437}
1438
David Sedlákaa854b02019-07-22 14:17:10 +02001439/**
David Sedlákdfbbb442019-08-06 16:33:21 +02001440 * @brief Parse revision date element.
1441 *
1442 * @param[in,out] ctx Yin parser context for logging and to store current state.
1443 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of revision-date element.
1444 * @param[in,out] data Data to read from, always moved to currently handled character.
1445 * @param[in,out] rev Array to store the parsed value in.
1446 * @param[in,out] exts Extension instances to add to.
1447 *
1448 * @return LY_ERR values.
1449 */
1450static LY_ERR
1451yin_parse_revision_date(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, char *rev,
1452 struct lysp_ext_instance **exts)
1453{
1454 const char *temp_rev;
1455 struct yin_subelement subelems[1] = {
1456 {YANG_CUSTOM, NULL, 0}
1457 };
1458
1459 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, YANG_REVISION_DATE));
1460 LY_CHECK_ERR_RET(lysp_check_date((struct lys_parser_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1461 FREE_STRING(ctx->xml_ctx.ctx, temp_rev), LY_EVALID);
1462
1463 strcpy(rev, temp_rev);
1464 FREE_STRING(ctx->xml_ctx.ctx, temp_rev);
1465
1466 return yin_parse_content(ctx, subelems, 1, data, YANG_REVISION_DATE, NULL, exts);
1467}
1468
1469/**
1470 * @brief Parse config element.
1471 *
1472 * @param[in] ctx Yin parser context for logging and to store current state.
1473 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1474 * @param[in,out] data Data to read from, always moved to currently handled character.
1475 * @param[in,out] flags Flags to add to.
1476 * @param[in,out] exts Extension instances to add to.
1477 *
1478 * @return LY_ERR values.
1479 */
1480static LY_ERR
1481yin_parse_config(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1482 struct lysp_ext_instance **exts)
1483{
1484 const char *temp_val = NULL;
1485 struct yin_subelement subelems[1] = {
1486 {YANG_CUSTOM, NULL, 0}
1487 };
1488
1489 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_CONFIG));
1490 if (strcmp(temp_val, "true") == 0) {
1491 *flags |= LYS_CONFIG_W;
1492 } else if (strcmp(temp_val, "false") == 0) {
1493 *flags |= LYS_CONFIG_R;
1494 } else {
1495 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "config");
1496 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1497 return LY_EVALID;
1498 }
1499 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1500
1501 return yin_parse_content(ctx, subelems, 1, data, YANG_CONFIG, NULL, exts);
1502}
1503
1504/**
1505 * @brief Parse yang-version element.
1506 *
1507 * @param[in,out] ctx Yin parser context for logging and to store current state.
1508 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yang-version element.
1509 * @param[in] data Data to read from, always moved to currently handled character.
1510 * @param[out] version Storage for the parsed information.
1511 * @param[in,out] exts Extension instance to add to.
1512 *
1513 * @return LY_ERR values.
1514 */
1515static LY_ERR
1516yin_parse_yangversion(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint8_t *version,
1517 struct lysp_ext_instance **exts)
1518{
1519 const char *temp_version = NULL;
1520 struct yin_subelement subelems[1] = {
1521 {YANG_CUSTOM, NULL, 0}
1522 };
1523
1524 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, YANG_YANG_VERSION));
1525 if (strcmp(temp_version, "1.0") == 0) {
1526 *version = LYS_VERSION_1_0;
1527 } else if (strcmp(temp_version, "1.1") == 0) {
1528 *version = LYS_VERSION_1_1;
1529 } else {
1530 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_version, "yang-version");
1531 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1532 return LY_EVALID;
1533 }
1534 FREE_STRING(ctx->xml_ctx.ctx, temp_version);
1535 ctx->mod_version = *version;
1536
1537 return yin_parse_content(ctx, subelems, 1, data, YANG_YANG_VERSION, NULL, exts);
1538}
1539
1540/**
1541 * @brief Parse import element.
1542 *
1543 * @param[in,out] ctx Yin parser context for logging and to store current state.
1544 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of import element.
1545 * @param[in,out] data Data to read from, always moved to currently handled character.
1546 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1547 *
1548 * @return LY_ERR values.
1549 */
1550static LY_ERR
1551yin_parse_import(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct import_meta *imp_meta)
1552{
1553 struct lysp_import *imp;
1554 /* allocate new element in sized array for import */
1555 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *imp_meta->imports, imp, LY_EMEM);
1556
1557 struct yin_subelement subelems[5] = {
1558 {YANG_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
1559 {YANG_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1560 {YANG_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
1561 {YANG_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
1562 {YANG_CUSTOM, NULL, 0}
1563 };
1564
1565 /* parse import attributes */
1566 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, YANG_IMPORT));
1567 LY_CHECK_RET(yin_parse_content(ctx, subelems, 5, data, YANG_IMPORT, NULL, &imp->exts));
1568 /* check prefix validity */
1569 LY_CHECK_RET(lysp_check_prefix((struct lys_parser_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
1570
1571 return LY_SUCCESS;
1572}
1573
1574/**
1575 * @brief Parse mandatory element.
1576 *
1577 * @param[in,out] ctx Yin parser context for logging and to store current state.
1578 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1579 * @param[in,out] data Data to read from, always moved to currently handled character.
1580 * @param[in,out] flags Flags to add to.
1581 * @param[in,out] exts Extension instances to add to.
1582 *
1583 * @return LY_ERR values.
1584 */
1585static LY_ERR
1586yin_parse_mandatory(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1587 struct lysp_ext_instance **exts)
1588{
1589 const char *temp_val = NULL;
1590 struct yin_subelement subelems[1] = {
1591 {YANG_CUSTOM, NULL, 0}
1592 };
1593
1594 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_MANDATORY));
1595 if (strcmp(temp_val, "true") == 0) {
1596 *flags |= LYS_MAND_TRUE;
1597 } else if (strcmp(temp_val, "false") == 0) {
1598 *flags |= LYS_MAND_FALSE;
1599 } else {
1600 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "mandatory");
1601 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1602 return LY_EVALID;
1603 }
1604 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1605
1606 return yin_parse_content(ctx, subelems, 1, data, YANG_MANDATORY, NULL, exts);
1607}
1608
1609/**
1610 * @brief Parse status element.
1611 *
1612 * @param[in,out] ctx Yin parser context for logging and to store current state.
1613 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of status element.
1614 * @param[in,out] data Data to read from, always moved to currently handled character.
1615 * @param[in,out] flags Flags to add to.
1616 * @param[in,out] exts Extension instances to add to.
1617 *
1618 * @return LY_ERR values.
1619 */
1620static LY_ERR
1621yin_parse_status(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, uint16_t *flags,
1622 struct lysp_ext_instance **exts)
1623{
1624 const char *value = NULL;
1625 struct yin_subelement subelems[1] = {
1626 {YANG_CUSTOM, NULL, 0}
1627 };
1628
1629 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &value, Y_STR_ARG, YANG_STATUS));
1630 if (strcmp(value, "current") == 0) {
1631 *flags |= LYS_STATUS_CURR;
1632 } else if (strcmp(value, "deprecated") == 0) {
1633 *flags |= LYS_STATUS_DEPRC;
1634 } else if (strcmp(value, "obsolete") == 0) {
1635 *flags |= LYS_STATUS_OBSLT;
1636 } else {
1637 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, value, "status");
1638 FREE_STRING(ctx->xml_ctx.ctx, value);
1639 return LY_EVALID;
1640 }
1641 FREE_STRING(ctx->xml_ctx.ctx, value);
1642
1643 return yin_parse_content(ctx, subelems, 1, data, YANG_STATUS, NULL, exts);
1644}
1645
1646/**
1647 * @brief Parse when element.
1648 *
1649 * @param[in,out] ctx Yin parser context for logging and to store current state.
1650 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of when element.
1651 * @param[in,out] data Data to read from, always moved to currently handled character.
1652 * @param[out] when_p When pointer to parse to.
1653 */
1654static LY_ERR
1655yin_parse_when(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_when **when_p)
1656{
1657 struct lysp_when *when;
1658 when = calloc(1, sizeof *when);
1659 LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
1660 yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, YANG_WHEN);
1661 *when_p = when;
1662 struct yin_subelement subelems[3] = {
1663 {YANG_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
1664 {YANG_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
1665 {YANG_CUSTOM, NULL, 0}
1666 };
1667
1668 return yin_parse_content(ctx, subelems, 3, data, YANG_WHEN, NULL, &when->exts);
1669}
1670
1671/**
1672 * @brief Parse yin-elemenet element.
1673 *
1674 * @param[in,out] ctx Yin parser context for logging and to store current state.
1675 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of yin-element element.
1676 * @param[in,out] data Data to read from, always moved to currently handled position.
1677 * @param[in,out] flags Flags to add to.
1678 * @prama[in,out] exts Extension instance to add to.
1679 *
1680 * @return LY_ERR values.
1681 */
1682static LY_ERR
1683yin_parse_yin_element_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1684 uint16_t *flags, struct lysp_ext_instance **exts)
1685{
1686 const char *temp_val = NULL;
1687 struct yin_subelement subelems[1] = {
1688 {YANG_CUSTOM, NULL, 0}
1689 };
1690
1691 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_YIN_ELEMENT));
1692 if (strcmp(temp_val, "true") == 0) {
1693 *flags |= LYS_YINELEM_TRUE;
1694 } else if (strcmp(temp_val, "false") == 0) {
1695 *flags |= LYS_YINELEM_FALSE;
1696 } else {
1697 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "yin-element");
1698 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1699 return LY_EVALID;
1700 }
1701 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
1702
1703 return yin_parse_content(ctx, subelems, 1, data, YANG_YIN_ELEMENT, NULL, exts);
1704}
1705
1706/**
1707 * @brief Parse argument element.
1708 *
1709 * @param[in,out] xml_ctx Xml context.
1710 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of argument element.
1711 * @param[in,out] data Data to read from, always moved to currently handled character.
1712 * @param[in,out] arg_meta Meta information about destionation af prased data.
1713 * @param[in,out] exts Extension instance to add to.
1714 *
1715 * @return LY_ERR values.
1716 */
1717static LY_ERR
1718yin_parse_argument_element(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1719 struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
1720{
1721 struct yin_subelement subelems[2] = {
1722 {YANG_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
1723 {YANG_CUSTOM, NULL, 0}
1724 };
1725
1726 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, YANG_ARGUMENT));
1727
1728 return yin_parse_content(ctx, subelems, 2, data, YANG_ARGUMENT, NULL, exts);
1729}
1730
1731/**
1732 * @brief Parse the extension statement.
1733 *
1734 * @param[in,out] ctx Yin parser context for logging and to store current state.
1735 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension element.
1736 * @param[in,out] data Data to read from.
1737 * @param[in,out] extensions Extensions to add to.
1738 *
1739 * @return LY_ERR values.
1740 */
1741static LY_ERR
1742yin_parse_extension(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, struct lysp_ext **extensions)
1743{
1744 struct lysp_ext *ex;
1745 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *extensions, ex, LY_EMEM);
1746 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, YANG_EXTENSION));
1747
1748 struct yin_argument_meta arg_info = {&ex->flags, &ex->argument};
1749 struct yin_subelement subelems[5] = {
1750 {YANG_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
1751 {YANG_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
1752 {YANG_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
1753 {YANG_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
1754 {YANG_CUSTOM, NULL, 0}
1755 };
1756
1757 return yin_parse_content(ctx, subelems, 5, data, YANG_EXTENSION, NULL, &ex->exts);
1758}
1759
1760/**
David Sedlák5e13dea2019-07-22 16:06:45 +02001761 * @brief Parse feature element.
1762 *
1763 * @param[in,out] ctx YIN parser context for logging and to store current state.
1764 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1765 * @param[in,out] data Data to read from, always moved to currently handled character.
1766 * @param[in,out] features Features to add to.
1767 *
1768 * @return LY_ERR values.
1769 */
1770static LY_ERR
1771yin_parse_feature(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1772 struct lysp_feature **features)
1773{
1774 struct lysp_feature *feat;
1775
1776 /* allocate new feature */
1777 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *features, feat, LY_EMEM);
1778
1779 /* parse argument */
1780 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, YANG_FEATURE));
1781
1782 /* parse content */
1783 struct yin_subelement subelems[5] = {
1784 {YANG_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
1785 {YANG_IF_FEATURE, &feat->iffeatures, 0},
1786 {YANG_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
1787 {YANG_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
1788 {YANG_CUSTOM, NULL, 0},
1789 };
1790 return yin_parse_content(ctx, subelems, 5, data, YANG_FEATURE, NULL, &feat->exts);
1791}
1792
1793/**
David Sedlák28794f22019-07-22 16:45:00 +02001794 * @brief Parse identity element.
1795 *
1796 * @param[in,out] ctx YIN parser context for logging and to store current state.
1797 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1798 * @param[in,out] data Data to read from, always moved to currently handled character.
1799 * @param[in,out] identities Identities to add to.
1800 *
1801 * @return LY_ERR values.
1802 */
1803static LY_ERR
1804yin_parse_identity(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1805 struct lysp_ident **identities)
1806{
1807 struct lysp_ident *ident;
1808
1809 /* allocate new identity */
1810 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *identities, ident, LY_EMEM);
1811
1812 /* parse argument */
1813 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, YANG_IDENTITY));
1814
1815 /* parse content */
1816 struct yin_subelement subelems[6] = {
1817 {YANG_BASE, &ident->bases, 0},
1818 {YANG_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
1819 {YANG_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
1820 {YANG_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
1821 {YANG_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
1822 {YANG_CUSTOM, NULL, 0},
1823 };
1824 return yin_parse_content(ctx, subelems, 6, data, YANG_IDENTITY, NULL, &ident->exts);
1825}
1826
1827/**
David Sedlákaf536aa2019-07-23 13:42:23 +02001828 * @brief Parse list element.
1829 *
1830 * @param[in,out] ctx YIN parser context for logging and to store current state.
1831 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1832 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001833 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákaf536aa2019-07-23 13:42:23 +02001834 *
1835 * @return LY_ERR values.
1836 */
1837static LY_ERR
David Sedlákf111bcb2019-07-23 17:15:51 +02001838yin_parse_list(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1839 struct tree_node_meta *node_meta)
David Sedlákaf536aa2019-07-23 13:42:23 +02001840{
David Sedlákaf536aa2019-07-23 13:42:23 +02001841 struct lysp_node_list *list;
1842
David Sedlák8d552d62019-08-06 15:29:05 +02001843 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, list, next);
David Sedlákaf536aa2019-07-23 13:42:23 +02001844 list->nodetype = LYS_LIST;
1845 list->parent = node_meta->parent;
1846
David Sedlákaf536aa2019-07-23 13:42:23 +02001847 /* parse argument */
1848 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, YANG_LIST));
1849
1850 /* parse list content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001851 struct action_meta act_meta = {(struct lysp_node *)list, &list->actions};
David Sedlákaf536aa2019-07-23 13:42:23 +02001852 struct tree_node_meta new_node_meta = {(struct lysp_node *)list, &list->child};
1853 struct typedef_meta typedef_meta = {(struct lysp_node *)list, &list->typedefs};
David Sedlák031b9e72019-07-23 15:19:37 +02001854 struct notif_meta notif_meta = {(struct lysp_node *)list, &list->notifs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001855 struct grouping_meta gr_meta = {(struct lysp_node *)list, &list->groupings};
David Sedlákaf536aa2019-07-23 13:42:23 +02001856 struct yin_subelement subelems[25] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001857 {YANG_ACTION, &act_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001858 {YANG_ANYDATA, &new_node_meta, 0},
1859 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001860 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001861 {YANG_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE},
David Sedlákf111bcb2019-07-23 17:15:51 +02001862 {YANG_CONTAINER, &new_node_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001863 {YANG_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001864 {YANG_GROUPING, &gr_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001865 {YANG_IF_FEATURE, &list->iffeatures, 0},
1866 {YANG_KEY, &list->key, YIN_SUBELEM_UNIQUE},
1867 {YANG_LEAF, &new_node_meta, 0},
1868 {YANG_LEAF_LIST, &new_node_meta, 0},
1869 {YANG_LIST, &new_node_meta, 0},
1870 {YANG_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1871 {YANG_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE},
1872 {YANG_MUST, &list->musts, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001873 {YANG_NOTIFICATION, &notif_meta, 0},
David Sedlákaf536aa2019-07-23 13:42:23 +02001874 {YANG_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE},
1875 {YANG_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE},
1876 {YANG_STATUS, &list->flags, YIN_SUBELEM_UNIQUE},
1877 {YANG_TYPEDEF, &typedef_meta, 0},
1878 {YANG_UNIQUE, &list->uniques, 0},
1879 {YANG_USES, &new_node_meta, 0},
1880 {YANG_WHEN, &list->when, YIN_SUBELEM_UNIQUE},
1881 {YANG_CUSTOM, NULL, 0},
1882 };
1883 LY_CHECK_RET(yin_parse_content(ctx, subelems, 25, data, YANG_LIST, NULL, &list->exts));
1884
1885 /* finalize parent pointers to the reallocated items */
1886 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, list->groupings, NULL, list->actions, list->notifs));
1887
1888 if (list->max && list->min > list->max) {
1889 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SEMANTICS,
1890 "Invalid combination of min-elements and max-elements: min value %u is bigger than the max value %u.",
1891 list->min, list->max);
1892 return LY_EVALID;
1893 }
1894
1895 return LY_SUCCESS;
1896}
1897
1898/**
David Sedlák031b9e72019-07-23 15:19:37 +02001899 * @brief Parse notification element.
1900 *
1901 * @param[in,out] ctx YIN parser context for logging and to store current state.
1902 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1903 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001904 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedlák031b9e72019-07-23 15:19:37 +02001905 *
1906 * @return LY_ERR values.
1907 */
1908static LY_ERR
1909yin_parse_notification(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1910 struct notif_meta *notif_meta)
1911{
1912 struct lysp_notif *notif;
1913
1914 /* allocate new notification */
1915 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *notif_meta->notifs, notif, LY_EMEM);
1916 notif->nodetype = LYS_NOTIF;
1917 notif->parent = notif_meta->parent;
1918
1919 /* parse argument */
1920 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, YANG_NOTIFICATION));
1921
1922 /* parse notification content */
1923 struct tree_node_meta node_meta = {(struct lysp_node *)notif, &notif->data};
1924 struct typedef_meta typedef_meta = {(struct lysp_node *)notif, &notif->typedefs};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001925 struct grouping_meta gr_meta = {(struct lysp_node *)notif, &notif->groupings};
David Sedlák031b9e72019-07-23 15:19:37 +02001926 struct yin_subelement subelems[16] = {
1927 {YANG_ANYDATA, &node_meta, 0},
1928 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001929 {YANG_CHOICE, &node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02001930 {YANG_CONTAINER, &node_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001931 {YANG_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001932 {YANG_GROUPING, &gr_meta, 0},
David Sedlák031b9e72019-07-23 15:19:37 +02001933 {YANG_IF_FEATURE, &notif->iffeatures, 0},
1934 {YANG_LEAF, &node_meta, 0},
1935 {YANG_LEAF_LIST, &node_meta, 0},
1936 {YANG_LIST, &node_meta, 0},
1937 {YANG_MUST, &notif->musts, YIN_SUBELEM_VER2},
1938 {YANG_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE},
1939 {YANG_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE},
1940 {YANG_TYPEDEF, &typedef_meta, 0},
1941 {YANG_USES, &node_meta, 0},
1942 {YANG_CUSTOM, NULL, 0},
1943 };
1944 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_NOTIFICATION, NULL, &notif->exts));
1945
1946 /* finalize parent pointers to the reallocated items */
1947 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, notif->groupings, NULL, NULL, NULL));
1948
1949 return LY_SUCCESS;
1950}
1951
1952/**
David Sedláke3ce9ef2019-07-23 16:34:30 +02001953 * @brief Parse notification element.
1954 *
1955 * @param[in,out] ctx YIN parser context for logging and to store current state.
1956 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
1957 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02001958 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
David Sedláke3ce9ef2019-07-23 16:34:30 +02001959 *
1960 * @return LY_ERR values.
1961 */
1962static LY_ERR
1963yin_parse_grouping(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
1964 struct grouping_meta *gr_meta)
1965{
1966 struct lysp_grp *grp;
1967
1968 /* create new grouping */
1969 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *gr_meta->groupings, grp, LY_EMEM);
1970 grp->nodetype = LYS_GROUPING;
1971 grp->parent = gr_meta->parent;
1972
1973 /* parse argument */
1974 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, YANG_GROUPING));
1975
1976 /* parse grouping content */
David Sedlák85d0eca2019-07-24 15:15:21 +02001977 struct action_meta act_meta = {(struct lysp_node *)grp, &grp->actions};
David Sedláke3ce9ef2019-07-23 16:34:30 +02001978 struct tree_node_meta node_meta = {(struct lysp_node *)grp, &grp->data};
1979 struct typedef_meta typedef_meta = {(struct lysp_node *)grp, &grp->typedefs};
1980 struct grouping_meta sub_grouping = {(struct lysp_node *)grp, &grp->groupings};
1981 struct notif_meta notif_meta = {(struct lysp_node *)grp, &grp->notifs};
1982 struct yin_subelement subelems[16] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02001983 {YANG_ACTION, &act_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001984 {YANG_ANYDATA, &node_meta, 0},
1985 {YANG_ANYXML, &node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02001986 {YANG_CHOICE, &node_meta, 0},
David Sedláke3ce9ef2019-07-23 16:34:30 +02001987 {YANG_CONTAINER, &node_meta, 0},
1988 {YANG_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE},
1989 {YANG_GROUPING, &sub_grouping, 0},
1990 {YANG_LEAF, &node_meta, 0},
1991 {YANG_LEAF_LIST, &node_meta, 0},
1992 {YANG_LIST, &node_meta, 0},
1993 {YANG_NOTIFICATION, &notif_meta, 0},
1994 {YANG_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE},
1995 {YANG_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE},
1996 {YANG_TYPEDEF, &typedef_meta, 0},
1997 {YANG_USES, &node_meta, 0},
1998 {YANG_CUSTOM, NULL, 0},
1999 };
2000 LY_CHECK_RET(yin_parse_content(ctx, subelems, 16, data, YANG_GROUPING, NULL, &grp->exts));
2001 /* finalize parent pointers to the reallocated items */
2002 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, grp->groupings, NULL, grp->actions, grp->notifs));
2003
2004 return LY_SUCCESS;
2005}
2006
2007/**
David Sedlákf111bcb2019-07-23 17:15:51 +02002008 * @brief Parse list element.
2009 *
2010 * @param[in,out] ctx YIN parser context for logging and to store current state.
2011 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2012 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002013 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákf111bcb2019-07-23 17:15:51 +02002014 *
2015 * @return LY_ERR values.
2016 */
2017static LY_ERR
2018yin_parse_container(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2019 struct tree_node_meta *node_meta)
2020{
David Sedlákf111bcb2019-07-23 17:15:51 +02002021 struct lysp_node_container *cont;
2022
2023 /* create new container */
David Sedlák8d552d62019-08-06 15:29:05 +02002024 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cont, next);
David Sedlákf111bcb2019-07-23 17:15:51 +02002025 cont->nodetype = LYS_CONTAINER;
2026 cont->parent = node_meta->parent;
2027
David Sedlákf111bcb2019-07-23 17:15:51 +02002028 /* parse aegument */
2029 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cont->name, Y_IDENTIF_ARG, YANG_CONTAINER));
2030
2031 /* parse container content */
David Sedlák85d0eca2019-07-24 15:15:21 +02002032 struct action_meta act_meta = {(struct lysp_node *)cont, &cont->actions};
David Sedlákf111bcb2019-07-23 17:15:51 +02002033 struct tree_node_meta new_node_meta = {(struct lysp_node *)cont, &cont->child};
2034 struct grouping_meta grp_meta = {(struct lysp_node *)cont, &cont->groupings};
2035 struct typedef_meta typedef_meta = {(struct lysp_node *)cont, &cont->typedefs};
2036 struct notif_meta notif_meta = {(struct lysp_node *)cont, &cont->notifs};
2037 struct yin_subelement subelems[21] = {
David Sedlák85d0eca2019-07-24 15:15:21 +02002038 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
David Sedlákf111bcb2019-07-23 17:15:51 +02002039 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2040 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02002041 {YANG_CHOICE, &new_node_meta, 0},
David Sedlákf111bcb2019-07-23 17:15:51 +02002042 {YANG_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE},
2043 {YANG_CONTAINER, &new_node_meta, 0},
2044 {YANG_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE},
2045 {YANG_GROUPING, &grp_meta, 0},
2046 {YANG_IF_FEATURE, &cont->iffeatures, 0},
2047 {YANG_LEAF, &new_node_meta, 0},
2048 {YANG_LEAF_LIST, &new_node_meta, 0},
2049 {YANG_LIST, &new_node_meta, 0},
2050 {YANG_MUST, &cont->musts, 0},
2051 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2052 {YANG_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE},
2053 {YANG_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE},
2054 {YANG_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE},
2055 {YANG_TYPEDEF, &typedef_meta, 0},
2056 {YANG_USES, &new_node_meta, 0},
2057 {YANG_WHEN, &cont->when, YIN_SUBELEM_UNIQUE},
2058 {YANG_CUSTOM, NULL, 0},
2059 };
2060 LY_CHECK_RET(yin_parse_content(ctx, subelems, 21, data, YANG_CONTAINER, NULL, &cont->exts));
2061 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, cont->groupings, NULL, cont->actions, cont->notifs));
2062
2063 return LY_SUCCESS;
2064}
2065
2066/**
David Sedlák5379d392019-07-24 10:42:03 +02002067 * @brief Parse case element.
2068 *
2069 * @param[in,out] ctx YIN parser context for logging and to store current state.
2070 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2071 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002072 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlák5379d392019-07-24 10:42:03 +02002073 *
2074 * @return LY_ERR values.
2075 */
2076static LY_ERR
2077yin_parse_case(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2078 struct tree_node_meta *node_meta)
2079{
David Sedlák5379d392019-07-24 10:42:03 +02002080 struct lysp_node_case *cas;
2081
2082 /* create new case */
David Sedlák8d552d62019-08-06 15:29:05 +02002083 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, cas, next);
David Sedlák5379d392019-07-24 10:42:03 +02002084 cas->nodetype = LYS_CASE;
2085 cas->parent = node_meta->parent;
2086
David Sedlák5379d392019-07-24 10:42:03 +02002087 /* parse argument */
2088 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, YANG_CASE));
2089
2090 /* parse case content */
2091 struct tree_node_meta new_node_meta = {(struct lysp_node *)cas, &cas->child};
2092 struct yin_subelement subelems[14] = {
2093 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2094 {YANG_ANYXML, &new_node_meta, 0},
David Sedlákb7abcfa2019-07-24 12:33:35 +02002095 {YANG_CHOICE, &new_node_meta, 0},
David Sedlák5379d392019-07-24 10:42:03 +02002096 {YANG_CONTAINER, &new_node_meta, 0},
2097 {YANG_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE},
2098 {YANG_IF_FEATURE, &cas->iffeatures, 0},
2099 {YANG_LEAF, &new_node_meta, 0},
2100 {YANG_LEAF_LIST, &new_node_meta, 0},
2101 {YANG_LIST, &new_node_meta, 0},
2102 {YANG_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE},
2103 {YANG_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE},
2104 {YANG_USES, &new_node_meta, 0},
2105 {YANG_WHEN, &cas->when, YIN_SUBELEM_UNIQUE},
2106 {YANG_CUSTOM, NULL, 0},
2107 };
2108 return yin_parse_content(ctx, subelems, 14, data, YANG_CASE, NULL, &cas->exts);
2109}
2110
2111/**
David Sedlák05404f62019-07-24 14:11:53 +02002112 * @brief Parse choice element.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002113 *
2114 * @param[in,out] ctx YIN parser context for logging and to store current state.
2115 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2116 * @param[in,out] data Data to read from, always moved to currently handled character.
David Sedlák05404f62019-07-24 14:11:53 +02002117 * @param[in] node_meta Meta information about parent node and siblings.
David Sedlákb7abcfa2019-07-24 12:33:35 +02002118 *
2119 * @return LY_ERR values.
2120 */
2121LY_ERR
2122yin_parse_choice(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2123 struct tree_node_meta *node_meta)
2124{
David Sedlákb7abcfa2019-07-24 12:33:35 +02002125 struct lysp_node_choice *choice;
2126
2127 /* create new choice */
David Sedlák8d552d62019-08-06 15:29:05 +02002128 LY_LIST_NEW_RET(ctx->xml_ctx.ctx, node_meta->siblings, choice, next);
2129
David Sedlákb7abcfa2019-07-24 12:33:35 +02002130 choice->nodetype = LYS_CHOICE;
2131 choice->parent = node_meta->parent;
2132
David Sedlákb7abcfa2019-07-24 12:33:35 +02002133 /* parse argument */
2134 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, YANG_CHOICE));
2135
2136 /* parse choice content */
2137 struct tree_node_meta new_node_meta = {(struct lysp_node *)choice, &choice->child};
2138 struct yin_subelement subelems[17] = {
2139 {YANG_ANYDATA, &new_node_meta, YIN_SUBELEM_VER2},
2140 {YANG_ANYXML, &new_node_meta, 0},
2141 {YANG_CASE, &new_node_meta, 0},
2142 {YANG_CHOICE, &new_node_meta, YIN_SUBELEM_VER2},
2143 {YANG_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE},
2144 {YANG_CONTAINER, &new_node_meta, 0},
2145 {YANG_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE},
2146 {YANG_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE},
2147 {YANG_IF_FEATURE, &choice->iffeatures, 0},
2148 {YANG_LEAF, &new_node_meta, 0},
2149 {YANG_LEAF_LIST, &new_node_meta, 0},
2150 {YANG_LIST, &new_node_meta, 0},
2151 {YANG_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE},
2152 {YANG_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE},
2153 {YANG_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE},
2154 {YANG_WHEN, &choice->when, YIN_SUBELEM_UNIQUE},
2155 {YANG_CUSTOM, NULL, 0},
2156 };
2157 return yin_parse_content(ctx, subelems, 17, data, YANG_CHOICE, NULL, &choice->exts);
2158}
2159
2160/**
David Sedlák05404f62019-07-24 14:11:53 +02002161 * @brief Parse input or output element.
2162 *
2163 * @param[in,out] ctx YIN parser context for logging and to store current state.
2164 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2165 * @param[in,out] data Data to read from, always moved to currently handled character.
2166 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2167 *
2168 * @return LY_ERR values.
2169 */
2170static LY_ERR
2171yin_parse_inout(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum yang_keyword inout_kw,
2172 struct inout_meta *inout_meta)
2173{
2174 /* initiate structure */
2175 inout_meta->inout_p->nodetype = (inout_kw == YANG_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2176 inout_meta->inout_p->parent = inout_meta->parent;
2177
2178 /* check attributes */
2179 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2180
2181 /* parser input/output content */
2182 struct tree_node_meta node_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->data};
2183 struct grouping_meta grp_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->groupings};
2184 struct typedef_meta typedef_meta = {(struct lysp_node *)inout_meta->inout_p, &inout_meta->inout_p->typedefs};
2185 struct yin_subelement subelems[12] = {
2186 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2187 {YANG_ANYXML, &node_meta, 0},
2188 {YANG_CHOICE, &node_meta, 0},
2189 {YANG_CONTAINER, &node_meta, 0},
2190 {YANG_GROUPING, &grp_meta, 0},
2191 {YANG_LEAF, &node_meta, 0},
2192 {YANG_LEAF_LIST, &node_meta, 0},
2193 {YANG_LIST, &node_meta, 0},
2194 {YANG_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2},
2195 {YANG_TYPEDEF, &typedef_meta, 0},
2196 {YANG_USES, &node_meta, 0},
2197 {YANG_CUSTOM, NULL, 0},
2198 };
2199 LY_CHECK_RET(yin_parse_content(ctx, subelems, 12, data, inout_kw, NULL, &inout_meta->inout_p->exts));
2200
2201 /* finalize parent pointers to the reallocated items */
2202 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, inout_meta->inout_p->groupings,
2203 NULL, NULL, NULL));
2204
2205 return LY_SUCCESS;
2206}
2207
David Sedlák992fb7c2019-07-24 16:51:01 +02002208/**
2209 * @brief Parse action element.
2210 *
2211 * @param[in,out] ctx YIN parser context for logging and to store current state.
2212 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2213 * @param[in,out] data Data to read from, always moved to currently handled character.
2214 * @param[in] act_meta Meta information about parent node and actions to add to.
2215 *
2216 * @return LY_ERR values.
2217 */
David Sedlák85d0eca2019-07-24 15:15:21 +02002218static LY_ERR
2219yin_parse_action(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2220 struct action_meta *act_meta)
2221{
2222 struct lysp_action *act;
2223
2224 /* create new action */
2225 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *act_meta->actions, act, LY_EMEM);
2226 act->nodetype = LYS_ACTION;
2227 act->parent = act_meta->parent;
2228
2229 /* parse argument */
2230 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, YANG_ACTION));
2231
2232 /* parse content */
2233 struct grouping_meta grp_meta = {(struct lysp_node *)act, &act->groupings};
2234 struct typedef_meta typedef_meta = {(struct lysp_node *)act, &act->typedefs};
2235 struct inout_meta input = {(struct lysp_node *)act, &act->input};
2236 struct inout_meta output = {(struct lysp_node *)act, &act->output};
2237 struct yin_subelement subelems[9] = {
2238 {YANG_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE},
2239 {YANG_GROUPING, &grp_meta, 0},
2240 {YANG_IF_FEATURE, &act->iffeatures, 0},
2241 {YANG_INPUT, &input, YIN_SUBELEM_UNIQUE},
2242 {YANG_OUTPUT, &output, YIN_SUBELEM_UNIQUE},
2243 {YANG_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE},
2244 {YANG_STATUS, &act->flags, YIN_SUBELEM_UNIQUE},
2245 {YANG_TYPEDEF, &typedef_meta, 0},
2246 {YANG_CUSTOM, NULL, 0},
2247 };
2248 LY_CHECK_RET(yin_parse_content(ctx, subelems, 9, data, YANG_ACTION, NULL, &act->exts));
2249 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, act->groupings, NULL, NULL, NULL));
2250
2251 return LY_SUCCESS;
2252}
2253
David Sedlák05404f62019-07-24 14:11:53 +02002254/**
David Sedlák992fb7c2019-07-24 16:51:01 +02002255 * @brief Parse augment element.
2256 *
2257 * @param[in,out] ctx YIN parser context for logging and to store current state.
2258 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2259 * @param[in,out] data Data to read from, always moved to currently handled character.
2260 * @param[in] aug_meta Meta information about parent node and augments to add to.
2261 *
2262 * @return LY_ERR values.
2263 */
2264static LY_ERR
2265yin_parse_augment(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2266 struct augment_meta *aug_meta)
2267{
2268 struct lysp_augment *aug;
2269
2270 /* create new augment */
2271 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *aug_meta->augments, aug, LY_EMEM);
2272 aug->nodetype = LYS_AUGMENT;
2273 aug->parent = aug_meta->parent;
2274
2275 /* parse argument */
2276 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, YANG_AUGMENT));
2277 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(aug->nodeid), "augment");
2278
2279 /* parser augment content */
2280 struct action_meta act_meta = {(struct lysp_node *)aug, &aug->actions};
2281 struct tree_node_meta node_meta = {(struct lysp_node *)aug, &aug->child};
2282 struct notif_meta notif_meta = {(struct lysp_node *)aug, &aug->notifs};
2283 struct yin_subelement subelems[17] = {
2284 {YANG_ACTION, &act_meta, YIN_SUBELEM_VER2},
2285 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
2286 {YANG_ANYXML, &node_meta, 0},
2287 {YANG_CASE, &node_meta, 0},
2288 {YANG_CHOICE, &node_meta, 0},
2289 {YANG_CONTAINER, &node_meta, 0},
2290 {YANG_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE},
2291 {YANG_IF_FEATURE, &aug->iffeatures, 0},
2292 {YANG_LEAF, &node_meta, 0},
2293 {YANG_LEAF_LIST, &node_meta, 0},
2294 {YANG_LIST, &node_meta, 0},
2295 {YANG_NOTIFICATION, &notif_meta, YIN_SUBELEM_VER2},
2296 {YANG_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE},
2297 {YANG_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE},
2298 {YANG_USES, &node_meta, 0},
2299 {YANG_WHEN, &aug->when, YIN_SUBELEM_UNIQUE},
2300 {YANG_CUSTOM, NULL, 0},
2301 };
2302 LY_CHECK_RET(yin_parse_content(ctx, subelems, 17, data, YANG_AUGMENT, NULL, &aug->exts));
2303
2304 LY_CHECK_RET(lysp_parse_finalize_reallocated((struct lys_parser_ctx *)ctx, NULL, NULL, aug->actions, aug->notifs));
2305
2306 return LY_SUCCESS;
2307}
2308
David Sedlák8b754462019-07-25 16:22:13 +02002309/**
2310 * @brief Parse deviate element.
2311 *
2312 * @param[in,out] ctx YIN parser context for logging and to store current state.
2313 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2314 * @param[in,out] data Data to read from, always moved to currently handled character.
2315 * @param[in] deviates Deviates to add to.
2316 *
2317 * @return LY_ERR values.
2318 */
David Sedlák4ffcec82019-07-25 15:10:21 +02002319static LY_ERR
2320yin_parse_deviate(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2321 struct lysp_deviate **deviates)
2322{
2323 LY_ERR ret = LY_SUCCESS;
2324 uint8_t dev_mod;
2325 const char *temp_val;
David Sedlák8d552d62019-08-06 15:29:05 +02002326 struct lysp_deviate *d;
David Sedlák4ffcec82019-07-25 15:10:21 +02002327 struct lysp_deviate_add *d_add = NULL;
2328 struct lysp_deviate_rpl *d_rpl = NULL;
2329 struct lysp_deviate_del *d_del = NULL;
2330
2331 /* parse argument */
2332 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, YANG_DEVIATE));
2333
2334 if (strcmp(temp_val, "not-supported") == 0) {
2335 dev_mod = LYS_DEV_NOT_SUPPORTED;
2336 } else if (strcmp(temp_val, "add") == 0) {
2337 dev_mod = LYS_DEV_ADD;
2338 } else if (strcmp(temp_val, "replace") == 0) {
2339 dev_mod = LYS_DEV_REPLACE;
2340 } else if (strcmp(temp_val, "delete") == 0) {
2341 dev_mod = LYS_DEV_DELETE;
2342 } else {
2343 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INVAL, strlen(temp_val), temp_val, "deviate");
2344 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2345 return LY_EVALID;
2346 }
2347 FREE_STRING(ctx->xml_ctx.ctx, temp_val);
2348
2349 if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2350 d = calloc(1, sizeof *d);
2351 LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2352 struct yin_subelement subelems[1] = {
2353 {YANG_CUSTOM, NULL, 0}
2354 };
2355 ret = yin_parse_content(ctx, subelems, 1, data, YANG_DEVIATE, NULL, &d->exts);
2356
2357 } else if (dev_mod == LYS_DEV_ADD) {
2358 d_add = calloc(1, sizeof *d_add);
2359 LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2360 d = (struct lysp_deviate *)d_add;
2361 struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2362 struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2363 struct yin_subelement subelems[9] = {
2364 {YANG_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2365 {YANG_DEFAULT, &d_add->dflts, 0},
2366 {YANG_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2367 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2368 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2369 {YANG_MUST, &d_add->musts, 0},
2370 {YANG_UNIQUE, &d_add->uniques, 0},
2371 {YANG_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2372 {YANG_CUSTOM, NULL, 0},
2373 };
2374 ret = yin_parse_content(ctx, subelems, 9, data, YANG_DEVIATE, NULL, &d_add->exts);
2375
2376 } else if (dev_mod == LYS_DEV_REPLACE) {
2377 d_rpl = calloc(1, sizeof *d_rpl);
2378 LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2379 d = (struct lysp_deviate *)d_rpl;
2380 struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2381 struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2382 struct yin_subelement subelems[8] = {
2383 {YANG_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2384 {YANG_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2385 {YANG_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2386 {YANG_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2387 {YANG_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2388 {YANG_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2389 {YANG_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2390 {YANG_CUSTOM, NULL, 0},
2391 };
2392 ret = yin_parse_content(ctx, subelems, 8, data, YANG_DEVIATE, NULL, &d_rpl->exts);
2393
2394 } else {
2395 d_del = calloc(1, sizeof *d_del);
2396 LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
2397 d = (struct lysp_deviate *)d_del;
2398 struct yin_subelement subelems[5] = {
2399 {YANG_DEFAULT, &d_del->dflts, 0},
2400 {YANG_MUST, &d_del->musts, 0},
2401 {YANG_UNIQUE, &d_del->uniques, 0},
2402 {YANG_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2403 {YANG_CUSTOM, NULL, 0},
2404 };
2405 ret = yin_parse_content(ctx, subelems, 5, data, YANG_DEVIATE, NULL, &d_del->exts);
2406 }
2407 LY_CHECK_GOTO(ret, cleanup);
2408
2409 d->mod = dev_mod;
2410 /* insert into siblings */
David Sedlák8d552d62019-08-06 15:29:05 +02002411 LY_LIST_INSERT(deviates, d, next);
David Sedlák4ffcec82019-07-25 15:10:21 +02002412
2413 return ret;
2414
2415cleanup:
2416 free(d);
David Sedlák4ffcec82019-07-25 15:10:21 +02002417 return ret;
2418}
2419
David Sedlák992fb7c2019-07-24 16:51:01 +02002420/**
David Sedlák8b754462019-07-25 16:22:13 +02002421 * @brief Parse deviation element.
2422 *
2423 * @param[in,out] ctx YIN parser context for logging and to store current state.
2424 * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of current element.
2425 * @param[in,out] data Data to read from, always moved to currently handled character.
2426 * @param[in] deviations Deviations to add to.
2427 *
2428 * @return LY_ERR values.
2429 */
2430static LY_ERR
2431yin_parse_deviation(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data,
2432 struct lysp_deviation **deviations)
2433{
2434 struct lysp_deviation *dev;
2435
2436 /* create new deviation */
2437 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *deviations, dev, LY_EMEM);
2438
2439 /* parse argument */
2440 LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, YANG_DEVIATE));
2441 YANG_CHECK_NONEMPTY((struct lys_parser_ctx *)ctx, strlen(dev->nodeid), "deviation");
2442 struct yin_subelement subelems[4] = {
2443 {YANG_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2444 {YANG_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2445 {YANG_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2446 {YANG_CUSTOM, NULL, 0},
2447 };
2448 return yin_parse_content(ctx, subelems, 4, data, YANG_DEVIATE, NULL, &dev->exts);
2449}
2450
2451/**
David Sedlákb4e44562019-07-04 15:42:12 +02002452 * @brief Map keyword type to substatement info.
2453 *
2454 * @param[in] kw Keyword type.
2455 *
2456 * @return correct LYEXT_SUBSTMT information.
2457 */
2458static LYEXT_SUBSTMT
2459kw2lyext_substmt(enum yang_keyword kw)
2460{
2461 switch (kw) {
2462 case YANG_ARGUMENT:
2463 return LYEXT_SUBSTMT_ARGUMENT;
2464 case YANG_BASE:
2465 return LYEXT_SUBSTMT_BASE;
2466 case YANG_BELONGS_TO:
2467 return LYEXT_SUBSTMT_BELONGSTO;
2468 case YANG_CONTACT:
2469 return LYEXT_SUBSTMT_CONTACT;
2470 case YANG_DEFAULT:
2471 return LYEXT_SUBSTMT_DEFAULT;
2472 case YANG_DESCRIPTION:
2473 return LYEXT_SUBSTMT_DESCRIPTION;
2474 case YANG_ERROR_APP_TAG:
2475 return LYEXT_SUBSTMT_ERRTAG;
2476 case YANG_ERROR_MESSAGE:
2477 return LYEXT_SUBSTMT_ERRMSG;
2478 case YANG_KEY:
2479 return LYEXT_SUBSTMT_KEY;
2480 case YANG_NAMESPACE:
2481 return LYEXT_SUBSTMT_NAMESPACE;
2482 case YANG_ORGANIZATION:
2483 return LYEXT_SUBSTMT_ORGANIZATION;
2484 case YANG_PATH:
2485 return LYEXT_SUBSTMT_PATH;
2486 case YANG_PREFIX:
2487 return LYEXT_SUBSTMT_PREFIX;
2488 case YANG_PRESENCE:
2489 return LYEXT_SUBSTMT_PRESENCE;
2490 case YANG_REFERENCE:
2491 return LYEXT_SUBSTMT_REFERENCE;
2492 case YANG_REVISION_DATE:
2493 return LYEXT_SUBSTMT_REVISIONDATE;
2494 case YANG_UNITS:
2495 return LYEXT_SUBSTMT_UNITS;
2496 case YANG_VALUE:
2497 return LYEXT_SUBSTMT_VALUE;
2498 case YANG_YANG_VERSION:
2499 return LYEXT_SUBSTMT_VERSION;
2500 case YANG_MODIFIER:
2501 return LYEXT_SUBSTMT_MODIFIER;
2502 case YANG_REQUIRE_INSTANCE:
2503 return LYEXT_SUBSTMT_REQINSTANCE;
2504 case YANG_YIN_ELEMENT:
2505 return LYEXT_SUBSTMT_YINELEM;
2506 case YANG_CONFIG:
2507 return LYEXT_SUBSTMT_CONFIG;
2508 case YANG_MANDATORY:
2509 return LYEXT_SUBSTMT_MANDATORY;
2510 case YANG_ORDERED_BY:
2511 return LYEXT_SUBSTMT_ORDEREDBY;
2512 case YANG_STATUS:
2513 return LYEXT_SUBSTMT_STATUS;
2514 case YANG_FRACTION_DIGITS:
2515 return LYEXT_SUBSTMT_FRACDIGITS;
2516 case YANG_MAX_ELEMENTS:
2517 return LYEXT_SUBSTMT_MAX;
2518 case YANG_MIN_ELEMENTS:
2519 return LYEXT_SUBSTMT_MIN;
2520 case YANG_POSITION:
2521 return LYEXT_SUBSTMT_POSITION;
2522 case YANG_UNIQUE:
2523 return LYEXT_SUBSTMT_UNIQUE;
2524 case YANG_IF_FEATURE:
2525 return LYEXT_SUBSTMT_IFFEATURE;
2526 default:
2527 return LYEXT_SUBSTMT_SELF;
2528 }
2529}
2530
David Sedláke6cd89e2019-08-07 12:46:02 +02002531static LY_ERR
2532kw2kw_group(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_module_stmt *group)
2533{
2534 switch (kw) {
2535 /* module header */
2536 case YANG_NONE:
2537 case YANG_NAMESPACE:
2538 case YANG_PREFIX:
2539 case YANG_BELONGS_TO:
2540 case YANG_YANG_VERSION:
2541 *group = Y_MOD_MODULE_HEADER;
2542 break;
2543 /* linkage */
2544 case YANG_INCLUDE:
2545 case YANG_IMPORT:
2546 *group = Y_MOD_LINKAGE;
2547 break;
2548 /* meta */
2549 case YANG_ORGANIZATION:
2550 case YANG_CONTACT:
2551 case YANG_DESCRIPTION:
2552 case YANG_REFERENCE:
2553 *group = Y_MOD_META;
2554 break;
2555 /* revision */
2556 case YANG_REVISION:
2557 *group = Y_MOD_REVISION;
2558 break;
2559 /* body */
2560 case YANG_ANYDATA:
2561 case YANG_ANYXML:
2562 case YANG_AUGMENT:
2563 case YANG_CHOICE:
2564 case YANG_CONTAINER:
2565 case YANG_DEVIATION:
2566 case YANG_EXTENSION:
2567 case YANG_FEATURE:
2568 case YANG_GROUPING:
2569 case YANG_IDENTITY:
2570 case YANG_LEAF:
2571 case YANG_LEAF_LIST:
2572 case YANG_LIST:
2573 case YANG_NOTIFICATION:
2574 case YANG_RPC:
2575 case YANG_TYPEDEF:
2576 case YANG_USES:
2577 case YANG_CUSTOM:
2578 *group = Y_MOD_BODY;
2579 break;
2580 default:
2581 LOGINT(ctx->xml_ctx.ctx);
2582 return LY_EINT;
2583 }
2584
2585 return LY_SUCCESS;
2586}
2587
2588static LY_ERR
2589yin_check_relative_order(struct yin_parser_ctx *ctx, enum yang_keyword kw, enum yang_keyword next_kw, enum yang_keyword parrent)
2590{
2591 assert(parrent == YANG_MODULE || parrent == YANG_SUBMODULE);
2592 enum yang_module_stmt gr, next_gr;
2593
2594 LY_CHECK_RET(kw2kw_group(ctx, kw, &gr));
2595 LY_CHECK_RET(kw2kw_group(ctx, next_kw, &next_gr));
2596
2597 if (gr > next_gr) {
2598 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INORDER_YIN, ly_stmt2str(parrent), ly_stmt2str(next_kw), ly_stmt2str(kw));
2599 return LY_EVALID;
2600 }
2601
2602 return LY_SUCCESS;
2603}
2604
David Sedlákd6e56892019-07-01 15:40:24 +02002605LY_ERR
David Sedlákda8ffa32019-07-08 14:17:10 +02002606yin_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 +02002607 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 +02002608{
2609 LY_ERR ret = LY_SUCCESS;
2610 struct sized_string prefix, name;
David Sedlák8e7bda82019-07-16 17:57:50 +02002611 char *out = NULL;
2612 size_t out_len = 0;
2613 int dynamic = 0;
David Sedlák1af868e2019-07-17 17:03:14 +02002614 struct yin_arg_record *attrs = NULL;
David Sedláke6cd89e2019-08-07 12:46:02 +02002615 enum yang_keyword kw = YANG_NONE, last_kw = YANG_NONE;
David Sedlák1af868e2019-07-17 17:03:14 +02002616 struct yin_subelement *subelem = NULL;
David Sedlák374d2b32019-07-17 15:06:55 +02002617 struct lysp_type *type, *nested_type;
David Sedlák09e18c92019-07-18 11:17:11 +02002618
David Sedlákb0faad82019-07-04 14:28:59 +02002619 assert(is_ordered(subelem_info, subelem_info_size));
David Sedlákd6e56892019-07-01 15:40:24 +02002620
David Sedlákda8ffa32019-07-08 14:17:10 +02002621 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
2622 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákd6e56892019-07-01 15:40:24 +02002623 /* current element has subelements as content */
2624 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002625 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
2626 ret = lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len);
David Sedlákd6e56892019-07-01 15:40:24 +02002627 LY_CHECK_GOTO(ret, cleanup);
2628 if (!name.value) {
2629 /* end of current element reached */
2630 break;
2631 }
David Sedlák1af868e2019-07-17 17:03:14 +02002632 ret = yin_load_attributes(ctx, data, &attrs);
David Sedlákd6e56892019-07-01 15:40:24 +02002633 LY_CHECK_GOTO(ret, cleanup);
David Sedláke6cd89e2019-08-07 12:46:02 +02002634 last_kw = kw;
David Sedlákc1771b12019-07-10 15:55:46 +02002635 kw = yin_match_keyword(ctx, name.value, name.len, prefix.value, prefix.len, current_element);
David Sedlákd6e56892019-07-01 15:40:24 +02002636
2637 /* check if this element can be child of current element */
David Sedlák1af868e2019-07-17 17:03:14 +02002638 subelem = get_record(kw, subelem_info_size, subelem_info);
2639 if (!subelem) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002640 if (current_element == YANG_DEVIATE && isdevsub(kw)) {
2641 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_INDEV_YIN, ly_stmt2str(kw));
2642 } else {
2643 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name.len, name.value, ly_stmt2str(current_element));
2644 }
David Sedlákd6e56892019-07-01 15:40:24 +02002645 ret = LY_EVALID;
2646 goto cleanup;
2647 }
2648
David Sedláke6cd89e2019-08-07 12:46:02 +02002649 if (current_element == YANG_MODULE || current_element == YANG_SUBMODULE) {
2650 ret = yin_check_relative_order(ctx, last_kw, kw, current_element);
2651 LY_CHECK_GOTO(ret, cleanup);
2652 }
David Sedlák5f8191e2019-07-08 16:35:52 +02002653
David Sedlák4ffcec82019-07-25 15:10:21 +02002654 /* flag check */
David Sedlák1af868e2019-07-17 17:03:14 +02002655 if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002656 /* subelement uniquenes */
David Sedlákda8ffa32019-07-08 14:17:10 +02002657 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVE_SYNTAX_YIN, "Redefinition of %s element in %s element.", ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák21f87cd2019-07-03 16:53:23 +02002658 return LY_EVALID;
2659 }
David Sedlák1af868e2019-07-17 17:03:14 +02002660 if (subelem->flags & YIN_SUBELEM_FIRST) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002661 /* subelement is supposed to be defined as first subelement */
David Sedlák1af868e2019-07-17 17:03:14 +02002662 ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, current_element, subelem);
David Sedlák66d7c842019-07-11 15:06:04 +02002663 LY_CHECK_GOTO(ret, cleanup);
David Sedlák21f87cd2019-07-03 16:53:23 +02002664 }
David Sedlák0c2bab92019-07-22 15:33:19 +02002665 if (subelem->flags & YIN_SUBELEM_VER2) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002666 /* subelement is supported only in version 1.1 or higher */
David Sedlák0c2bab92019-07-22 15:33:19 +02002667 if (ctx->mod_version < 2) {
2668 LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LYVCODE_INSUBELEM2, ly_stmt2str(kw), ly_stmt2str(current_element));
David Sedlák9bb1c042019-07-22 16:45:37 +02002669 ret = LY_EVALID;
2670 goto cleanup;
David Sedlák0c2bab92019-07-22 15:33:19 +02002671 }
2672 }
David Sedlák4ffcec82019-07-25 15:10:21 +02002673 /* note that element was parsed for easy uniqueness check in next iterations */
David Sedlák1af868e2019-07-17 17:03:14 +02002674 subelem->flags |= YIN_SUBELEM_PARSED;
David Sedlák21f87cd2019-07-03 16:53:23 +02002675
David Sedlákd6e56892019-07-01 15:40:24 +02002676 switch (kw) {
David Sedlák4ffcec82019-07-25 15:10:21 +02002677 /* call responsible function */
David Sedlákd6e56892019-07-01 15:40:24 +02002678 case YANG_CUSTOM:
David Sedlák1af868e2019-07-17 17:03:14 +02002679 ret = yin_parse_extension_instance(ctx, attrs, data, name2fullname(name.value, prefix.len),
David Sedlák3ffbc522019-07-02 17:49:28 +02002680 namelen2fulllen(name.len, prefix.len),
David Sedlák1af868e2019-07-17 17:03:14 +02002681 kw2lyext_substmt(current_element),
2682 (subelem->dest) ? *((uint32_t*)subelem->dest) : 0, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002683 break;
2684 case YANG_ACTION:
David Sedlákeaa45792019-07-24 15:25:01 +02002685 case YANG_RPC:
David Sedlák85d0eca2019-07-24 15:15:21 +02002686 ret = yin_parse_action(ctx, attrs, data, (struct action_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002687 break;
2688 case YANG_ANYDATA:
David Sedlákd6e56892019-07-01 15:40:24 +02002689 case YANG_ANYXML:
David Sedlák8a83bbb2019-07-18 14:46:00 +02002690 ret = yin_parse_any(ctx, attrs, data, kw, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002691 break;
2692 case YANG_ARGUMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002693 ret = yin_parse_argument_element(ctx, attrs, data, (struct yin_argument_meta *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002694 break;
2695 case YANG_AUGMENT:
David Sedlák992fb7c2019-07-24 16:51:01 +02002696 ret = yin_parse_augment(ctx, attrs, data, (struct augment_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002697 break;
2698 case YANG_BASE:
David Sedláka62750b2019-07-16 11:21:31 +02002699 if (current_element == YANG_TYPE) {
David Sedlák1af868e2019-07-17 17:03:14 +02002700 type = (struct lysp_type *)subelem->dest;
2701 ret = yin_parse_simple_elements(ctx, attrs, data, kw, &type->bases, YIN_ARG_NAME,
David Sedlák292763b2019-07-09 11:10:53 +02002702 Y_PREF_IDENTIF_ARG, exts);
2703 type->flags |= LYS_SET_BASE;
David Sedláka62750b2019-07-16 11:21:31 +02002704 } else if (current_element == YANG_IDENTITY) {
David Sedlák1af868e2019-07-17 17:03:14 +02002705 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedlák292763b2019-07-09 11:10:53 +02002706 YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts);
2707 } else {
2708 LOGINT(ctx->xml_ctx.ctx);
2709 ret = LY_EINT;
2710 }
David Sedlákd6e56892019-07-01 15:40:24 +02002711 break;
2712 case YANG_BELONGS_TO:
David Sedlák1af868e2019-07-17 17:03:14 +02002713 ret = yin_parse_belongs_to(ctx, attrs, data, (struct lysp_submodule *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002714 break;
2715 case YANG_BIT:
David Sedlák43801c92019-08-05 15:58:54 +02002716 ret = yin_parse_bit(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002717 break;
2718 case YANG_CASE:
David Sedlák5379d392019-07-24 10:42:03 +02002719 ret = yin_parse_case(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002720 break;
2721 case YANG_CHOICE:
David Sedlákb7abcfa2019-07-24 12:33:35 +02002722 ret = yin_parse_choice(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002723 break;
2724 case YANG_CONFIG:
David Sedlák1af868e2019-07-17 17:03:14 +02002725 ret = yin_parse_config(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002726 break;
2727 case YANG_CONTACT:
David Sedlák619db942019-07-03 14:47:30 +02002728 case YANG_DESCRIPTION:
2729 case YANG_ORGANIZATION:
2730 case YANG_REFERENCE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002731 ret = yin_parse_meta_element(ctx, attrs, data, kw, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002732 break;
2733 case YANG_CONTAINER:
David Sedlákf111bcb2019-07-23 17:15:51 +02002734 ret = yin_parse_container(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002735 break;
2736 case YANG_DEFAULT:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002737 if (subelem->flags & YIN_SUBELEM_UNIQUE) {
2738 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
2739 YIN_ARG_VALUE, Y_STR_ARG, exts);
2740 } else {
2741 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
2742 YIN_ARG_VALUE, Y_STR_ARG, exts);
2743 }
David Sedlákd6e56892019-07-01 15:40:24 +02002744 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002745 case YANG_DEVIATE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002746 ret = yin_parse_deviate(ctx, attrs, data, (struct lysp_deviate **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002747 break;
2748 case YANG_DEVIATION:
David Sedlák8b754462019-07-25 16:22:13 +02002749 ret = yin_parse_deviation(ctx, attrs, data, (struct lysp_deviation **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002750 break;
David Sedlák43801c92019-08-05 15:58:54 +02002751 case YANG_ENUM:
2752 ret = yin_parse_enum(ctx, attrs, data, (struct lysp_type *)subelem->dest);
2753 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002754 case YANG_ERROR_APP_TAG:
David Sedlák1af868e2019-07-17 17:03:14 +02002755 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002756 YIN_ARG_VALUE, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002757 break;
2758 case YANG_ERROR_MESSAGE:
David Sedlákdf2a9732019-08-07 13:23:16 +02002759 ret = yin_parse_err_msg_element(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002760 break;
2761 case YANG_EXTENSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002762 ret = yin_parse_extension(ctx, attrs, data, (struct lysp_ext **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002763 break;
2764 case YANG_FEATURE:
David Sedlák5e13dea2019-07-22 16:06:45 +02002765 ret = yin_parse_feature(ctx, attrs, data, (struct lysp_feature **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002766 break;
2767 case YANG_FRACTION_DIGITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002768 ret = yin_parse_fracdigits(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002769 break;
2770 case YANG_GROUPING:
David Sedláke3ce9ef2019-07-23 16:34:30 +02002771 ret = yin_parse_grouping(ctx, attrs, data, (struct grouping_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002772 break;
2773 case YANG_IDENTITY:
David Sedlák28794f22019-07-22 16:45:00 +02002774 ret = yin_parse_identity(ctx, attrs, data, (struct lysp_ident **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002775 break;
2776 case YANG_IF_FEATURE:
David Sedlák1af868e2019-07-17 17:03:14 +02002777 ret = yin_parse_simple_elements(ctx, attrs, data, kw,
2778 (const char ***)subelem->dest, YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002779 break;
2780 case YANG_IMPORT:
David Sedlák298ff6d2019-07-26 14:29:03 +02002781 ret = yin_parse_import(ctx, attrs, data, (struct import_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002782 break;
2783 case YANG_INCLUDE:
David Sedlák0c2bab92019-07-22 15:33:19 +02002784 ret = yin_parse_include(ctx, attrs, data, (struct include_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002785 break;
2786 case YANG_INPUT:
David Sedlák05404f62019-07-24 14:11:53 +02002787 case YANG_OUTPUT:
2788 ret = yin_parse_inout(ctx, attrs, data, kw, (struct inout_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002789 break;
2790 case YANG_KEY:
David Sedlák12470a82019-07-19 13:44:36 +02002791 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2792 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002793 break;
2794 case YANG_LEAF:
David Sedlák203ca3a2019-07-18 15:26:25 +02002795 ret = yin_parse_leaf(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002796 break;
2797 case YANG_LEAF_LIST:
David Sedlákc3da3ef2019-07-19 12:56:08 +02002798 ret = yin_parse_leaflist(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002799 break;
2800 case YANG_LENGTH:
David Sedlák1af868e2019-07-17 17:03:14 +02002801 type = (struct lysp_type *)subelem->dest;
David Sedlák438ae432019-07-11 15:36:54 +02002802 type->length = calloc(1, sizeof *type->length);
2803 LY_CHECK_ERR_GOTO(!type->length, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002804 ret = yin_parse_restriction(ctx, attrs, data, kw, type->length);
David Sedlák438ae432019-07-11 15:36:54 +02002805 type->flags |= LYS_SET_LENGTH;
David Sedlákd6e56892019-07-01 15:40:24 +02002806 break;
2807 case YANG_LIST:
David Sedlákaf536aa2019-07-23 13:42:23 +02002808 ret = yin_parse_list(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002809 break;
2810 case YANG_MANDATORY:
David Sedlák1af868e2019-07-17 17:03:14 +02002811 ret = yin_parse_mandatory(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002812 break;
2813 case YANG_MAX_ELEMENTS:
David Sedlákd6e56892019-07-01 15:40:24 +02002814 case YANG_MIN_ELEMENTS:
David Sedlák09e18c92019-07-18 11:17:11 +02002815 ret = yin_parse_minmax(ctx, attrs, data, current_element, kw, subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002816 break;
2817 case YANG_MODIFIER:
David Sedlák1af868e2019-07-17 17:03:14 +02002818 ret = yin_parse_modifier(ctx, attrs, data, (const char **)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002819 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002820 case YANG_MUST:
David Sedlák1af868e2019-07-17 17:03:14 +02002821 ret = yin_parse_must(ctx, attrs, data, (struct lysp_restr **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002822 break;
2823 case YANG_NAMESPACE:
David Sedlák1af868e2019-07-17 17:03:14 +02002824 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedlák2ce1be62019-07-10 16:15:09 +02002825 YIN_ARG_URI, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002826 break;
2827 case YANG_NOTIFICATION:
David Sedlák031b9e72019-07-23 15:19:37 +02002828 ret = yin_parse_notification(ctx, attrs, data, (struct notif_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002829 break;
2830 case YANG_ORDERED_BY:
David Sedláka2dad212019-07-18 12:45:19 +02002831 ret = yin_parse_orderedby(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002832 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002833 case YANG_PATH:
David Sedlák1af868e2019-07-17 17:03:14 +02002834 type = (struct lysp_type *)subelem->dest;
2835 ret = yin_parse_simple_element(ctx, attrs, data, kw, &type->path,
David Sedlákd1144562019-08-06 12:36:14 +02002836 YIN_ARG_VALUE, Y_STR_ARG, &type->exts);
David Sedlák58979872019-07-12 11:42:43 +02002837 type->flags |= LYS_SET_PATH;
David Sedlákd6e56892019-07-01 15:40:24 +02002838 break;
2839 case YANG_PATTERN:
David Sedlák1af868e2019-07-17 17:03:14 +02002840 ret = yin_parse_pattern(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002841 break;
David Sedlák5545f5d2019-07-11 11:55:16 +02002842 case YANG_VALUE:
David Sedlákd6e56892019-07-01 15:40:24 +02002843 case YANG_POSITION:
David Sedlák1af868e2019-07-17 17:03:14 +02002844 ret = yin_parse_value_pos_element(ctx, attrs, data, kw,
2845 (struct lysp_type_enum *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002846 break;
2847 case YANG_PREFIX:
David Sedlák1af868e2019-07-17 17:03:14 +02002848 ret = yin_parse_simple_element(ctx, attrs, data, kw,
2849 (const char **)subelem->dest, YIN_ARG_VALUE, Y_IDENTIF_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002850 break;
2851 case YANG_PRESENCE:
David Sedlákcb39f642019-07-19 13:19:55 +02002852 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest, YIN_ARG_VALUE,
2853 Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002854 break;
2855 case YANG_RANGE:
David Sedlák1af868e2019-07-17 17:03:14 +02002856 type = (struct lysp_type *)subelem->dest;
David Sedlákb7296dd2019-07-11 14:58:38 +02002857 type->range = calloc(1, sizeof *type->range);
David Sedlák66d7c842019-07-11 15:06:04 +02002858 LY_CHECK_ERR_GOTO(!type->range, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002859 ret = yin_parse_restriction(ctx, attrs, data, kw, type->range);
David Sedlák438ae432019-07-11 15:36:54 +02002860 type->flags |= LYS_SET_RANGE;
David Sedlákd6e56892019-07-01 15:40:24 +02002861 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002862 case YANG_REFINE:
David Sedlákd2d676a2019-07-22 11:28:19 +02002863 ret = yin_parse_refine(ctx, attrs, data, (struct lysp_refine **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002864 break;
2865 case YANG_REQUIRE_INSTANCE:
David Sedlák1af868e2019-07-17 17:03:14 +02002866 ret = yin_pasrse_reqinstance(ctx, attrs, data, (struct lysp_type *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002867 break;
2868 case YANG_REVISION:
David Sedlákaa854b02019-07-22 14:17:10 +02002869 ret = yin_parse_revision(ctx, attrs, data, (struct lysp_revision **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002870 break;
2871 case YANG_REVISION_DATE:
David Sedlák1af868e2019-07-17 17:03:14 +02002872 ret = yin_parse_revision_date(ctx, attrs, data, (char *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002873 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002874 case YANG_STATUS:
David Sedlák1af868e2019-07-17 17:03:14 +02002875 ret = yin_parse_status(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002876 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002877 case YANG_TYPE:
David Sedlák4ffcec82019-07-25 15:10:21 +02002878 if (current_element == YANG_DEVIATE) {
2879 *(struct lysp_type **)subelem->dest = calloc(1, sizeof **(struct lysp_type **)subelem->dest);
2880 LY_CHECK_ERR_GOTO(!(*(struct lysp_type **)subelem->dest), LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
2881 type = *((struct lysp_type **)subelem->dest);
2882 } else {
2883 type = (struct lysp_type *)subelem->dest;
2884 }
David Sedlák374d2b32019-07-17 15:06:55 +02002885 /* type as child of another type */
David Sedlák374d2b32019-07-17 15:06:55 +02002886 if (current_element == YANG_TYPE) {
2887 LY_ARRAY_NEW_GOTO(ctx->xml_ctx.ctx, type->types, nested_type, ret, cleanup);
David Sedlákc3da3ef2019-07-19 12:56:08 +02002888 type->flags |= LYS_SET_TYPE;
David Sedlák374d2b32019-07-17 15:06:55 +02002889 type = nested_type;
2890 }
David Sedlák1af868e2019-07-17 17:03:14 +02002891 ret = yin_parse_type(ctx, attrs, data, type);
David Sedlákd6e56892019-07-01 15:40:24 +02002892 break;
2893 case YANG_TYPEDEF:
David Sedlák04e17b22019-07-19 15:29:48 +02002894 ret = yin_parse_typedef(ctx, attrs, data, (struct typedef_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002895 break;
2896 case YANG_UNIQUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002897 ret = yin_parse_simple_elements(ctx, attrs, data, kw, (const char ***)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002898 YIN_ARG_TAG, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002899 break;
2900 case YANG_UNITS:
David Sedlák1af868e2019-07-17 17:03:14 +02002901 ret = yin_parse_simple_element(ctx, attrs, data, kw, (const char **)subelem->dest,
David Sedláka5b1d382019-07-10 16:31:09 +02002902 YIN_ARG_NAME, Y_STR_ARG, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002903 break;
2904 case YANG_USES:
David Sedlák0d6de5a2019-07-22 13:25:44 +02002905 ret = yin_parse_uses(ctx, attrs, data, (struct tree_node_meta *)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002906 break;
David Sedlákd6e56892019-07-01 15:40:24 +02002907 case YANG_WHEN:
David Sedlák1af868e2019-07-17 17:03:14 +02002908 ret = yin_parse_when(ctx, attrs, data, (struct lysp_when **)subelem->dest);
David Sedlákd6e56892019-07-01 15:40:24 +02002909 break;
2910 case YANG_YANG_VERSION:
David Sedlák1af868e2019-07-17 17:03:14 +02002911 ret = yin_parse_yangversion(ctx, attrs, data, (uint8_t *)subelem->dest, exts);
David Sedlákd6e56892019-07-01 15:40:24 +02002912 break;
2913 case YANG_YIN_ELEMENT:
David Sedlák1af868e2019-07-17 17:03:14 +02002914 ret = yin_parse_yin_element_element(ctx, attrs, data, (uint16_t *)subelem->dest, exts);
David Sedlák3ffbc522019-07-02 17:49:28 +02002915 break;
2916 case YIN_TEXT:
David Sedlák3ffbc522019-07-02 17:49:28 +02002917 case YIN_VALUE:
David Sedlák1af868e2019-07-17 17:03:14 +02002918 ret = yin_parse_content(ctx, NULL, 0, data, kw, (const char **)subelem->dest, NULL);
David Sedlákd6e56892019-07-01 15:40:24 +02002919 break;
2920 default:
David Sedlákda8ffa32019-07-08 14:17:10 +02002921 LOGINT(ctx->xml_ctx.ctx);
David Sedlák21f87cd2019-07-03 16:53:23 +02002922 return LY_EINT;
David Sedlákd6e56892019-07-01 15:40:24 +02002923 }
David Sedlák3ffbc522019-07-02 17:49:28 +02002924 LY_CHECK_GOTO(ret, cleanup);
David Sedlák1af868e2019-07-17 17:03:14 +02002925 FREE_ARRAY(ctx, attrs, free_arg_rec);
2926 attrs = NULL;
2927 subelem = NULL;
David Sedlákd6e56892019-07-01 15:40:24 +02002928 }
2929 } else {
2930 /* elements with text or none content */
David Sedlák3ffbc522019-07-02 17:49:28 +02002931 /* save text content, if text_content isn't set, it's just ignored */
David Sedlák4ffcec82019-07-25 15:10:21 +02002932 /* no resources are allocated in this branch so no need to use cleanup label */
David Sedlák3b4df842019-07-17 11:39:46 +02002933 LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG, out, out_len));
David Sedlák3ffbc522019-07-02 17:49:28 +02002934 if (text_content) {
2935 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002936 *text_content = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák3ffbc522019-07-02 17:49:28 +02002937 if (!*text_content) {
2938 free(out);
2939 return LY_EMEM;
2940 }
2941 } else {
2942 if (out_len == 0) {
David Sedlák99295322019-07-17 11:34:18 +02002943 *text_content = lydict_insert(ctx->xml_ctx.ctx, "", 0);
David Sedlák3ffbc522019-07-02 17:49:28 +02002944 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02002945 *text_content = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák3ffbc522019-07-02 17:49:28 +02002946 }
2947 }
2948 }
David Sedlákd6e56892019-07-01 15:40:24 +02002949 /* load closing element */
David Sedlákda8ffa32019-07-08 14:17:10 +02002950 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix.value, &prefix.len, &name.value, &name.len));
David Sedlákd6e56892019-07-01 15:40:24 +02002951 }
2952 }
David Sedlák8b754462019-07-25 16:22:13 +02002953 /* mandatory subelemnts are checked only after whole element was succesfully parsed */
2954 LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, current_element));
David Sedlákd6e56892019-07-01 15:40:24 +02002955
2956cleanup:
David Sedlák1af868e2019-07-17 17:03:14 +02002957 FREE_ARRAY(ctx, attrs, free_arg_rec);
David Sedlákd6e56892019-07-01 15:40:24 +02002958 return ret;
2959}
2960
David Sedlák619db942019-07-03 14:47:30 +02002961LY_ERR
David Sedlák1f90d252019-07-10 17:09:32 +02002962yin_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 +02002963 int ext_name_len, LYEXT_SUBSTMT subelem, uint32_t subelem_index, struct lysp_ext_instance **exts)
David Sedlák1e2cdd02019-06-27 14:17:43 +02002964{
2965 LY_ERR ret = LY_SUCCESS;
David Sedlákb1a78352019-06-28 16:16:29 +02002966 char *out;
2967 const char *name, *prefix;
2968 size_t out_len, prefix_len, name_len;
2969 int dynamic;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002970 struct lysp_ext_instance *e;
David Sedlákb1a78352019-06-28 16:16:29 +02002971 struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
2972 struct yin_arg_record *iter;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002973
David Sedlákda8ffa32019-07-08 14:17:10 +02002974 LY_ARRAY_NEW_RET(ctx->xml_ctx.ctx, *exts, e, LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02002975
2976 e->yin = 0;
2977 /* store name and insubstmt info */
David Sedlákda8ffa32019-07-08 14:17:10 +02002978 e->name = lydict_insert(ctx->xml_ctx.ctx, ext_name, ext_name_len);
David Sedlák619db942019-07-03 14:47:30 +02002979 e->insubstmt = subelem;
2980 e->insubstmt_index = subelem_index;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002981 e->yin |= LYS_YIN;
2982
David Sedlákb1a78352019-06-28 16:16:29 +02002983 /* store attributes as subelements */
David Sedlák1f90d252019-07-10 17:09:32 +02002984 LY_ARRAY_FOR_ITER(attrs, struct yin_arg_record, iter) {
David Sedlákb1a78352019-06-28 16:16:29 +02002985 if (!iter->prefix) {
2986 new_subelem = calloc(1, sizeof(*new_subelem));
2987 if (!e->child) {
2988 e->child = new_subelem;
David Sedlák1e2cdd02019-06-27 14:17:43 +02002989 } else {
David Sedlákb1a78352019-06-28 16:16:29 +02002990 last_subelem->next = new_subelem;
2991 }
2992 last_subelem = new_subelem;
2993
2994 last_subelem->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02002995 last_subelem->stmt = lydict_insert(ctx->xml_ctx.ctx, iter->name, iter->name_len);
2996 LY_CHECK_ERR_RET(!last_subelem->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02002997 if (iter->dynamic_content) {
David Sedlákda8ffa32019-07-08 14:17:10 +02002998 last_subelem->arg = lydict_insert_zc(ctx->xml_ctx.ctx, iter->content);
2999 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003000 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003001 last_subelem->arg = lydict_insert(ctx->xml_ctx.ctx, iter->content, iter->content_len);
3002 LY_CHECK_ERR_RET(!last_subelem->arg, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003003 }
3004 }
3005 }
David Sedlák1e2cdd02019-06-27 14:17:43 +02003006
David Sedlákf250ecf2019-07-01 11:02:05 +02003007 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003008 if (ctx->xml_ctx.status == LYXML_ELEM_CONTENT) {
3009 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003010 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003011 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
3012 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákb1a78352019-06-28 16:16:29 +02003013 if (!name) {
3014 /* end of extension instance reached */
3015 break;
3016 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003017 LY_CHECK_RET(yin_parse_element_generic(ctx, name, name_len, data, &new_subelem));
David Sedlákb1a78352019-06-28 16:16:29 +02003018 if (!e->child) {
3019 e->child = new_subelem;
3020 } else {
3021 last_subelem->next = new_subelem;
3022 }
3023 last_subelem = new_subelem;
3024 }
David Sedlák555c7202019-07-04 12:14:12 +02003025 } else {
3026 /* save text content */
3027 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003028 e->argument = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák555c7202019-07-04 12:14:12 +02003029 if (!e->argument) {
3030 free(out);
3031 return LY_EMEM;
3032 }
3033 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003034 e->argument = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
David Sedlák555c7202019-07-04 12:14:12 +02003035 LY_CHECK_RET(!e->argument, LY_EMEM);
3036 }
David Sedlákda8ffa32019-07-08 14:17:10 +02003037 LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlák555c7202019-07-04 12:14:12 +02003038 LY_CHECK_RET(name, LY_EINT);
David Sedlákb1a78352019-06-28 16:16:29 +02003039 }
David Sedlákb1a78352019-06-28 16:16:29 +02003040 }
3041
3042 return LY_SUCCESS;
3043}
3044
3045LY_ERR
David Sedlák4ffcec82019-07-25 15:10:21 +02003046yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char **data,
3047 struct lysp_stmt **element)
David Sedlákb1a78352019-06-28 16:16:29 +02003048{
3049 LY_ERR ret = LY_SUCCESS;
3050 const char *temp_prefix, *temp_name;
3051 char *out = NULL;
David Sedlák4ffcec82019-07-25 15:10:21 +02003052 size_t out_len, temp_name_len, temp_prefix_len, prefix_len;
David Sedlákb1a78352019-06-28 16:16:29 +02003053 int dynamic;
3054 struct yin_arg_record *subelem_args = NULL;
3055 struct lysp_stmt *last = NULL, *new = NULL;
3056
3057 /* allocate new structure for element */
3058 *element = calloc(1, sizeof(**element));
David Sedlákda8ffa32019-07-08 14:17:10 +02003059 (*element)->stmt = lydict_insert(ctx->xml_ctx.ctx, name, name_len);
3060 LY_CHECK_ERR_RET(!(*element)->stmt, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
David Sedlákb1a78352019-06-28 16:16:29 +02003061
3062 last = (*element)->child;
David Sedlákf250ecf2019-07-01 11:02:05 +02003063 /* load attributes */
David Sedlákda8ffa32019-07-08 14:17:10 +02003064 while(ctx->xml_ctx.status == LYXML_ATTRIBUTE) {
David Sedlákb1a78352019-06-28 16:16:29 +02003065 /* add new element to linked-list */
3066 new = calloc(1, sizeof(*last));
David Sedlákda8ffa32019-07-08 14:17:10 +02003067 LY_CHECK_ERR_GOTO(ret, LOGMEM(ctx->xml_ctx.ctx), err);
David Sedlákb1a78352019-06-28 16:16:29 +02003068 if (!(*element)->child) {
3069 /* save first */
3070 (*element)->child = new;
3071 } else {
3072 last->next = new;
3073 }
3074 last = new;
3075
3076 last->flags |= LYS_YIN_ATTR;
David Sedlákda8ffa32019-07-08 14:17:10 +02003077 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 +02003078 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003079 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003080 LY_CHECK_GOTO(ret, err);
David Sedlákda8ffa32019-07-08 14:17:10 +02003081 last->stmt = lydict_insert(ctx->xml_ctx.ctx, temp_name, temp_name_len);
3082 LY_CHECK_ERR_GOTO(!last->stmt, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003083 /* attributes with prefix are ignored */
3084 if (!temp_prefix) {
3085 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003086 last->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlákb1a78352019-06-28 16:16:29 +02003087 if (!last->arg) {
3088 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003089 LOGMEM(ctx->xml_ctx.ctx);
David Sedlákb1a78352019-06-28 16:16:29 +02003090 ret = LY_EMEM;
3091 goto err;
3092 }
3093 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003094 last->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3095 LY_CHECK_ERR_GOTO(!last->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003096 }
3097 }
3098 }
3099
3100 /* parse content of element */
David Sedlákda8ffa32019-07-08 14:17:10 +02003101 ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb1a78352019-06-28 16:16:29 +02003102 if (ret == LY_EINVAL) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003103 while (ctx->xml_ctx.status == LYXML_ELEMENT) {
David Sedlákb1a78352019-06-28 16:16:29 +02003104 /* parse subelements */
David Sedlákda8ffa32019-07-08 14:17:10 +02003105 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 +02003106 LY_CHECK_GOTO(ret, err);
3107 if (!name) {
3108 /* end of element reached */
3109 break;
3110 }
David Sedlák4ffcec82019-07-25 15:10:21 +02003111 ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, data, &last->next);
David Sedlákb1a78352019-06-28 16:16:29 +02003112 LY_CHECK_GOTO(ret, err);
3113 last = last->next;
3114 }
3115 } else {
3116 /* save element content */
David Sedlák5392a212019-07-01 09:19:10 +02003117 if (out_len != 0) {
3118 if (dynamic) {
David Sedlákda8ffa32019-07-08 14:17:10 +02003119 (*element)->arg = lydict_insert_zc(ctx->xml_ctx.ctx, out);
David Sedlák5392a212019-07-01 09:19:10 +02003120 if (!(*element)->arg) {
3121 free(out);
David Sedlákda8ffa32019-07-08 14:17:10 +02003122 LOGMEM(ctx->xml_ctx.ctx);
David Sedlák5392a212019-07-01 09:19:10 +02003123 ret = LY_EMEM;
3124 goto err;
3125 }
3126 } else {
David Sedlákda8ffa32019-07-08 14:17:10 +02003127 (*element)->arg = lydict_insert(ctx->xml_ctx.ctx, out, out_len);
3128 LY_CHECK_ERR_GOTO(!(*element)->arg, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, err);
David Sedlákb1a78352019-06-28 16:16:29 +02003129 }
David Sedlákb1a78352019-06-28 16:16:29 +02003130 }
3131 /* read closing tag */
David Sedlákda8ffa32019-07-08 14:17:10 +02003132 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 +02003133 LY_CHECK_GOTO(ret, err);
3134 }
3135
David Sedlákda8ffa32019-07-08 14:17:10 +02003136 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlákb1a78352019-06-28 16:16:29 +02003137 return LY_SUCCESS;
3138
3139err:
David Sedlákda8ffa32019-07-08 14:17:10 +02003140 FREE_ARRAY(ctx, subelem_args, free_arg_rec);
David Sedlák1e2cdd02019-06-27 14:17:43 +02003141 return ret;
3142}
3143
3144LY_ERR
David Sedlák4f03b932019-07-26 13:01:47 +02003145yin_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 +02003146{
David Sedlák4f03b932019-07-26 13:01:47 +02003147 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, YANG_MODULE));
3148 struct tree_node_meta node_meta = {NULL, &mod->data};
3149 struct augment_meta aug_meta = {NULL, &mod->augments};
3150 struct grouping_meta grp_meta = {NULL, &mod->groupings};
3151 struct include_meta inc_meta = {mod->mod->name, &mod->includes};
3152 struct notif_meta notif_meta = {NULL, &mod->notifs};
3153 struct action_meta act_meta = {NULL, &mod->rpcs};
3154 struct typedef_meta tpdf_meta = {NULL, &mod->typedefs};
David Sedlák298ff6d2019-07-26 14:29:03 +02003155 struct import_meta imp_meta = {mod->mod->prefix, &mod->imports};
David Sedlák4f03b932019-07-26 13:01:47 +02003156 struct yin_subelement subelems[28] = {
3157 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3158 {YANG_ANYXML, &node_meta, 0},
3159 {YANG_AUGMENT, &aug_meta, 0},
3160 {YANG_CHOICE, &node_meta, 0},
3161 {YANG_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE},
3162 {YANG_CONTAINER, &node_meta, 0},
3163 {YANG_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE},
3164 {YANG_DEVIATION, &mod->deviations, 0},
3165 {YANG_EXTENSION, &mod->extensions, 0},
3166 {YANG_FEATURE, &mod->features, 0},
3167 {YANG_GROUPING, &grp_meta, 0},
3168 {YANG_IDENTITY, &mod->identities, 0},
David Sedlák298ff6d2019-07-26 14:29:03 +02003169 {YANG_IMPORT, &imp_meta, 0},
David Sedlák4f03b932019-07-26 13:01:47 +02003170 {YANG_INCLUDE, &inc_meta, 0},
3171 {YANG_LEAF, &node_meta, 0},
3172 {YANG_LEAF_LIST, &node_meta, 0},
3173 {YANG_LIST, &node_meta, 0},
3174 {YANG_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3175 {YANG_NOTIFICATION, &notif_meta, 0},
3176 {YANG_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE},
3177 {YANG_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3178 {YANG_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE},
3179 {YANG_REVISION, &mod->revs, 0},
3180 {YANG_RPC, &act_meta, 0},
3181 {YANG_TYPEDEF, &tpdf_meta, 0},
3182 {YANG_USES, &node_meta, 0},
3183 {YANG_YANG_VERSION, &mod->mod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
David Sedlák968ac342019-07-11 15:17:59 +02003184 {YANG_CUSTOM, NULL, 0}
David Sedlák4f03b932019-07-26 13:01:47 +02003185 };
David Sedlák3b4db242018-10-19 16:11:01 +02003186
David Sedlák4f03b932019-07-26 13:01:47 +02003187 return yin_parse_content(ctx, subelems, 28, data, YANG_MODULE, NULL, &mod->exts);
David Sedlák3b4db242018-10-19 16:11:01 +02003188}
3189
3190LY_ERR
David Sedlák298ff6d2019-07-26 14:29:03 +02003191yin_parse_submod(struct yin_parser_ctx *ctx, struct yin_arg_record *mod_attrs, const char **data, struct lysp_submodule *submod)
3192{
3193 LY_CHECK_RET(yin_parse_attribute(ctx, mod_attrs, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, YANG_SUBMODULE));
3194 struct tree_node_meta node_meta = {NULL, &submod->data};
3195 struct augment_meta aug_meta = {NULL, &submod->augments};
3196 struct grouping_meta grp_meta = {NULL, &submod->groupings};
3197 struct include_meta inc_meta = {submod->name, &submod->includes};
3198 struct notif_meta notif_meta = {NULL, &submod->notifs};
3199 struct action_meta act_meta = {NULL, &submod->rpcs};
3200 struct typedef_meta tpdf_meta = {NULL, &submod->typedefs};
3201 struct import_meta imp_meta = {submod->prefix, &submod->imports};
3202 struct yin_subelement subelems[27] = {
3203 {YANG_ANYDATA, &node_meta, YIN_SUBELEM_VER2},
3204 {YANG_ANYXML, &node_meta, 0},
3205 {YANG_AUGMENT, &aug_meta, 0},
3206 {YANG_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3207 {YANG_CHOICE, &node_meta, 0},
3208 {YANG_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE},
3209 {YANG_CONTAINER, &node_meta, 0},
3210 {YANG_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE},
3211 {YANG_DEVIATION, &submod->deviations, 0},
3212 {YANG_EXTENSION, &submod->extensions, 0},
3213 {YANG_FEATURE, &submod->features, 0},
3214 {YANG_GROUPING, &grp_meta, 0},
3215 {YANG_IDENTITY, &submod->identities, 0},
3216 {YANG_IMPORT, &imp_meta, 0},
3217 {YANG_INCLUDE, &inc_meta, 0},
3218 {YANG_LEAF, &node_meta, 0},
3219 {YANG_LEAF_LIST, &node_meta, 0},
3220 {YANG_LIST, &node_meta, 0},
3221 {YANG_NOTIFICATION, &notif_meta, 0},
3222 {YANG_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE},
3223 {YANG_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE},
3224 {YANG_REVISION, &submod->revs, 0},
3225 {YANG_RPC, &act_meta, 0},
3226 {YANG_TYPEDEF, &tpdf_meta, 0},
3227 {YANG_USES, &node_meta, 0},
3228 {YANG_YANG_VERSION, &submod->version, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
3229 {YANG_CUSTOM, NULL, 0}
3230 };
3231
3232 return yin_parse_content(ctx, subelems, 27, data, YANG_SUBMODULE, NULL, &submod->exts);
3233}
3234
3235LY_ERR
David Sedlák1b623122019-08-05 15:27:49 +02003236yin_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 +02003237{
3238 enum yang_keyword kw = YANG_NONE;
3239 LY_ERR ret = LY_SUCCESS;
3240 const char *prefix, *name;
3241 size_t prefix_len, name_len;
3242 struct yin_arg_record *attrs = NULL;
3243 struct lysp_submodule *mod_p = NULL;
3244
3245 /* create context */
3246 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003247 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003248 (*yin_ctx)->xml_ctx.ctx = ctx;
3249 (*yin_ctx)->xml_ctx.line = 1;
3250
David Sedlák1b623122019-08-05 15:27:49 +02003251 /* map the typedefs and groupings list from main context to the submodule's context */
3252 memcpy(&(*yin_ctx)->tpdfs_nodes, &main_ctx->tpdfs_nodes, sizeof main_ctx->tpdfs_nodes);
3253 memcpy(&(*yin_ctx)->grps_nodes, &main_ctx->grps_nodes, sizeof main_ctx->grps_nodes);
3254
David Sedlák8985a142019-07-31 16:43:06 +02003255 /* check submodule */
3256 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3257 LY_CHECK_GOTO(ret, cleanup);
3258 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
3259 LY_CHECK_GOTO(ret, cleanup);
3260 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
3261
3262 if (kw == YANG_MODULE) {
3263 LOGERR(ctx, LY_EDENIED, "Input data contains module in situation when a submodule is expected.");
3264 ret = LY_EINVAL;
3265 goto cleanup;
3266 } else if (kw != YANG_SUBMODULE) {
3267 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
3268 ly_stmt2str(kw));
3269 ret = LY_EVALID;
3270 goto cleanup;
3271 }
3272
3273 mod_p = calloc(1, sizeof *mod_p);
3274 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
3275 mod_p->parsing = 1;
3276
3277 ret = yin_parse_submod(*yin_ctx, attrs, &data, mod_p);
3278 LY_CHECK_GOTO(ret, cleanup);
3279
David Sedlák6d781b62019-08-02 15:22:52 +02003280 name = NULL;
3281 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3282 const char *temp_data = data;
3283 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3284 data = temp_data;
3285 }
3286 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3287 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after submodule, expected end-of-input.",
3288 15, data, strlen(data) > 15 ? "..." : "");
3289 ret = LY_EVALID;
3290 goto cleanup;
3291 }
3292
David Sedlák8985a142019-07-31 16:43:06 +02003293 mod_p->parsing = 0;
3294 *submod = mod_p;
3295
3296cleanup:
3297 if (ret) {
3298 lysp_submodule_free(ctx, mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003299 yin_parser_ctx_free(*yin_ctx);
3300 *yin_ctx = NULL;
David Sedlák8985a142019-07-31 16:43:06 +02003301 }
3302
3303 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
3304 return ret;
3305}
3306
3307LY_ERR
3308yin_parse_module(struct yin_parser_ctx **yin_ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +02003309{
David Sedláke4889912018-11-02 09:52:40 +01003310 LY_ERR ret = LY_SUCCESS;
3311 enum yang_keyword kw = YANG_NONE;
David Sedlák3017da42019-02-15 09:48:04 +01003312 struct lysp_module *mod_p = NULL;
3313 const char *prefix, *name;
3314 size_t prefix_len, name_len;
David Sedlák1f90d252019-07-10 17:09:32 +02003315 struct yin_arg_record *attrs = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +02003316
David Sedlák8985a142019-07-31 16:43:06 +02003317 /* create context */
3318 *yin_ctx = calloc(1, sizeof **yin_ctx);
David Sedlák1b623122019-08-05 15:27:49 +02003319 LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
David Sedlák8985a142019-07-31 16:43:06 +02003320 (*yin_ctx)->xml_ctx.ctx = mod->ctx;
3321 (*yin_ctx)->xml_ctx.line = 1;
David Sedlákda8ffa32019-07-08 14:17:10 +02003322
David Sedlák8985a142019-07-31 16:43:06 +02003323 /* check module */
3324 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák00250342019-06-21 14:19:39 +02003325 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003326 ret = yin_load_attributes(*yin_ctx, &data, &attrs);
David Sedlák00250342019-06-21 14:19:39 +02003327 LY_CHECK_GOTO(ret, cleanup);
David Sedlák8985a142019-07-31 16:43:06 +02003328 kw = yin_match_keyword(*yin_ctx, name, name_len, prefix, prefix_len, YANG_NONE);
David Sedláke4889912018-11-02 09:52:40 +01003329 if (kw == YANG_SUBMODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003330 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 +01003331 ret = LY_EINVAL;
3332 goto cleanup;
3333 } else if (kw != YANG_MODULE) {
David Sedlák8985a142019-07-31 16:43:06 +02003334 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +02003335 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +01003336 ret = LY_EVALID;
3337 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +01003338 }
3339
David Sedlák3017da42019-02-15 09:48:04 +01003340 /* allocate module */
3341 mod_p = calloc(1, sizeof *mod_p);
David Sedlák8985a142019-07-31 16:43:06 +02003342 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
David Sedlák3017da42019-02-15 09:48:04 +01003343 mod_p->mod = mod;
3344 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +01003345
David Sedlák00250342019-06-21 14:19:39 +02003346 /* parse module substatements */
David Sedlák8985a142019-07-31 16:43:06 +02003347 ret = yin_parse_mod(*yin_ctx, attrs, &data, mod_p);
David Sedlák3017da42019-02-15 09:48:04 +01003348 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +01003349
David Sedlák1b623122019-08-05 15:27:49 +02003350 /* check trailing characters */
David Sedlák6d781b62019-08-02 15:22:52 +02003351 if ((*yin_ctx)->xml_ctx.status == LYXML_ELEMENT) {
3352 ret = lyxml_get_element(&(*yin_ctx)->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
3353 }
3354 if ((*yin_ctx)->xml_ctx.status != LYXML_END || name) {
3355 LOGVAL_PARSER((struct lys_parser_ctx *)*yin_ctx, LYVE_SYNTAX, "Trailing garbage \"%.*s%s\" after module, expected end-of-input.",
3356 15, data, strlen(data) > 15 ? "..." : "");
3357
3358 ret = LY_EVALID;
3359 goto cleanup;
3360 }
3361
David Sedlák3017da42019-02-15 09:48:04 +01003362 mod_p->parsing = 0;
3363 mod->parsed = mod_p;
3364
3365cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +02003366 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +01003367 lysp_module_free(mod_p);
David Sedlák1b623122019-08-05 15:27:49 +02003368 yin_parser_ctx_free(*yin_ctx);
3369 *yin_ctx = NULL;
David Sedlák3017da42019-02-15 09:48:04 +01003370 }
David Sedlák8985a142019-07-31 16:43:06 +02003371 FREE_ARRAY(*yin_ctx, attrs, free_arg_rec);
David Sedlák2e411422018-12-17 02:35:39 +01003372 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +02003373}