blob: 00db36f550822bb0612a185a438bffd3b221c264 [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ák8f7a1172019-06-20 14:42:18 +020020#include <stdbool.h>
David Sedlákf824ad52018-10-14 23:58:15 +020021
David Sedlákf824ad52018-10-14 23:58:15 +020022#include "context.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020023#include "dict.h"
David Sedlák3b4db242018-10-19 16:11:01 +020024#include "xml.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020025#include "tree.h"
26#include "tree_schema.h"
David Sedlák3b4db242018-10-19 16:11:01 +020027#include "tree_schema_internal.h"
David Sedlákecf5eb82019-06-03 14:12:44 +020028#include "parser_yin.h"
David Sedlák2b214ac2019-06-06 16:11:03 +020029/**
30 * @brief check if given string is URI of yin namespace.
31 * @param ns Namespace URI to check.
32 *
33 * @return true if ns equals YIN_NS_URI false otherwise.
34 */
35#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
36
David Sedlákf6251182019-06-06 10:22:13 +020037const char *const yin_attr_list[] = {
38 [YIN_ARG_NAME] = "name",
39 [YIN_ARG_TARGET_NODE] = "target-node",
40 [YIN_ARG_MODULE] = "module",
41 [YIN_ARG_VALUE] = "value",
42 [YIN_ARG_TEXT] = "text",
43 [YIN_ARG_CONDITION] = "condition",
44 [YIN_ARG_URI] = "uri",
45 [YIN_ARG_DATE] = "date",
46 [YIN_ARG_TAG] = "tag",
47 [YIN_ARG_XMLNS] = "xmlns",
48};
49
David Sedlákc8dd80e2019-06-19 16:08:48 +020050/**
51 * @brief check if keyword was matched properly,
52 * information about namespace is not always fully available when type of keyword is already needed
53 * this function retroactively checks if kw isn't actually extension instance or unknown element without namespace
54 *
55 * @param[in] xml_ctx Xml context.
56 * @param[in] prefix Keyword prefix.
57 * @param[in] prefix_len Length of prefix.
58 * @param[in,out] kw Type of keyword.
59 */
60void
61check_kw_ns(struct lyxml_context *xml_ctx, const char *prefix, size_t prefix_len, enum yang_keyword *kw)
62{
63 const struct lyxml_ns *ns = NULL;
64
65 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
66
67 if (!ns) {
68 *kw = YANG_NONE;
69 } else {
70 if (!IS_YIN_NS(ns->uri)) {
71 *kw = YANG_CUSTOM;
72 }
73 }
74}
75
David Sedlák1bccdfa2019-06-17 15:55:27 +020076enum yang_keyword
David Sedlák8f7a1172019-06-20 14:42:18 +020077yin_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 +020078{
David Sedlák8f7a1172019-06-20 14:42:18 +020079 const char *start = NULL;
80 enum yang_keyword kw = YANG_NONE;
81 const struct lyxml_ns *ns = NULL;
82
83 if (!name || name_len == 0) {
David Sedlák1bccdfa2019-06-17 15:55:27 +020084 return YANG_NONE;
85 }
86
David Sedlák8f7a1172019-06-20 14:42:18 +020087 ns = lyxml_ns_get(xml_ctx, prefix, prefix_len);
88 if (ns) {
89 if (!IS_YIN_NS(ns->uri)) {
90 return YANG_CUSTOM;
91 }
92 } else {
93 /* elements without namespace are automatically unknown */
94 return YANG_NONE;
95 }
David Sedlák1bccdfa2019-06-17 15:55:27 +020096
David Sedlák8f7a1172019-06-20 14:42:18 +020097
98 start = name;
99 kw = lysp_match_kw(NULL, &name);
100
101 if (name - start == (long int)name_len) {
David Sedlák1bccdfa2019-06-17 15:55:27 +0200102 return kw;
103 } else {
104 return YANG_NONE;
105 }
106}
107
108
David Sedlák872c7b42018-10-26 13:15:20 +0200109enum YIN_ARGUMENT
David Sedlák060b00e2019-06-19 11:12:06 +0200110yin_match_argument_name(const char *name, size_t len)
David Sedlák3b4db242018-10-19 16:11:01 +0200111{
David Sedláka7406952019-04-05 10:33:07 +0200112 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200113 size_t already_read = 0;
David Sedlák7ff55a92019-06-17 11:11:41 +0200114 LY_CHECK_RET(len == 0, YIN_ARG_NONE);
David Sedlák3b4db242018-10-19 16:11:01 +0200115
David Sedlák94de2aa2019-02-15 12:42:11 +0100116#define IF_ARG(STR, LEN, STMT) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;arg=STMT;}
117#define IF_ARG_PREFIX(STR, LEN) if (!strncmp((name) + already_read, STR, LEN)) {already_read+=LEN;
David Sedlákc10e7902018-12-17 02:17:59 +0100118#define IF_ARG_PREFIX_END }
119
David Sedlák1c8b2702019-02-22 11:03:02 +0100120 switch (*name) {
David Sedlák18730132019-03-15 15:51:34 +0100121 case 'x':
122 already_read += 1;
123 IF_ARG("mlns", 4, YIN_ARG_XMLNS);
124 break;
David Sedlák94de2aa2019-02-15 12:42:11 +0100125 case 'c':
126 already_read += 1;
127 IF_ARG("ondition", 8, YIN_ARG_CONDITION);
David Sedlák3b4db242018-10-19 16:11:01 +0200128 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200129
David Sedlák94de2aa2019-02-15 12:42:11 +0100130 case 'd':
131 already_read += 1;
132 IF_ARG("ate", 3, YIN_ARG_DATE);
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 'm':
136 already_read += 1;
137 IF_ARG("odule", 5, YIN_ARG_MODULE);
David Sedlák872c7b42018-10-26 13:15:20 +0200138 break;
139
David Sedlák94de2aa2019-02-15 12:42:11 +0100140 case 'n':
141 already_read += 1;
142 IF_ARG("ame", 3, YIN_ARG_NAME);
David Sedlák872c7b42018-10-26 13:15:20 +0200143 break;
144
David Sedlák94de2aa2019-02-15 12:42:11 +0100145 case 't':
146 already_read += 1;
147 IF_ARG_PREFIX("a", 1)
148 IF_ARG("g", 1, YIN_ARG_TAG)
149 else IF_ARG("rget-node", 9, YIN_ARG_TARGET_NODE)
150 IF_ARG_PREFIX_END
151 else IF_ARG("ext", 3, YIN_ARG_TEXT)
David Sedlák3b4db242018-10-19 16:11:01 +0200152 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200153
David Sedlák94de2aa2019-02-15 12:42:11 +0100154 case 'u':
155 already_read += 1;
156 IF_ARG("ri", 2, YIN_ARG_URI)
David Sedlák3b4db242018-10-19 16:11:01 +0200157 break;
David Sedlák872c7b42018-10-26 13:15:20 +0200158
David Sedlák94de2aa2019-02-15 12:42:11 +0100159 case 'v':
160 already_read += 1;
161 IF_ARG("alue", 4, YIN_ARG_VALUE);
David Sedlák3b4db242018-10-19 16:11:01 +0200162 break;
163 }
164
David Sedlákc10e7902018-12-17 02:17:59 +0100165 /* whole argument must be matched */
David Sedlák872c7b42018-10-26 13:15:20 +0200166 if (already_read != len) {
David Sedláka7406952019-04-05 10:33:07 +0200167 arg = YIN_ARG_UNKNOWN;
David Sedlák872c7b42018-10-26 13:15:20 +0200168 }
169
David Sedlák18730132019-03-15 15:51:34 +0100170#undef IF_ARG
171#undef IF_ARG_PREFIX
172#undef IF_ARG_PREFIX_END
173
David Sedlák872c7b42018-10-26 13:15:20 +0200174 return arg;
David Sedlák3b4db242018-10-19 16:11:01 +0200175}
176
David Sedlák8f7a1172019-06-20 14:42:18 +0200177LY_ERR
178yin_load_attributes(struct lyxml_context *xml_ctx, const char **data, struct yin_arg_record **args)
David Sedláka7406952019-04-05 10:33:07 +0200179{
180 LY_ERR ret = LY_SUCCESS;
David Sedlák8f7a1172019-06-20 14:42:18 +0200181 struct yin_arg_record *argument_record = NULL;
David Sedláka7406952019-04-05 10:33:07 +0200182
David Sedlák7ff55a92019-06-17 11:11:41 +0200183 /* load all attributes first */
David Sedlák57715b12019-06-17 13:05:22 +0200184 while (xml_ctx->status == LYXML_ATTRIBUTE) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200185 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *args, argument_record, ret, cleanup);
David Sedlák7ff55a92019-06-17 11:11:41 +0200186 ret = lyxml_get_attribute(xml_ctx, data, &argument_record->prefix, &argument_record->prefix_len,
187 &argument_record->name, &argument_record->name_len);
188 LY_CHECK_ERR_GOTO(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), cleanup);
David Sedláka7406952019-04-05 10:33:07 +0200189
David Sedlák7ff55a92019-06-17 11:11:41 +0200190 if (xml_ctx->status == LYXML_ATTR_CONTENT) {
David Sedlák57715b12019-06-17 13:05:22 +0200191 argument_record->content = NULL;
192 argument_record->content_len = 0;
193 argument_record->dynamic_content = 0;
194 ret = lyxml_get_string(xml_ctx, data, &argument_record->content, &argument_record->content_len,
195 &argument_record->content, &argument_record->content_len, &argument_record->dynamic_content);
David Sedlák7ff55a92019-06-17 11:11:41 +0200196 LY_CHECK_ERR_GOTO(ret != LY_SUCCESS, LOGMEM(xml_ctx->ctx), cleanup);
197 }
198 }
199
David Sedlák8f7a1172019-06-20 14:42:18 +0200200cleanup:
201 if (ret != LY_SUCCESS) {
202 LY_ARRAY_FREE(*args);
203 }
204 return ret;
205}
206
207LY_ERR
208yin_parse_attribute(struct lyxml_context *xml_ctx, struct yin_arg_record **args, enum YIN_ARGUMENT arg_type, const char **arg_val)
209{
210 LY_ERR ret = LY_SUCCESS;
211 enum YIN_ARGUMENT arg = YIN_ARG_UNKNOWN;
212 struct yin_arg_record *iter = NULL;
213 const struct lyxml_ns *ns = NULL;
214
David Sedlák1bccdfa2019-06-17 15:55:27 +0200215 /* validation of attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200216 LY_ARRAY_FOR(*args, struct yin_arg_record, iter) {
David Sedlák7ff55a92019-06-17 11:11:41 +0200217 ns = lyxml_ns_get(xml_ctx, iter->prefix, iter->prefix_len);
David Sedlák2b214ac2019-06-06 16:11:03 +0200218 if (ns && IS_YIN_NS(ns->uri)) {
David Sedlák060b00e2019-06-19 11:12:06 +0200219 arg = yin_match_argument_name(iter->name, iter->name_len);
David Sedlák7ff55a92019-06-17 11:11:41 +0200220 if (arg == YIN_ARG_NONE) {
David Sedlák2b214ac2019-06-06 16:11:03 +0200221 continue;
David Sedlák7ff55a92019-06-17 11:11:41 +0200222 } else if (arg == arg_type) {
David Sedlák57715b12019-06-17 13:05:22 +0200223 if (iter->dynamic_content) {
224 *arg_val = lydict_insert_zc(xml_ctx->ctx, iter->content);
225 } else {
226 *arg_val = lydict_insert(xml_ctx->ctx, iter->content, iter->content_len);
227 LY_CHECK_ERR_GOTO(!(*arg_val), LOGMEM(xml_ctx->ctx); ret = LY_EMEM, cleanup);
228 }
David Sedlák2b214ac2019-06-06 16:11:03 +0200229 } else {
David Sedlák57715b12019-06-17 13:05:22 +0200230 if (iter->dynamic_content) {
231 free(iter->content);
232 }
David Sedlák7ff55a92019-06-17 11:11:41 +0200233 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected attribute \"%.*s\".", iter->name_len, iter->name);
234 ret = LY_EVALID;
235 goto cleanup;
David Sedláka7406952019-04-05 10:33:07 +0200236 }
237 }
238 }
239
David Sedlák7ff55a92019-06-17 11:11:41 +0200240cleanup:
David Sedlák7ff55a92019-06-17 11:11:41 +0200241 return ret;
David Sedláka7406952019-04-05 10:33:07 +0200242}
243
David Sedlák0daba9a2019-03-22 14:07:49 +0100244LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200245yin_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 +0100246{
247 LY_ERR ret = LY_SUCCESS;
248 char *buf = NULL, *out = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200249 const char *prefix = NULL, *name = NULL;
250 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200251 int dynamic = 0;
David Sedlák0daba9a2019-03-22 14:07:49 +0100252
David Sedlák8f7a1172019-06-20 14:42:18 +0200253 ret = yin_parse_attribute(xml_ctx, args, YIN_ARG_NONE, NULL);
David Sedlák68826732019-06-05 10:50:58 +0200254 LY_CHECK_RET(ret);
David Sedlák0daba9a2019-03-22 14:07:49 +0100255 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
256
257 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
258 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
259 LY_CHECK_RET(ret);
David Sedlák57715b12019-06-17 13:05:22 +0200260 if (dynamic) {
261 *value = lydict_insert_zc(xml_ctx->ctx, buf);
262 } else {
263 *value = lydict_insert(xml_ctx->ctx, out, out_len);
264 LY_CHECK_ERR_RET(!(*value), LOGMEM(xml_ctx->ctx), LY_EMEM);
265 }
David Sedlák0daba9a2019-03-22 14:07:49 +0100266 }
267
David Sedlák15a92662019-06-18 11:55:15 +0200268 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
269 LY_CHECK_RET(ret);
270
271 return LY_SUCCESS;
272}
273
274/**
275 * @brief function to parse meta tags eg. elements with text element as child
276 *
277 * @param[in] xml_ctx Xml context.
David Sedlák8f7a1172019-06-20 14:42:18 +0200278 * @param[in] args Sized array of arguments of current elements.
David Sedlák15a92662019-06-18 11:55:15 +0200279 * @param[in,out] data Data to read from.
280 * @param[out] value Where the content of meta tag should be stored.
281 *
282 * @return LY_ERR values.
283 */
284LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200285yin_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 +0200286{
287 LY_ERR ret = LY_SUCCESS;
288 char *buf = NULL, *out = NULL;
David Sedlák8f7a1172019-06-20 14:42:18 +0200289 const char *prefix = NULL, *name = NULL, *content_start = NULL;
David Sedlák15a92662019-06-18 11:55:15 +0200290 size_t buf_len = 0, out_len = 0, prefix_len = 0, name_len = 0;
291 int dynamic = 0;
David Sedlák15a92662019-06-18 11:55:15 +0200292 enum YIN_ARGUMENT arg = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200293 struct yin_arg_record *subelem_args = NULL;
294 enum yang_keyword kw = YANG_NONE;
David Sedlák15a92662019-06-18 11:55:15 +0200295
David Sedlák8f7a1172019-06-20 14:42:18 +0200296 ret = yin_parse_attribute(xml_ctx, args, YIN_ARG_NONE, NULL);
David Sedlák15a92662019-06-18 11:55:15 +0200297 LY_CHECK_RET(ret);
298 LY_CHECK_RET(xml_ctx->status != LYXML_ELEM_CONTENT, LY_EVALID);
299
300 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200301 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 +0200302
David Sedlák8f7a1172019-06-20 14:42:18 +0200303 /* first element should be argument element <text> */
304 content_start = *data;
305 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
306 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &subelem_args));
307 arg = yin_match_argument_name(name, name_len);
308 if (arg == YIN_ARG_TEXT) {
309 yin_parse_text_element(xml_ctx, &subelem_args, data, value);
310 } else {
311 /* first element is not argument element, go back to start of element content and try to parse normal subelements */
312 *data = content_start;
313 }
314
David Sedlák15a92662019-06-18 11:55:15 +0200315 /* loop over all child elements and parse them */
316 while (xml_ctx->status == LYXML_ELEMENT) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200317 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
318 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &subelem_args));
319 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák15a92662019-06-18 11:55:15 +0200320
David Sedlák8f7a1172019-06-20 14:42:18 +0200321 if (!name) {
David Sedlák15a92662019-06-18 11:55:15 +0200322 /* end of meta element reached */
323 break;
324 }
325
David Sedlák8f7a1172019-06-20 14:42:18 +0200326 switch (kw) {
327 case YANG_CUSTOM:
328 // TODO parse extension instance
329 break;
330
331 default:
332 LOGERR(xml_ctx->ctx, LYVE_SYNTAX_YIN, "Unexpected child element \"%.*s\".", name_len, name);
333 return LY_EVALID;
334 }
David Sedlák15a92662019-06-18 11:55:15 +0200335 }
336
David Sedlák6b7ac2d2019-03-22 14:40:29 +0100337 return LY_SUCCESS;
David Sedlák0daba9a2019-03-22 14:07:49 +0100338}
339
David Sedlákb666bcc2019-06-05 15:00:05 +0200340/**
David Sedlák2b214ac2019-06-06 16:11:03 +0200341 * @brief Parse revision date.
David Sedlákb666bcc2019-06-05 15:00:05 +0200342 *
343 * @param[in] xml_ctx Xml context.
David Sedlák8f7a1172019-06-20 14:42:18 +0200344 * @param[in] args Sized array of arguments of current element.
David Sedlákb666bcc2019-06-05 15:00:05 +0200345 * @param[in,out] data Data to read from.
346 * @param[in,out] rev Array to store the parsed value in.
347 * @param[in,out] exts Extension instances to add to.
348 *
David Sedlák2b214ac2019-06-06 16:11:03 +0200349 * @return LY_ERR values.
David Sedlákb666bcc2019-06-05 15:00:05 +0200350 */
David Sedlák81e04022019-04-05 15:05:46 +0200351static LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200352yin_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 +0200353{
354 LY_ERR ret = LY_SUCCESS;
David Sedlákda63c082019-06-04 13:52:23 +0200355 const char *temp_rev;
David Sedlákcd0c9512019-03-29 13:23:06 +0100356
David Sedlák81e04022019-04-05 15:05:46 +0200357 if (rev[0]) {
David Sedlákb3077192019-06-19 10:55:37 +0200358 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "revision-date");
David Sedlák81e04022019-04-05 15:05:46 +0200359 return LY_EVALID;
360 }
361
David Sedlák8f7a1172019-06-20 14:42:18 +0200362 LY_CHECK_RET(yin_parse_attribute(xml_ctx, args, YIN_ARG_DATE, &temp_rev))
David Sedlák81e04022019-04-05 15:05:46 +0200363 LY_CHECK_RET(ret != LY_SUCCESS, ret);
David Sedlákda63c082019-06-04 13:52:23 +0200364 LY_CHECK_RET(lysp_check_date((struct lys_parser_ctx *)xml_ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS, LY_EVALID);
365
366 strcpy(rev, temp_rev);
367 lydict_remove(xml_ctx->ctx, temp_rev);
368 /* TODO extension */
David Sedlák81e04022019-04-05 15:05:46 +0200369
David Sedlák81e04022019-04-05 15:05:46 +0200370 return ret;
371}
David Sedlákcd0c9512019-03-29 13:23:06 +0100372
David Sedlákda63c082019-06-04 13:52:23 +0200373LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200374yin_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 +0100375{
376 LY_ERR ret = LY_SUCCESS;
377 enum yang_keyword kw;
378 struct lysp_import *imp;
379 const char *prefix, *name;
David Sedlák8f7a1172019-06-20 14:42:18 +0200380 struct yin_arg_record *subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100381 size_t prefix_len, name_len;
382
David Sedlák81e04022019-04-05 15:05:46 +0200383 /* allocate sized array for imports */
David Sedlák8f7a1172019-06-20 14:42:18 +0200384 LY_ARRAY_NEW_GOTO(xml_ctx->ctx, *imports, imp, ret, validation_err);
David Sedlák736fd0d2019-02-15 16:06:31 +0100385
David Sedláka7406952019-04-05 10:33:07 +0200386 /* parse import attributes */
David Sedlák8f7a1172019-06-20 14:42:18 +0200387 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 +0100388 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 +0200389 LY_CHECK_GOTO(yin_load_attributes(xml_ctx, data, &subelem_args) != LY_SUCCESS, validation_err);
390 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák736fd0d2019-02-15 16:06:31 +0100391 switch (kw) {
392 case YANG_PREFIX:
David Sedlák8f7a1172019-06-20 14:42:18 +0200393 LY_CHECK_ERR_GOTO(imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "prefix"), validation_err);
394 LY_CHECK_GOTO(yin_parse_attribute(xml_ctx, &subelem_args, YIN_ARG_VALUE, &imp->prefix) != LY_SUCCESS, validation_err);
395 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 +0100396 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100397 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200398 LY_CHECK_ERR_GOTO(imp->dsc, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "description"), validation_err);
399 yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->dsc);
David Sedlákcd0c9512019-03-29 13:23:06 +0100400 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100401 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200402 LY_CHECK_ERR_GOTO(imp->ref, LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPSTMT, "reference"), validation_err);
403 yin_parse_meta_element(xml_ctx, &subelem_args, data, &imp->ref);
David Sedlákcd0c9512019-03-29 13:23:06 +0100404 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100405 case YANG_REVISION_DATE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200406 yin_parse_revision_date(xml_ctx, &subelem_args, data, imp->rev, &imp->exts);
David Sedlák3a55bc12019-06-03 08:57:29 +0200407 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100408 case YANG_CUSTOM:
409 /* TODO parse extension */
David Sedlák3a55bc12019-06-03 08:57:29 +0200410 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100411 default:
David Sedlák916b1902019-06-06 11:35:05 +0200412 LOGERR(xml_ctx->ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, "import");
David Sedlák8f7a1172019-06-20 14:42:18 +0200413 goto validation_err;
David Sedlák736fd0d2019-02-15 16:06:31 +0100414 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200415 /* TODO add free_argument_instance function and use FREE_ARRAY */
416 LY_ARRAY_FREE(subelem_args);
417 subelem_args = NULL;
David Sedlák736fd0d2019-02-15 16:06:31 +0100418 }
419
David Sedlák8f7a1172019-06-20 14:42:18 +0200420 LY_CHECK_ERR_GOTO(!imp->prefix, LOGVAL_PARSER(xml_ctx, LY_VCODE_MISSATTR, "prefix", "import"), validation_err);
421 LY_ARRAY_FREE(subelem_args);
David Sedlák736fd0d2019-02-15 16:06:31 +0100422 return ret;
David Sedlák8f7a1172019-06-20 14:42:18 +0200423
424validation_err:
425 LY_ARRAY_FREE(subelem_args);
426 return LY_EVALID;
David Sedlák736fd0d2019-02-15 16:06:31 +0100427}
428
David Sedlák11900c82019-06-18 16:29:12 +0200429LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200430yin_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 +0200431{
432 LY_ERR ret = LY_SUCCESS;
433 enum yang_keyword kw = YANG_NONE;
434 const char *value = NULL, *prefix = NULL, *name = NULL;
435 char *out;
436 size_t prefix_len = 0, name_len = 0, out_len = 0;
437 int dynamic = 0;
438
439 if (*flags & LYS_STATUS_MASK) {
David Sedlákb3077192019-06-19 10:55:37 +0200440 LOGVAL_PARSER(xml_ctx, LY_VCODE_DUPELEM, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200441 return LY_EVALID;
442 }
443
David Sedlák8f7a1172019-06-20 14:42:18 +0200444 LY_CHECK_RET(yin_parse_attribute(xml_ctx, status_args, YIN_ARG_VALUE, &value));
David Sedlák11900c82019-06-18 16:29:12 +0200445 if (strcmp(value, "current") == 0) {
446 *flags |= LYS_STATUS_CURR;
447 } else if (strcmp(value, "deprecated") == 0) {
448 *flags |= LYS_STATUS_DEPRC;
449 } else if (strcmp(value, "obsolete") == 0) {
450 *flags |= LYS_STATUS_OBSLT;
451 } else {
David Sedlákb3077192019-06-19 10:55:37 +0200452 LOGVAL_PARSER(xml_ctx, LY_VCODE_INVAL_YIN, value, "status");
David Sedlák11900c82019-06-18 16:29:12 +0200453 lydict_remove(xml_ctx->ctx, value);
454 return LY_EVALID;
455 }
456 lydict_remove(xml_ctx->ctx, value);
457
David Sedlákb6e65972019-06-19 10:44:13 +0200458 /* TODO check if dynamic was set to 1 in case of error */
459 if (xml_ctx->status == LYXML_ELEM_CONTENT) {
460 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
461 /* if there are any xml subelements parse them, unknown text content is silently ignored */
462 if (ret == LY_EINVAL) {
463 /* load subelements */
464 while (xml_ctx->status == LYXML_ELEMENT) {
465 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
466 if (!name) {
467 break;
468 }
David Sedlák11900c82019-06-18 16:29:12 +0200469
David Sedlák8f7a1172019-06-20 14:42:18 +0200470 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákb6e65972019-06-19 10:44:13 +0200471 switch (kw) {
472 case YANG_CUSTOM:
473 /* TODO parse extension instance */
474 break;
475 default:
David Sedlákb3077192019-06-19 10:55:37 +0200476 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 6, "status");
David Sedlákb6e65972019-06-19 10:44:13 +0200477 }
478 }
David Sedlák11900c82019-06-18 16:29:12 +0200479 }
480 }
481
482 return ret;
483}
484
485/**
486 * @brief Parse the extension statement.
487 *
488 * @param[in] xml_ctx Xml context.
David Sedlák8f7a1172019-06-20 14:42:18 +0200489 * @param[in] extension_args Arguments of extension element.
David Sedlák11900c82019-06-18 16:29:12 +0200490 * @param[in,out] data Data to read from.
491 * @param[in,out] extensions Extensions to add to.
492 *
493 * @return LY_ERR values.
494 */
495LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200496yin_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 +0200497{
498 LY_ERR ret = LY_SUCCESS;
499 struct lysp_ext *ex;
500 const char *prefix = NULL, *name = NULL;
501 char *out = NULL;
502 size_t out_len = 0, prefix_len = 0, name_len = 0;
503 int dynamic = 0;
504 enum yang_keyword kw = YANG_NONE;
David Sedlák8f7a1172019-06-20 14:42:18 +0200505 struct yin_arg_record *subelem_args = NULL;
David Sedlák11900c82019-06-18 16:29:12 +0200506
507 LY_ARRAY_NEW_RET(xml_ctx->ctx, *extensions, ex, LY_EMEM);
David Sedlák8f7a1172019-06-20 14:42:18 +0200508 yin_parse_attribute(xml_ctx, extension_args, YIN_ARG_NAME, &ex->name);
David Sedlák11900c82019-06-18 16:29:12 +0200509 ret = lyxml_get_string(xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200510 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 +0200511
512 while (xml_ctx->status == LYXML_ELEMENT) {
513 ret = lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len);
514 LY_CHECK_RET(ret);
515 if (!name) {
516 break;
517 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200518 yin_load_attributes(xml_ctx, data, &subelem_args);
519 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlák11900c82019-06-18 16:29:12 +0200520 switch (kw) {
521 case YANG_ARGUMENT:
522 break;
523 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200524 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->dsc));
David Sedlák11900c82019-06-18 16:29:12 +0200525 break;
526 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200527 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &subelem_args, data, &ex->ref));
David Sedlák11900c82019-06-18 16:29:12 +0200528 break;
529 case YANG_STATUS:
David Sedlák8f7a1172019-06-20 14:42:18 +0200530 LY_CHECK_RET(yin_parse_status(xml_ctx, &subelem_args, data, &ex->flags, &ex->exts));
David Sedlák11900c82019-06-18 16:29:12 +0200531 break;
532 case YANG_CUSTOM:
533 /* TODO parse extension instance */
534 break;
535 default:
David Sedlákb3077192019-06-19 10:55:37 +0200536 LOGVAL_PARSER(xml_ctx, LY_VCODE_INCHILDSTMT_YIN, name_len, name, 9, "extension");
David Sedlák11900c82019-06-18 16:29:12 +0200537 return LY_EVALID;
538 }
539 }
540
541 return ret;
542}
543
544/**
David Sedlákd5318ee2019-02-15 10:14:50 +0100545 * @brief Parse module substatements.
546 *
David Sedlák11900c82019-06-18 16:29:12 +0200547 * @param[in] xml_ctx Xml context.
David Sedlákb666bcc2019-06-05 15:00:05 +0200548 * @param[in,out] data Data to read from.
David Sedlák2b214ac2019-06-06 16:11:03 +0200549 * @param[out] mod Parsed module structure.
David Sedlákd5318ee2019-02-15 10:14:50 +0100550 *
551 * @return LY_ERR values.
552 */
David Sedlák4a4c0722018-11-26 17:03:10 +0100553LY_ERR
David Sedlák8f7a1172019-06-20 14:42:18 +0200554yin_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 +0200555{
David Sedlákf3b24f62018-11-02 10:40:47 +0100556 LY_ERR ret = LY_SUCCESS;
David Sedlák4a4c0722018-11-26 17:03:10 +0100557 enum yang_keyword kw = YANG_NONE;
David Sedláke4889912018-11-02 09:52:40 +0100558 const char *prefix, *name;
David Sedlák3b4db242018-10-19 16:11:01 +0200559 size_t prefix_len, name_len;
David Sedlák4b4713f2019-02-15 13:47:45 +0100560 enum yang_module_stmt mod_stmt = Y_MOD_MODULE_HEADER;
David Sedlák3b4db242018-10-19 16:11:01 +0200561
David Sedlákf3b24f62018-11-02 10:40:47 +0100562 char *buf = NULL, *out = NULL;
563 size_t buf_len = 0, out_len = 0;
David Sedlák57715b12019-06-17 13:05:22 +0200564 int dynamic = 0;
David Sedlák8f7a1172019-06-20 14:42:18 +0200565 struct yin_arg_record *substmt_args = NULL;
David Sedlákf3b24f62018-11-02 10:40:47 +0100566
David Sedlák8f7a1172019-06-20 14:42:18 +0200567 yin_parse_attribute(xml_ctx, mod_args, YIN_ARG_NAME, &(*mod)->mod->name);
David Sedlákb3077192019-06-19 10:55:37 +0200568 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 +0100569 ret = lyxml_get_string(xml_ctx, data, &buf, &buf_len, &out, &out_len, &dynamic);
David Sedlákb3077192019-06-19 10:55:37 +0200570 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 +0100571
David Sedlák736fd0d2019-02-15 16:06:31 +0100572 /* loop over all elements and parse them */
David Sedlákc136b972019-03-08 13:39:06 +0100573 while (xml_ctx->status != LYXML_END) {
David Sedlák4b4713f2019-02-15 13:47:45 +0100574#define CHECK_ORDER(SECTION) \
575 if (mod_stmt > SECTION) {return LY_EVALID;}mod_stmt = SECTION
576
577 switch (kw) {
578 /* module header */
579 case YANG_NAMESPACE:
580 case YANG_PREFIX:
581 CHECK_ORDER(Y_MOD_MODULE_HEADER);
582 break;
583 case YANG_YANG_VERSION:
584 CHECK_ORDER(Y_MOD_MODULE_HEADER);
585 break;
586 /* linkage */
587 case YANG_INCLUDE:
588 case YANG_IMPORT:
589 CHECK_ORDER(Y_MOD_LINKAGE);
590 break;
591 /* meta */
592 case YANG_ORGANIZATION:
593 case YANG_CONTACT:
594 case YANG_DESCRIPTION:
595 case YANG_REFERENCE:
596 CHECK_ORDER(Y_MOD_META);
597 break;
598
599 /* revision */
600 case YANG_REVISION:
601 CHECK_ORDER(Y_MOD_REVISION);
602 break;
603 /* body */
604 case YANG_ANYDATA:
605 case YANG_ANYXML:
606 case YANG_AUGMENT:
607 case YANG_CHOICE:
608 case YANG_CONTAINER:
609 case YANG_DEVIATION:
610 case YANG_EXTENSION:
611 case YANG_FEATURE:
612 case YANG_GROUPING:
613 case YANG_IDENTITY:
614 case YANG_LEAF:
615 case YANG_LEAF_LIST:
616 case YANG_LIST:
617 case YANG_NOTIFICATION:
618 case YANG_RPC:
619 case YANG_TYPEDEF:
620 case YANG_USES:
621 case YANG_CUSTOM:
622 mod_stmt = Y_MOD_BODY;
623 break;
624 default:
625 /* error will be handled in the next switch */
626 break;
627 }
628#undef CHECK_ORDER
629
David Sedlák68826732019-06-05 10:50:58 +0200630 LY_CHECK_RET(lyxml_get_element(xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
David Sedlákc136b972019-03-08 13:39:06 +0100631 if (name) {
David Sedlák8f7a1172019-06-20 14:42:18 +0200632 LY_CHECK_RET(yin_load_attributes(xml_ctx, data, &substmt_args));
633 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedlákc136b972019-03-08 13:39:06 +0100634 switch (kw) {
David Sedlák736fd0d2019-02-15 16:06:31 +0100635
David Sedlákc136b972019-03-08 13:39:06 +0100636 /* module header */
637 case YANG_NAMESPACE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200638 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_URI, &(*mod)->mod->ns));
David Sedlákc136b972019-03-08 13:39:06 +0100639 break;
640 case YANG_PREFIX:
David Sedlák8f7a1172019-06-20 14:42:18 +0200641 LY_CHECK_RET(yin_parse_attribute(xml_ctx, &substmt_args, YIN_ARG_VALUE, &(*mod)->mod->prefix));
David Sedlákc136b972019-03-08 13:39:06 +0100642 break;
David Sedlák4a4c0722018-11-26 17:03:10 +0100643
David Sedlákc136b972019-03-08 13:39:06 +0100644 /* linkage */
645 case YANG_IMPORT:
David Sedlák8f7a1172019-06-20 14:42:18 +0200646 yin_parse_import(xml_ctx, &substmt_args, (*mod)->mod->prefix, data, &(*mod)->imports);
David Sedlákc136b972019-03-08 13:39:06 +0100647 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100648
David Sedlákc136b972019-03-08 13:39:06 +0100649 /* meta */
650 case YANG_ORGANIZATION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200651 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->org));
David Sedlákc136b972019-03-08 13:39:06 +0100652 break;
653 case YANG_CONTACT:
David Sedlák8f7a1172019-06-20 14:42:18 +0200654 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->contact));
David Sedlákc136b972019-03-08 13:39:06 +0100655 break;
656 case YANG_DESCRIPTION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200657 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->dsc));
David Sedlákc136b972019-03-08 13:39:06 +0100658 break;
659 case YANG_REFERENCE:
David Sedlák8f7a1172019-06-20 14:42:18 +0200660 LY_CHECK_RET(yin_parse_meta_element(xml_ctx, &substmt_args, data, &(*mod)->mod->ref));
David Sedlákc136b972019-03-08 13:39:06 +0100661 break;
David Sedlák11900c82019-06-18 16:29:12 +0200662 /* revision */
663
664 /*body */
665 case YANG_EXTENSION:
David Sedlák8f7a1172019-06-20 14:42:18 +0200666 LY_CHECK_RET(yin_parse_extension(xml_ctx, &substmt_args, data, &(*mod)->extensions));
David Sedlák11900c82019-06-18 16:29:12 +0200667 break;
David Sedlák736fd0d2019-02-15 16:06:31 +0100668
David Sedlákc136b972019-03-08 13:39:06 +0100669 default:
David Sedlák18730132019-03-15 15:51:34 +0100670 return LY_EVALID;
David Sedlákc136b972019-03-08 13:39:06 +0100671 break;
672 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200673 LY_ARRAY_FREE(substmt_args);
674 substmt_args = NULL;
David Sedlák4a4c0722018-11-26 17:03:10 +0100675 }
676 }
677
David Sedlák68826732019-06-05 10:50:58 +0200678 return LY_SUCCESS;
David Sedlák3b4db242018-10-19 16:11:01 +0200679}
680
681LY_ERR
David Sedlák3017da42019-02-15 09:48:04 +0100682yin_parse_module(struct ly_ctx *ctx, const char *data, struct lys_module *mod)
David Sedlák3b4db242018-10-19 16:11:01 +0200683{
David Sedláke4889912018-11-02 09:52:40 +0100684 LY_ERR ret = LY_SUCCESS;
685 enum yang_keyword kw = YANG_NONE;
David Sedlákecf5eb82019-06-03 14:12:44 +0200686 struct lys_parser_ctx parser_ctx;
David Sedlákaadab9c2019-04-05 15:01:27 +0200687 struct lyxml_context *xml_ctx = (struct lyxml_context *)&parser_ctx;
David Sedlák3017da42019-02-15 09:48:04 +0100688 struct lysp_module *mod_p = NULL;
689 const char *prefix, *name;
690 size_t prefix_len, name_len;
David Sedlák8f7a1172019-06-20 14:42:18 +0200691 struct yin_arg_record *args = NULL;
David Sedlák3b4db242018-10-19 16:11:01 +0200692
David Sedlák3017da42019-02-15 09:48:04 +0100693 /* initialize xml context */
David Sedlákaadab9c2019-04-05 15:01:27 +0200694 memset(&parser_ctx, 0, sizeof parser_ctx);
695 xml_ctx->ctx = ctx;
696 xml_ctx->line = 1;
David Sedláke4889912018-11-02 09:52:40 +0100697
David Sedlák3017da42019-02-15 09:48:04 +0100698 /* check submodule */
David Sedlákaadab9c2019-04-05 15:01:27 +0200699 ret = lyxml_get_element(xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
David Sedlák8f7a1172019-06-20 14:42:18 +0200700 yin_load_attributes(xml_ctx, &data, &args);
David Sedlák3017da42019-02-15 09:48:04 +0100701 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
David Sedlák8f7a1172019-06-20 14:42:18 +0200702 kw = yin_match_keyword(xml_ctx, name, name_len, prefix, prefix_len);
David Sedláke4889912018-11-02 09:52:40 +0100703 if (kw == YANG_SUBMODULE) {
David Sedlák3017da42019-02-15 09:48:04 +0100704 LOGERR(ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
705 ret = LY_EINVAL;
706 goto cleanup;
707 } else if (kw != YANG_MODULE) {
David Sedlákb3077192019-06-19 10:55:37 +0200708 LOGVAL_PARSER(xml_ctx, LYVE_SYNTAX, "Invalid keyword \"%s\", expected \"module\" or \"submodule\".",
David Sedlák79e50cb2019-06-05 16:33:09 +0200709 ly_stmt2str(kw));
David Sedlák3017da42019-02-15 09:48:04 +0100710 ret = LY_EVALID;
711 goto cleanup;
David Sedláke4889912018-11-02 09:52:40 +0100712 }
713
David Sedlák3017da42019-02-15 09:48:04 +0100714 /* allocate module */
715 mod_p = calloc(1, sizeof *mod_p);
716 LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx), cleanup);
717 mod_p->mod = mod;
718 mod_p->parsing = 1;
David Sedláke4889912018-11-02 09:52:40 +0100719
David Sedlák3017da42019-02-15 09:48:04 +0100720 /* parser module substatements */
David Sedlák8f7a1172019-06-20 14:42:18 +0200721 ret = yin_parse_mod(xml_ctx, &args, &data, &mod_p);
David Sedlák3017da42019-02-15 09:48:04 +0100722 LY_CHECK_GOTO(ret, cleanup);
David Sedlák2e411422018-12-17 02:35:39 +0100723
David Sedlák3017da42019-02-15 09:48:04 +0100724 mod_p->parsing = 0;
725 mod->parsed = mod_p;
726
727cleanup:
David Sedlák8f7a1172019-06-20 14:42:18 +0200728 if (ret != LY_SUCCESS) {
David Sedlák3017da42019-02-15 09:48:04 +0100729 lysp_module_free(mod_p);
730 }
David Sedlák8f7a1172019-06-20 14:42:18 +0200731 LY_ARRAY_FREE(args);
David Sedlákaadab9c2019-04-05 15:01:27 +0200732 lyxml_context_clear(xml_ctx);
David Sedlák2e411422018-12-17 02:35:39 +0100733 return ret;
David Sedlák3b4db242018-10-19 16:11:01 +0200734}