blob: 03241ef6a01d73a32b9fe5926e4a07689ad44e4c [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ák3b4db242018-10-19 16:11:01 +020016#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
David Sedlák872c7b42018-10-26 13:15:20 +020019#include <string.h>
David Sedlákf824ad52018-10-14 23:58:15 +020020
David Sedlákf824ad52018-10-14 23:58:15 +020021#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020022#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020023#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020024#include "tree.h"
25#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020026#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020027#include "parser_yin.h"
David Sedlák2b214ac2019-06-06 16:11:03 +020028/**
29 * @brief check if given string is URI of yin namespace.
30 * @param ns Namespace URI to check.
31 *
32 * @return true if ns equals YIN_NS_URI false otherwise.
33 */
34#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
35
David Sedlákf6251182019-06-06 10:22:13 +020036const char *const yin_attr_list[] = {
37 [YIN_ARG_NAME] = "name",
38 [YIN_ARG_TARGET_NODE] = "target-node",
39 [YIN_ARG_MODULE] = "module",
40 [YIN_ARG_VALUE] = "value",
41 [YIN_ARG_TEXT] = "text",
42 [YIN_ARG_CONDITION] = "condition",
43 [YIN_ARG_URI] = "uri",
44 [YIN_ARG_DATE] = "date",
45 [YIN_ARG_TAG] = "tag",
46 [YIN_ARG_XMLNS] = "xmlns",
47};
48
David Sedlákc8dd80e2019-06-19 16:08:48 +020049/**
50 * @brief check if keyword was matched properly,
51 * information about namespace is not always fully available when type of keyword is already needed
52 * this function retroactively checks if kw isn't actually extension instance or unknown element without namespace
53 *
54 * @param[in] xml_ctx Xml context.
55 * @param[in] prefix Keyword prefix.
56 * @param[in] prefix_len Length of prefix.
57 * @param[in,out] kw Type of keyword.
58 */
59void
60check_kw_ns(struct lyxml_context *xml_ctx, const char *prefix, size_t prefix_len, enum yang_keyword *kw)
61{
62 const struct lyxml_ns *ns = NULL;
63
64 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
65
66 if (!ns) {
67 *kw = YANG_NONE;
68 } else {
69 if (!IS_YIN_NS(ns->uri)) {
70 *kw = YANG_CUSTOM;
71 }
72 }
73}
74
David Sedlák1bccdfa2019-06-17 15:55:27 +020075enum yang_keyword
David Sedlák8f7a1172019-06-20 14:42:18 +020076yin_match_keyword(struct lyxml_context *xml_ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len)
David Sedlák1bccdfa2019-06-17 15:55:27 +020077{
David Sedlák8f7a1172019-06-20 14:42:18 +020078 const char *start = NULL;
79 enum yang_keyword kw = YANG_NONE;
80 const struct lyxml_ns *ns = NULL;
81
82 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020083 return YANG_NONE;
84 }
85
David Sedlák8f7a1172019-06-20 14:42:18 +020086 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
87 if (ns) {
88 if (!IS_YIN_NS(ns->uri)) {
89 return YANG_CUSTOM;
90 }
91 } else {
92 /* elements without namespace are automatically unknown */
93 return YANG_NONE;
94 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020095
David Sedlák8f7a1172019-06-20 14:42:18 +020096
97 start = name;
98 kw = lysp_match_kw(NULL, &name);
99
100 if (name - start == (long int)name_len) {
David Sedlák1bccdfa2019-06-17 15:55:27 +0200101 return kw;
102 } else {
103 return YANG_NONE;
104 }
105}
106
107
David Sedlák872c7b42018-10-26 13:15:20 +0200108enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +0200109yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200110{
David Sedláka7406952019-04-05 10:33:07 +0200111 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200112 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200113 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200114
David Sedlák94de2aa2019-02-15 12:42:11 +0100115#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
116#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100117#define IF_ARG_PREFIX_END }
118
David Sedlák1c8b2702019-02-22 11:03:02 +0100119 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +0100120 case 'x':
121 already_read += 1;
122 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
123 break;
David Sedlák94de2aa2019-02-15 12:42:11 +0100124 case 'c':
125 already_read += 1;
126 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200127 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200128
David Sedlák94de2aa2019-02-15 12:42:11 +0100129 case 'd':
130 already_read += 1;
131 IF_ARG("ate", 3, YIN_ARG_DATE);
David Sedlák3b4db242018-10-19 16:11:01 +0200132 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200133
David Sedlák94de2aa2019-02-15 12:42:11 +0100134 case 'm':
135 already_read += 1;
136 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200137 break;
138
David Sedlák94de2aa2019-02-15 12:42:11 +0100139 case 'n':
140 already_read += 1;
141 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200142 break;
143
David Sedlák94de2aa2019-02-15 12:42:11 +0100144 case 't':
145 already_read += 1;
146 IF_ARG_PREFIX("a", 1)
147 IF_ARG("g", 1, YIN_ARG_TAG)
148 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
149 IF_ARG_PREFIX_END
150 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200151 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200152
David Sedlák94de2aa2019-02-15 12:42:11 +0100153 case 'u':
154 already_read += 1;
155 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200156 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200157
David Sedlák94de2aa2019-02-15 12:42:11 +0100158 case 'v':
159 already_read += 1;
160 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200161 break;
162 }
163
David Sedlákc10e7902018-12-17 02:17:59 +0100164 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200165 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200166 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200167 }
168
David Sedlák18730132019-03-15 15:51:34 +0100169#undef IF_ARG
170#undef IF_ARG_PREFIX
171#undef IF_ARG_PREFIX_END
172
David Sedlák872c7b42018-10-26 13:15:20 +0200173 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200174}
175
David Sedlák8f7a1172019-06-20 14:42:18 +0200176LY_ERR
177yin_load_attributes(struct lyxml_context *xml_ctx, const char **data, struct yin_arg_record **args)
David Sedláka7406952019-04-05 10:33:07 +0200178{
179 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200180 struct yin_arg_record *argument_record = NULL;
David Sedláka7406952019-04-05 10:33:07 +0200181
David Sedlák7ff55a92019-06-17 11:11:41 +0200182 /* load all attributes first */
David Sedlák57715b12019-06-17 13:05:22 +0200183 while (xml_ctx->status == LYXML_ATTRIBUTE) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200184 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *args, argument_record, ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200185 ret = lyxml_get_attribute(xml_ctx, data, &argument_record->prefix, &argument_record->prefix_len,
186 &argument_record->name, &argument_record->name_len);
187 LY_CHECK_ERR_GOTO(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200188
David Sedlák7ff55a92019-06-17 11:11:41 +0200189 if (xml_ctx->status == LYXML_ATTR_CONTENT) {
David Sedlák57715b12019-06-17 13:05:22 +0200190 argument_record->content = NULL;
191 argument_record->content_len = 0;
192 argument_record->dynamic_content = 0;
193 ret = lyxml_get_string(xml_ctx, data, &argument_record->content, &argument_record->content_len,
194 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák7ff55a92019-06-17 11:11:41 +0200195 LY_CHECK_ERR_GOTO(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), cleanup);
196 }
197 }
198
David Sedlák8f7a1172019-06-20 14:42:18 +0200199cleanup:
200 if (ret != LY_SUCCESS) {
201 LY_ARRAY_FREE(*args);
202 }
203 return ret;
204}
205
206LY_ERR
207yin_parse_attribute(struct lyxml_context *xml_ctx, struct yin_arg_record **args, enum YIN_ARGUMENT arg_type, const char **arg_val)
208{
209 LY_ERR ret = LY_SUCCESS;
210 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
211 struct yin_arg_record *iter = NULL;
212 const struct lyxml_ns *ns = NULL;
213
David Sedlák1bccdfa2019-06-17 15:55:27 +0200214 /* validation of attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200215 LY_ARRAY_FOR(*args, struct yin_arg_record, iter) {
David Sedlák7ff55a92019-06-17 11:11:41 +0200216 ns = lyxml_ns_get(xml_ctx, iter->prefix, iter->prefix_len);
David Sedlák2b214ac2019-06-06 16:11:03 +0200217 if (ns && IS_YIN_NS(ns->uri)) {
David Sedlák060b00e2019-06-19 11:12:06 +0200218 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200219 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200220 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200221 } else if (arg == arg_type) {
David Sedlák57715b12019-06-17 13:05:22 +0200222 if (iter->dynamic_content) {
223 *arg_val = lydict_insert_zc(xml_ctx->ctx, iter->content);
224 } else {
225 *arg_val = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
226 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
227 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200228 } else {
David Sedlák57715b12019-06-17 13:05:22 +0200229 if (iter->dynamic_content) {
230 free(iter->content);
231 }
David Sedlák7ff55a92019-06-17 11:11:41 +0200232 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\".", iter->name_len, iter->name);
233 ret = LY_EVALID;
234 goto cleanup;
David Sedláka7406952019-04-05 10:33:07 +0200235 }
236 }
237 }
238
David Sedlák7ff55a92019-06-17 11:11:41 +0200239cleanup:
David Sedlák7ff55a92019-06-17 11:11:41 +0200240 return ret;
David Sedláka7406952019-04-05 10:33:07 +0200241}
242
David Sedlák0daba9a2019-03-22 14:07:49 +0100243LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200244yin_parse_text_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
David Sedlák0daba9a2019-03-22 14:07:49 +0100245{
246 LY_ERR ret = LY_SUCCESS;
247 char *buf = NULL, *out = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200248 const char *prefix = NULL, *name = NULL;
249 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200250 int dynamic = 0;
David Sedlák0daba9a2019-03-22 14:07:49 +0100251
David Sedlák8f7a1172019-06-20 14:42:18 +0200252 ret = yin_parse_attribute(xml_ctx, args, YIN_ARG_NONE, NULL);
David Sedlák68826732019-06-05 10:50:58 +0200253 LY_CHECK_RET(ret);
David Sedlák0daba9a2019-03-22 14:07:49 +0100254 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
255
256 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
257 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
258 LY_CHECK_RET(ret);
David Sedlák57715b12019-06-17 13:05:22 +0200259 if (dynamic) {
260 *value = lydict_insert_zc(xml_ctx->ctx, buf);
261 } else {
262 *value = lydict_insert(xml_ctx->ctx, out, out_len);
263 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
264 }
David Sedlák0daba9a2019-03-22 14:07:49 +0100265 }
266
David Sedlák15a92662019-06-18 11:55:15 +0200267 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
268 LY_CHECK_RET(ret);
269
270 return LY_SUCCESS;
271}
272
273/**
274 * @brief function to parse meta tags eg. elements with text element as child
275 *
276 * @param[in] xml_ctx Xml context.
David Sedlák8f7a1172019-06-20 14:42:18 +0200277 * @param[in] args Sized array of arguments of current elements.
David Sedlák15a92662019-06-18 11:55:15 +0200278 * @param[in,out] data Data to read from.
279 * @param[out] value Where the content of meta tag should be stored.
280 *
281 * @return LY_ERR values.
282 */
283LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200284yin_parse_meta_element(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, const char **value)
David Sedlák15a92662019-06-18 11:55:15 +0200285{
286 LY_ERR ret = LY_SUCCESS;
287 char *buf = NULL, *out = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200288 const char *prefix = NULL, *name = NULL, *content_start = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200289 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
290 int dynamic = 0;
David Sedlák15a92662019-06-18 11:55:15 +0200291 enum YIN_ARGUMENT arg = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200292 struct yin_arg_record *subelem_args = NULL;
293 enum yang_keyword kw = YANG_NONE;
David Sedlák15a92662019-06-18 11:55:15 +0200294
David Sedlák8f7a1172019-06-20 14:42:18 +0200295 ret = yin_parse_attribute(xml_ctx, args, YIN_ARG_NONE, NULL);
David Sedlák15a92662019-06-18 11:55:15 +0200296 LY_CHECK_RET(ret);
297 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
298
299 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200300 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected \"text\" element as child of meta element."), LY_EINVAL);
David Sedlák15a92662019-06-18 11:55:15 +0200301
David Sedlák8f7a1172019-06-20 14:42:18 +0200302 /* first element should be argument element <text> */
303 content_start = *data;
304 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
305 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &subelem_args));
306 arg = yin_match_argument_name(name, name_len);
307 if (arg == YIN_ARG_TEXT) {
308 yin_parse_text_element(xml_ctx, &subelem_args, data, value);
309 } else {
310 /* first element is not argument element, go back to start of element content and try to parse normal subelements */
311 *data = content_start;
312 }
313
David Sedlák15a92662019-06-18 11:55:15 +0200314 /* loop over all child elements and parse them */
315 while (xml_ctx->status == LYXML_ELEMENT) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200316 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
317 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &subelem_args));
318 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák15a92662019-06-18 11:55:15 +0200319
David Sedlák8f7a1172019-06-20 14:42:18 +0200320 if (!name) {
David Sedlák15a92662019-06-18 11:55:15 +0200321 /* end of meta element reached */
322 break;
323 }
324
David Sedlák8f7a1172019-06-20 14:42:18 +0200325 switch (kw) {
326 case YANG_CUSTOM:
327 // TODO parse extension instance
328 break;
329
330 default:
331 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
332 return LY_EVALID;
333 }
David Sedlák15a92662019-06-18 11:55:15 +0200334 }
335
David Sedlák6b7ac2d2019-03-22 14:40:29 +0100336 return LY_SUCCESS;
David Sedlák0daba9a2019-03-22 14:07:49 +0100337}
338
David Sedlákb666bcc2019-06-05 15:00:05 +0200339/**
David Sedlák2b214ac2019-06-06 16:11:03 +0200340 * @brief Parse revision date.
David Sedlákb666bcc2019-06-05 15:00:05 +0200341 *
342 * @param[in] xml_ctx Xml context.
David Sedlák8f7a1172019-06-20 14:42:18 +0200343 * @param[in] args Sized array of arguments of current element.
David Sedlákb666bcc2019-06-05 15:00:05 +0200344 * @param[in,out] data Data to read from.
345 * @param[in,out] rev Array to store the parsed value in.
346 * @param[in,out] exts Extension instances to add to.
347 *
David Sedlák2b214ac2019-06-06 16:11:03 +0200348 * @return LY_ERR values.
David Sedlákb666bcc2019-06-05 15:00:05 +0200349 */
David Sedlák81e04022019-04-05 15:05:46 +0200350static LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200351yin_parse_revision_date(struct lyxml_context *xml_ctx, struct yin_arg_record **args, const char **data, char *rev, struct lysp_ext_instance **exts)
David Sedlák81e04022019-04-05 15:05:46 +0200352{
353 LY_ERR ret = LY_SUCCESS;
David Sedlákda63c082019-06-04 13:52:23 +0200354 const char *temp_rev;
David Sedlákcd0c9512019-03-29 13:23:06 +0100355
David Sedlák81e04022019-04-05 15:05:46 +0200356 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200357 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
David Sedlák81e04022019-04-05 15:05:46 +0200358 return LY_EVALID;
359 }
360
David Sedlák8f7a1172019-06-20 14:42:18 +0200361 LY_CHECK_RET(yin_parse_attribute(xml_ctx, args, YIN_ARG_DATE, &temp_rev))
David Sedlák81e04022019-04-05 15:05:46 +0200362 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákda63c082019-06-04 13:52:23 +0200363 LY_CHECK_RET(lysp_check_date((struct lys_parser_ctx *)xml_ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, LY_EVALID);
364
365 strcpy(rev, temp_rev);
366 lydict_remove(xml_ctx->ctx, temp_rev);
367 /* TODO extension */
David Sedlák81e04022019-04-05 15:05:46 +0200368
David Sedlák81e04022019-04-05 15:05:46 +0200369 return ret;
370}
David Sedlákcd0c9512019-03-29 13:23:06 +0100371
David Sedlákda63c082019-06-04 13:52:23 +0200372LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200373yin_parse_import(struct lyxml_context *xml_ctx, struct yin_arg_record **import_args, const char *module_prefix, const char **data, struct lysp_import **imports)
David Sedlák736fd0d2019-02-15 16:06:31 +0100374{
375 LY_ERR ret = LY_SUCCESS;
376 enum yang_keyword kw;
377 struct lysp_import *imp;
378 const char *prefix, *name;
David Sedlák8f7a1172019-06-20 14:42:18 +0200379 struct yin_arg_record *subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100380 size_t prefix_len, name_len;
381
David Sedlák81e04022019-04-05 15:05:46 +0200382 /* allocate sized array for imports */
David Sedlák8f7a1172019-06-20 14:42:18 +0200383 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *imports, imp, ret, validation_err);
David Sedlák736fd0d2019-02-15 16:06:31 +0100384
David Sedláka7406952019-04-05 10:33:07 +0200385 /* parse import attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200386 LY_CHECK_GOTO((ret = yin_parse_attribute(xml_ctx, import_args, YIN_ARG_MODULE, &imp->name)) != LY_SUCCESS, validation_err);
David Sedlák736fd0d2019-02-15 16:06:31 +0100387 while ((ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len) == LY_SUCCESS && name != NULL)) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200388 LY_CHECK_GOTO(yin_load_attributes(xml_ctx, data, &subelem_args) != LY_SUCCESS, validation_err);
389 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák736fd0d2019-02-15 16:06:31 +0100390 switch (kw) {
391 case YANG_PREFIX:
David Sedlák8f7a1172019-06-20 14:42:18 +0200392 LY_CHECK_ERR_GOTO(imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), validation_err);
393 LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, &subelem_args, YIN_ARG_VALUE, &imp->prefix) != LY_SUCCESS, validation_err);
394 LY_CHECK_GOTO(lysp_check_prefix((struct lys_parser_ctx *)xml_ctx, *imports, module_prefix, &imp->prefix) != LY_SUCCESS, validation_err);
David Sedlákcd0c9512019-03-29 13:23:06 +0100395 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100396 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200397 LY_CHECK_ERR_GOTO(imp->dsc, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "description"), validation_err);
398 yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->dsc);
David Sedlákcd0c9512019-03-29 13:23:06 +0100399 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100400 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200401 LY_CHECK_ERR_GOTO(imp->ref, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "reference"), validation_err);
402 yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->ref);
David Sedlákcd0c9512019-03-29 13:23:06 +0100403 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100404 case YANG_REVISION_DATE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200405 yin_parse_revision_date(xml_ctx, &subelem_args, data, imp->rev, &imp->exts);
David Sedlák3a55bc12019-06-03 08:57:29 +0200406 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100407 case YANG_CUSTOM:
408 /* TODO parse extension */
David Sedlák3a55bc12019-06-03 08:57:29 +0200409 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100410 default:
David Sedlák916b1902019-06-06 11:35:05 +0200411 LOGERR(xml_ctx->ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, "import");
David Sedlák8f7a1172019-06-20 14:42:18 +0200412 goto validation_err;
David Sedlák736fd0d2019-02-15 16:06:31 +0100413 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200414 /* TODO add free_argument_instance function and use FREE_ARRAY */
415 LY_ARRAY_FREE(subelem_args);
416 subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100417 }
418
David Sedlák8f7a1172019-06-20 14:42:18 +0200419 LY_CHECK_ERR_GOTO(!imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_MISSATTR, "prefix", "import"), validation_err);
420 LY_ARRAY_FREE(subelem_args);
David Sedlák736fd0d2019-02-15 16:06:31 +0100421 return ret;
David Sedlák8f7a1172019-06-20 14:42:18 +0200422
423validation_err:
424 LY_ARRAY_FREE(subelem_args);
425 return LY_EVALID;
David Sedlák736fd0d2019-02-15 16:06:31 +0100426}
427
David Sedlák11900c82019-06-18 16:29:12 +0200428LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200429yin_parse_status(struct lyxml_context *xml_ctx, struct yin_arg_record **status_args, const char **data, uint16_t *flags, struct lysp_ext_instance **exts)
David Sedlák11900c82019-06-18 16:29:12 +0200430{
431 LY_ERR ret = LY_SUCCESS;
432 enum yang_keyword kw = YANG_NONE;
433 const char *value = NULL, *prefix = NULL, *name = NULL;
434 char *out;
435 size_t prefix_len = 0, name_len = 0, out_len = 0;
436 int dynamic = 0;
437
438 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +0200439 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPELEM, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200440 return LY_EVALID;
441 }
442
David Sedlák8f7a1172019-06-20 14:42:18 +0200443 LY_CHECK_RET(yin_parse_attribute(xml_ctx, status_args, YIN_ARG_VALUE, &value));
David Sedlák11900c82019-06-18 16:29:12 +0200444 if (strcmp(value, "current") == 0) {
445 *flags |= LYS_STATUS_CURR;
446 } else if (strcmp(value, "deprecated") == 0) {
447 *flags |= LYS_STATUS_DEPRC;
448 } else if (strcmp(value, "obsolete") == 0) {
449 *flags |= LYS_STATUS_OBSLT;
450 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200451 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, value, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200452 lydict_remove(xml_ctx->ctx, value);
453 return LY_EVALID;
454 }
455 lydict_remove(xml_ctx->ctx, value);
456
David Sedlákb6e65972019-06-19 10:44:13 +0200457 /* TODO check if dynamic was set to 1 in case of error */
458 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
459 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
460 /* if there are any xml subelements parse them, unknown text content is silently ignored */
461 if (ret == LY_EINVAL) {
462 /* load subelements */
463 while (xml_ctx->status == LYXML_ELEMENT) {
464 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
465 if (!name) {
466 break;
467 }
David Sedlák11900c82019-06-18 16:29:12 +0200468
David Sedlák8f7a1172019-06-20 14:42:18 +0200469 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákb6e65972019-06-19 10:44:13 +0200470 switch (kw) {
471 case YANG_CUSTOM:
472 /* TODO parse extension instance */
473 break;
474 default:
David Sedlákb3077192019-06-19 10:55:37 +0200475 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 6, "status");
David Sedlákb6e65972019-06-19 10:44:13 +0200476 }
477 }
David Sedlák11900c82019-06-18 16:29:12 +0200478 }
479 }
480
481 return ret;
482}
483
David Sedlák11900c82019-06-18 16:29:12 +0200484LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200485yin_parse_extension(struct lyxml_context *xml_ctx, struct yin_arg_record **extension_args, const char **data, struct lysp_ext **extensions)
David Sedlák11900c82019-06-18 16:29:12 +0200486{
487 LY_ERR ret = LY_SUCCESS;
488 struct lysp_ext *ex;
489 const char *prefix = NULL, *name = NULL;
490 char *out = NULL;
491 size_t out_len = 0, prefix_len = 0, name_len = 0;
492 int dynamic = 0;
493 enum yang_keyword kw = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200494 struct yin_arg_record *subelem_args = NULL;
David Sedlák11900c82019-06-18 16:29:12 +0200495
496 LY_ARRAY_NEW_RET(xml_ctx->ctx, *extensions, ex, LY_EMEM);
David Sedlák8f7a1172019-06-20 14:42:18 +0200497 yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name);
David Sedlák11900c82019-06-18 16:29:12 +0200498 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200499 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new element after extension element."), LY_EINVAL);
David Sedlák11900c82019-06-18 16:29:12 +0200500
501 while (xml_ctx->status == LYXML_ELEMENT) {
502 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
503 LY_CHECK_RET(ret);
504 if (!name) {
505 break;
506 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200507 yin_load_attributes(xml_ctx, data, &subelem_args);
508 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák11900c82019-06-18 16:29:12 +0200509 switch (kw) {
510 case YANG_ARGUMENT:
David Sedlák554e36d2019-06-20 16:00:04 +0200511 /* TODO */
David Sedlák11900c82019-06-18 16:29:12 +0200512 break;
513 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200514 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->dsc));
David Sedlák11900c82019-06-18 16:29:12 +0200515 break;
516 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200517 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->ref));
David Sedlák11900c82019-06-18 16:29:12 +0200518 break;
519 case YANG_STATUS:
David Sedlák8f7a1172019-06-20 14:42:18 +0200520 LY_CHECK_RET(yin_parse_status(xml_ctx, &subelem_args, data, &ex->flags, &ex->exts));
David Sedlák11900c82019-06-18 16:29:12 +0200521 break;
522 case YANG_CUSTOM:
523 /* TODO parse extension instance */
524 break;
525 default:
David Sedlákb3077192019-06-19 10:55:37 +0200526 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 9, "extension");
David Sedlák11900c82019-06-18 16:29:12 +0200527 return LY_EVALID;
528 }
529 }
530
531 return ret;
532}
533
534/**
David Sedlákd5318ee2019-02-15 10:14:50 +0100535 * @brief Parse module substatements.
536 *
David Sedlák11900c82019-06-18 16:29:12 +0200537 * @param[in] xml_ctx Xml context.
David Sedlákb666bcc2019-06-05 15:00:05 +0200538 * @param[in,out] data Data to read from.
David Sedlák2b214ac2019-06-06 16:11:03 +0200539 * @param[out] mod Parsed module structure.
David Sedlákd5318ee2019-02-15 10:14:50 +0100540 *
541 * @return LY_ERR values.
542 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100543LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200544yin_parse_mod(struct lyxml_context *xml_ctx, struct yin_arg_record **mod_args, const char **data, struct lysp_module **mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200545{
David Sedlákf3b24f62018-11-02 10:40:47 +0100546 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100547 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100548 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200549 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100550 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200551
David Sedlákf3b24f62018-11-02 10:40:47 +0100552 char *buf = NULL, *out = NULL;
553 size_t buf_len = 0, out_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200554 int dynamic = 0;
David Sedlák8f7a1172019-06-20 14:42:18 +0200555 struct yin_arg_record *substmt_args = NULL;
David Sedlákf3b24f62018-11-02 10:40:47 +0100556
David Sedlák8f7a1172019-06-20 14:42:18 +0200557 yin_parse_attribute(xml_ctx, mod_args, YIN_ARG_NAME, &(*mod)->mod->name);
David Sedlákb3077192019-06-19 10:55:37 +0200558 LY_CHECK_ERR_RET(!(*mod)->mod->name, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Missing argument name of a module"), LY_EVALID);
David Sedlákc136b972019-03-08 13:39:06 +0100559 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200560 LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX_YIN, "Expected new xml element after module element."), LY_EINVAL);
David Sedlák4a4c0722018-11-26 17:03:10 +0100561
David Sedlák736fd0d2019-02-15 16:06:31 +0100562 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100563 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100564#define CHECK_ORDER(SECTION) \
565 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
566
567 switch (kw) {
568 /* module header */
569 case YANG_NAMESPACE:
570 case YANG_PREFIX:
571 CHECK_ORDER(Y_MOD_MODULE_HEADER);
572 break;
573 case YANG_YANG_VERSION:
574 CHECK_ORDER(Y_MOD_MODULE_HEADER);
575 break;
576 /* linkage */
577 case YANG_INCLUDE:
578 case YANG_IMPORT:
579 CHECK_ORDER(Y_MOD_LINKAGE);
580 break;
581 /* meta */
582 case YANG_ORGANIZATION:
583 case YANG_CONTACT:
584 case YANG_DESCRIPTION:
585 case YANG_REFERENCE:
586 CHECK_ORDER(Y_MOD_META);
587 break;
588
589 /* revision */
590 case YANG_REVISION:
591 CHECK_ORDER(Y_MOD_REVISION);
592 break;
593 /* body */
594 case YANG_ANYDATA:
595 case YANG_ANYXML:
596 case YANG_AUGMENT:
597 case YANG_CHOICE:
598 case YANG_CONTAINER:
599 case YANG_DEVIATION:
600 case YANG_EXTENSION:
601 case YANG_FEATURE:
602 case YANG_GROUPING:
603 case YANG_IDENTITY:
604 case YANG_LEAF:
605 case YANG_LEAF_LIST:
606 case YANG_LIST:
607 case YANG_NOTIFICATION:
608 case YANG_RPC:
609 case YANG_TYPEDEF:
610 case YANG_USES:
611 case YANG_CUSTOM:
612 mod_stmt = Y_MOD_BODY;
613 break;
614 default:
615 /* error will be handled in the next switch */
616 break;
617 }
618#undef CHECK_ORDER
619
David Sedlák68826732019-06-05 10:50:58 +0200620 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákc136b972019-03-08 13:39:06 +0100621 if (name) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200622 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &substmt_args));
623 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +0100624 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100625
David Sedlákc136b972019-03-08 13:39:06 +0100626 /* module header */
627 case YANG_NAMESPACE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200628 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_URI, &(*mod)->mod->ns));
David Sedlákc136b972019-03-08 13:39:06 +0100629 break;
630 case YANG_PREFIX:
David Sedlák8f7a1172019-06-20 14:42:18 +0200631 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_VALUE, &(*mod)->mod->prefix));
David Sedlákc136b972019-03-08 13:39:06 +0100632 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100633
David Sedlákc136b972019-03-08 13:39:06 +0100634 /* linkage */
635 case YANG_IMPORT:
David Sedlák8f7a1172019-06-20 14:42:18 +0200636 yin_parse_import(xml_ctx, &substmt_args, (*mod)->mod->prefix, data, &(*mod)->imports);
David Sedlákc136b972019-03-08 13:39:06 +0100637 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100638
David Sedlákc136b972019-03-08 13:39:06 +0100639 /* meta */
640 case YANG_ORGANIZATION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200641 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->org));
David Sedlákc136b972019-03-08 13:39:06 +0100642 break;
643 case YANG_CONTACT:
David Sedlák8f7a1172019-06-20 14:42:18 +0200644 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->contact));
David Sedlákc136b972019-03-08 13:39:06 +0100645 break;
646 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200647 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->dsc));
David Sedlákc136b972019-03-08 13:39:06 +0100648 break;
649 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200650 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->ref));
David Sedlákc136b972019-03-08 13:39:06 +0100651 break;
David Sedlák11900c82019-06-18 16:29:12 +0200652 /* revision */
653
654 /*body */
655 case YANG_EXTENSION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200656 LY_CHECK_RET(yin_parse_extension(xml_ctx, &substmt_args, data, &(*mod)->extensions));
David Sedlák11900c82019-06-18 16:29:12 +0200657 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100658
David Sedlákc136b972019-03-08 13:39:06 +0100659 default:
David Sedlák18730132019-03-15 15:51:34 +0100660 return LY_EVALID;
David Sedlákc136b972019-03-08 13:39:06 +0100661 break;
662 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200663 LY_ARRAY_FREE(substmt_args);
664 substmt_args = NULL;
David Sedlák4a4c0722018-11-26 17:03:10 +0100665 }
666 }
667
David Sedlák68826732019-06-05 10:50:58 +0200668 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +0200669}
670
671LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100672yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200673{
David Sedláke4889912018-11-02 09:52:40 +0100674 LY_ERR ret = LY_SUCCESS;
675 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +0200676 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +0200677 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100678 struct lysp_module *mod_p = NULL;
679 const char *prefix, *name;
680 size_t prefix_len, name_len;
David Sedlák8f7a1172019-06-20 14:42:18 +0200681 struct yin_arg_record *args = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +0200682
David Sedlák3017da42019-02-15 09:48:04 +0100683 /* initialize xml context */
David Sedlákaadab9c2019-04-05 15:01:27 +0200684 memset(&parser_ctx, 0, sizeof parser_ctx);
685 xml_ctx->ctx = ctx;
686 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +0100687
David Sedlák3017da42019-02-15 09:48:04 +0100688 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +0200689 ret = lyxml_get_element(xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200690 yin_load_attributes(xml_ctx, &data, &args);
David Sedlák3017da42019-02-15 09:48:04 +0100691 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200692 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedláke4889912018-11-02 09:52:40 +0100693 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100694 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
695 ret = LY_EINVAL;
696 goto cleanup;
697 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +0200698 LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +0200699 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +0100700 ret = LY_EVALID;
701 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100702 }
703
David Sedlák3017da42019-02-15 09:48:04 +0100704 /* allocate module */
705 mod_p = calloc(1, sizeof *mod_p);
706 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
707 mod_p->mod = mod;
708 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100709
David Sedlák3017da42019-02-15 09:48:04 +0100710 /* parser module substatements */
David Sedlák8f7a1172019-06-20 14:42:18 +0200711 ret = yin_parse_mod(xml_ctx, &args, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +0100712 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100713
David Sedlák3017da42019-02-15 09:48:04 +0100714 mod_p->parsing = 0;
715 mod->parsed = mod_p;
716
717cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +0200718 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +0100719 lysp_module_free(mod_p);
720 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200721 LY_ARRAY_FREE(args);
David Sedlákaadab9c2019-04-05 15:01:27 +0200722 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +0100723 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200724}